diff options
| author | Scott Shawcroft <scott.shawcroft@gmail.com> | 2016-12-06 18:39:18 -0800 |
|---|---|---|
| committer | Scott Shawcroft <scott.shawcroft@gmail.com> | 2016-12-12 15:11:25 -0800 |
| commit | 3972bc19c7c788d5c587156aba39ea659decc420 (patch) | |
| tree | ecfe27d509b206b39f733a71857625d165502164 /atmel-samd/common-hal | |
| parent | cd09726904dfb70fbfe6ed8de648737bc34ab37c (diff) | |
atmel-samd: Basic capacitive touch button support.
Currently only works on a single channel and is only enabled for boards with
SPI flash. Only really designed for hardware testing at this point.
Diffstat (limited to 'atmel-samd/common-hal')
| -rw-r--r-- | atmel-samd/common-hal/microcontroller/types.h | 8 | ||||
| -rw-r--r-- | atmel-samd/common-hal/nativeio/TouchIn.c | 274 | ||||
| -rw-r--r-- | atmel-samd/common-hal/nativeio/TouchInStub.c | 46 | ||||
| -rw-r--r-- | atmel-samd/common-hal/nativeio/types.h | 13 |
4 files changed, 338 insertions, 3 deletions
diff --git a/atmel-samd/common-hal/microcontroller/types.h b/atmel-samd/common-hal/microcontroller/types.h index b76700c93..96aea6a07 100644 --- a/atmel-samd/common-hal/microcontroller/types.h +++ b/atmel-samd/common-hal/microcontroller/types.h @@ -61,9 +61,11 @@ typedef struct { uint8_t pin; bool has_adc:1; enum adc_positive_input adc_input:7; - pin_timer_t primary_timer; // Mux E - pin_timer_t secondary_timer; // Mux F - pin_sercom_t sercom[NUM_SERCOMS_PER_PIN]; // Mux C and D + bool has_touch:1; + uint8_t touch_y_line:7; // 0 - 15. Assumed to be Y channel. + pin_timer_t primary_timer; + pin_timer_t secondary_timer; + pin_sercom_t sercom[NUM_SERCOMS_PER_PIN]; } mcu_pin_obj_t; #endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__ diff --git a/atmel-samd/common-hal/nativeio/TouchIn.c b/atmel-samd/common-hal/nativeio/TouchIn.c new file mode 100644 index 000000000..1e7158e22 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/TouchIn.c @@ -0,0 +1,274 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/binary.h" +#include "py/mphal.h" +#include "shared-bindings/nativeio/TouchIn.h" + +#include "tick.h" + +#include "QTouch/touch_api_ptc.h" + +#define DEF_SELFCAP_CAL_SEQ1_COUNT 8 +#define DEF_SELFCAP_CAL_SEQ2_COUNT 4 +#define DEF_SELFCAP_CC_CAL_CLK_PRESCALE_PER_NODE DEF_SELFCAP_CLK_PRESCALE_PER_NODE +#define DEF_SELFCAP_CC_CAL_SENSE_RESISTOR_PER_NODE DEF_SELFCAP_SENSE_RESISTOR_PER_NODE +#define DEF_SELFCAP_QUICK_REBURST_ENABLE 1u + +/** + * Mutual Cap sensors measured data pointer. + * Note: This pointer is initialized by the QTouch library once the + * touch_mutlcap_sensors_init API is called. */ +touch_measure_data_t *p_mutlcap_measure_data = NULL; + +/** + * Self Cap sensors measured data pointer. + * Note: This pointer is initialized by the QTouch library once the + * touch_selfcap_sensors_init API is called. */ +touch_measure_data_t *p_selfcap_measure_data = NULL; + + +/** + * Self Cap sensors data block provided as input to Touch library. + */ +static uint8_t selfcap_data_blk[PRIV_SELFCAP_DATA_BLK_SIZE]; + +/** + * Self Cap sensors Pins Info. + */ + +uint32_t selfcap_y_nodes[DEF_SELFCAP_NUM_CHANNELS] = {DEF_SELFCAP_LINES}; + +filter_level_t selfcap_filter_level_per_node[DEF_SELFCAP_NUM_CHANNELS] = {DEF_SELFCAP_FILTER_LEVEL_PER_NODE}; + +uint8_t selfcap_auto_os_per_node[DEF_SELFCAP_NUM_CHANNELS]= {DEF_SELFCAP_AUTO_OS_PER_NODE}; + +gain_t selfcap_gain_per_node[DEF_SELFCAP_NUM_CHANNELS] = {DEF_SELFCAP_GAIN_PER_NODE}; + +rsel_val_t selfcap_resistor_per_node[DEF_SELFCAP_NUM_CHANNELS] = {DEF_SELFCAP_SENSE_RESISTOR_PER_NODE}; + +prsc_div_sel_t selfcap_prsc_per_node[DEF_SELFCAP_NUM_CHANNELS] = {DEF_SELFCAP_CLK_PRESCALE_PER_NODE}; + +prsc_div_sel_t selfcap_boot_prsc_per_node[DEF_SELFCAP_NUM_CHANNELS] = {DEF_SELFCAP_CC_CAL_CLK_PRESCALE_PER_NODE}; + +rsel_val_t selfcap_boot_resistor_per_node[DEF_SELFCAP_NUM_CHANNELS] = { DEF_SELFCAP_CC_CAL_SENSE_RESISTOR_PER_NODE}; + +freq_hop_sel_t selfcap_freq_hops[3u] = {DEF_SELFCAP_HOP_FREQS}; + +/** + * Self Cap Configuration structure provided as input to Touch Library. + * + * Note: Use the touch.h configuration header file to fill in + * the elements of this structure. DO NOT modify any of the input values + * directly in this structure. + */ +static touch_selfcap_config_t selfcap_config = { + DEF_SELFCAP_NUM_CHANNELS, /* Self Cap number of channels. */ + DEF_SELFCAP_NUM_SENSORS, /* Self Cap number of sensors. */ + DEF_SELFCAP_NUM_ROTORS_SLIDERS, /* Self Cap number of rotors and + * sliders. */ + + /* Self Cap GLOBAL SENSOR CONFIGURATION INFO. */ + { + DEF_SELFCAP_DI, /* uint8_t di; Sensor detect + * integration (DI) limit. */ + + /* Interchanging Negative and Positive Drift rate, since Signal + * increases on Touch. */ + DEF_SELFCAP_ATCH_DRIFT_RATE, /* uint8_t neg_drift_rate; + * Sensor + * negative drift rate. */ + DEF_SELFCAP_TCH_DRIFT_RATE, /* uint8_t pos_drift_rate; + * Sensor + * positive drift rate. */ + DEF_SELFCAP_MAX_ON_DURATION, /* uint8_t max_on_duration; + * Sensor + * maximum on duration. */ + DEF_SELFCAP_DRIFT_HOLD_TIME, /* uint8_t drift_hold_time; + * Sensor + * drift hold time. */ + DEF_SELFCAP_ATCH_RECAL_DELAY, /* uint8_t pos_recal_delay; + * Sensor positive recalibration + * delay. */ + + DEF_SELFCAP_CAL_SEQ1_COUNT, + DEF_SELFCAP_CAL_SEQ2_COUNT, + DEF_SELFCAP_ATCH_RECAL_THRESHOLD, /* recal_threshold_t + * recal_threshold; Sensor + * recalibration threshold. */ + DEF_SELFCAP_TOUCH_POSTPROCESS_MODE, + DEF_SELFCAP_AUTO_OS_SIGNAL_STABILITY_LIMIT, + DEF_SELFCAP_FREQ_AUTO_TUNE_SIGNAL_STABILITY_LIMIT, + DEF_SELFCAP_FREQ_AUTO_TUNE_IN_CNT, + DEF_SELFCAP_NOISE_MEAS_SIGNAL_STABILITY_LIMIT, /* signal + *stability */ + DEF_SELFCAP_NOISE_LIMIT, + DEF_SELFCAP_LOCKOUT_SEL, + DEF_SELFCAP_LOCKOUT_CNTDOWN, + #if ((SAMC20) || (SAMC21) || (SAML22)) + DEF_SELF_CAP_CSD_VALUE, + #endif + }, + { + selfcap_gain_per_node, /* Self Cap channel gain setting. */ + DEF_SELFCAP_FREQ_MODE, /* Self Cap noise counter measure + * enable/disable. */ + selfcap_prsc_per_node, + selfcap_resistor_per_node, + selfcap_boot_prsc_per_node, + selfcap_boot_resistor_per_node, + selfcap_freq_hops, + selfcap_filter_level_per_node, /* Self Cap filter level setting. */ + selfcap_auto_os_per_node, /* Self Cap auto oversamples + *setting. */ + }, + selfcap_data_blk, /* Self Cap data block index. */ + PRIV_SELFCAP_DATA_BLK_SIZE, /* Self Cap data block size. */ + selfcap_y_nodes, /* Self Cap channel nodes. */ + DEF_SELFCAP_QUICK_REBURST_ENABLE, + DEF_SELFCAP_FILTER_CALLBACK, /* Self Cap filter callback + * function + * pointer. */ + DEF_SELFCAP_FREQ_AUTO_TUNE_ENABLE, + DEF_SELFCAP_NOISE_MEAS_ENABLE, + DEF_SELFCAP_NOISE_MEAS_BUFFER_CNT, + DEF_SELFCAP_MOIS_TOLERANCE_ENABLE, + DEF_SELFCAP_NUM_MOIS_GROUPS, + DEF_SELFCAP_MOIS_QUICK_REBURST_ENABLE, + DEF_SELFCAP_PTC_GPIO_STATE, + .tlib_feature_list ={ + .lk_chk = DEF_LOCKOUT_FUNC, + .auto_os_init = DEF_AUTO_OS_FUNC,//auto_os_resolve, + .auto_tune_init = DEF_SELF_AUTO_TUNE_FUNC,// self_auto_tuning + .enable_aks = DEF_AKS_FUNC, /*AKS grouping function */ + } +}; + +/** + * Touch Library input configuration structure. + */ +touch_config_t touch_config = { + NULL, + &selfcap_config, /* Pointer to Self Cap configuration + * structure. */ + DEF_TOUCH_PTC_ISR_LVL, /* PTC interrupt level. */ +}; + +bool ptc_initialized = false; +void common_hal_nativeio_touchin_construct(nativeio_touchin_obj_t* self, + const mcu_pin_obj_t *pin) { + if (!pin->has_touch) { + // No ADC function on that pin + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have touch capabilities", pin->name)); + } + + touch_ret_t status; + if (!ptc_initialized) { + /* Setup and enable generic clock source for PTC module. */ + struct system_gclk_chan_config gclk_chan_conf; + system_gclk_chan_get_config_defaults(&gclk_chan_conf); + gclk_chan_conf.source_generator = GCLK_GENERATOR_1; + system_gclk_chan_set_config(PTC_GCLK_ID, &gclk_chan_conf); + system_gclk_chan_enable(PTC_GCLK_ID); + system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_PTC); + + /* Initialize touch library for Self Cap operation. */ + status = touch_selfcap_sensors_init_with_rs_table(&touch_config, + PRIV_SELFCAP_RS_TABLE_INIT, PRIV_NM_TABLE_INIT, + PRIV_FREQ_AUTO_TUNE_CHK, PRIV_MOIS_TOLERANCE_CHK); + if (status != TOUCH_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch init failed (%d)", status)); + } + ptc_initialized = true; + } + // Map Y line to channel. Boards can switch the order. + int channel; + for (channel = 0; channel < DEF_SELFCAP_NUM_CHANNELS; channel++) { + if (selfcap_y_nodes[channel] == Y(pin->touch_y_line)) { + break; + } + } + if (channel == DEF_SELFCAP_NUM_CHANNELS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin %q on this board does not have touch capabilities", pin->name)); + } + status = touch_selfcap_sensor_config(SENSOR_TYPE_KEY, channel, channel, + NO_AKS_GROUP, 10u, HYST_25, RES_8_BIT, &self->sensor_id); + if (status != TOUCH_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch pad config failed (%d)", status)); + } + status = touch_selfcap_sensors_calibrate(AUTO_TUNE_RSEL); + if (status != TOUCH_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch pad calibration failed (%d)", status)); + } + + self->pin = pin; +} + +void common_hal_nativeio_touchin_deinit(nativeio_touchin_obj_t* self) { + touch_selfcap_sensor_disable(self->sensor_id); +} + +volatile bool touch_read_ready = false; +volatile touch_acq_status_t touch_acq_status; + +void touch_selfcap_measure_complete_callback(void) +{ + touch_read_ready = true; + touch_acq_status = p_selfcap_measure_data->acq_status; +} + +bool common_hal_nativeio_touchin_get_value(nativeio_touchin_obj_t *self) { + if (p_selfcap_measure_data->acq_status & TOUCH_CC_CALIB_ERROR) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch calibration error")); + } + touch_acq_status = TOUCH_BURST_AGAIN; + uint64_t start_ticks = ticks_ms; + while((touch_acq_status & TOUCH_BURST_AGAIN) && ticks_ms - start_ticks < 1000) { + touch_read_ready = false; + touch_ret_t touch_ret = touch_selfcap_sensors_measure( + ticks_ms, + NORMAL_ACQ_MODE, + touch_selfcap_measure_complete_callback); + + if (touch_ret != TOUCH_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch measure failed")); + } + + while(!touch_read_ready && ticks_ms - start_ticks < 1000) { + // wait + } + } + + if (touch_acq_status & TOUCH_BURST_AGAIN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch read failed")); + } + + return (p_selfcap_measure_data->p_sensor_states[self->sensor_id / 8] & (1 << (self->sensor_id % 8))) == 1; +} diff --git a/atmel-samd/common-hal/nativeio/TouchInStub.c b/atmel-samd/common-hal/nativeio/TouchInStub.c new file mode 100644 index 000000000..491e93677 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/TouchInStub.c @@ -0,0 +1,46 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/binary.h" +#include "py/mphal.h" +#include "shared-bindings/nativeio/TouchIn.h" + +void common_hal_nativeio_touchin_construct(nativeio_touchin_obj_t* self, + const mcu_pin_obj_t *pin) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "No room in flash for capacitive touch hardware support.")); +} + +void common_hal_nativeio_touchin_deinit(nativeio_touchin_obj_t* self) { +} + +bool common_hal_nativeio_touchin_get_value(nativeio_touchin_obj_t *self) { + return false; +} diff --git a/atmel-samd/common-hal/nativeio/types.h b/atmel-samd/common-hal/nativeio/types.h index 0a34fe209..365345a2e 100644 --- a/atmel-samd/common-hal/nativeio/types.h +++ b/atmel-samd/common-hal/nativeio/types.h @@ -44,6 +44,10 @@ #include "asf/sam0/drivers/sercom/spi/spi.h" #include "asf/sam0/drivers/tc/tc.h" #include "asf/sam0/drivers/tcc/tcc.h" +// Only support TouchIn when external SPI flash is used. +#ifdef SPI_FLASH_SECTOR_SIZE +#include "QTouch/touch_api_ptc.h" +#endif #include "py/obj.h" @@ -90,4 +94,13 @@ typedef struct { struct tcc_module tcc_instance; } nativeio_pwmout_obj_t; +typedef struct { + mp_obj_base_t base; + // Only support TouchIn when external SPI flash is used. + #ifdef SPI_FLASH_SECTOR_SIZE + const mcu_pin_obj_t * pin; + sensor_id_t sensor_id; + #endif +} nativeio_touchin_obj_t; + #endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ |
