summaryrefslogtreecommitdiff
path: root/atmel-samd/common-hal/nativeio
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2016-12-06 18:39:18 -0800
committerScott Shawcroft <scott.shawcroft@gmail.com>2016-12-12 15:11:25 -0800
commit3972bc19c7c788d5c587156aba39ea659decc420 (patch)
treeecfe27d509b206b39f733a71857625d165502164 /atmel-samd/common-hal/nativeio
parentcd09726904dfb70fbfe6ed8de648737bc34ab37c (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/nativeio')
-rw-r--r--atmel-samd/common-hal/nativeio/TouchIn.c274
-rw-r--r--atmel-samd/common-hal/nativeio/TouchInStub.c46
-rw-r--r--atmel-samd/common-hal/nativeio/types.h13
3 files changed, 333 insertions, 0 deletions
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__