atmel-samd: Improve TouchIn to allow for multiple simultaneous touch pads.
This commit is contained in:
parent
e8db23d241
commit
f48d2df634
|
@ -89,9 +89,9 @@ freq_hop_sel_t selfcap_freq_hops[3u] = {DEF_SELFCAP_HOP_FREQS};
|
||||||
* the elements of this structure. DO NOT modify any of the input values
|
* the elements of this structure. DO NOT modify any of the input values
|
||||||
* directly in this structure.
|
* directly in this structure.
|
||||||
*/
|
*/
|
||||||
static touch_selfcap_config_t selfcap_config = {
|
touch_selfcap_config_t selfcap_config = {
|
||||||
DEF_SELFCAP_NUM_CHANNELS, /* Self Cap number of channels. */
|
0, /* Self Cap number of channels. */
|
||||||
DEF_SELFCAP_NUM_SENSORS, /* Self Cap number of sensors. */
|
0, /* Self Cap number of sensors. */
|
||||||
DEF_SELFCAP_NUM_ROTORS_SLIDERS, /* Self Cap number of rotors and
|
DEF_SELFCAP_NUM_ROTORS_SLIDERS, /* Self Cap number of rotors and
|
||||||
* sliders. */
|
* sliders. */
|
||||||
|
|
||||||
|
@ -181,7 +181,8 @@ touch_config_t touch_config = {
|
||||||
DEF_TOUCH_PTC_ISR_LVL, /* PTC interrupt level. */
|
DEF_TOUCH_PTC_ISR_LVL, /* PTC interrupt level. */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ptc_initialized = false;
|
nativeio_touchin_obj_t *active_touchin_obj[DEF_SELFCAP_NUM_CHANNELS];
|
||||||
|
|
||||||
void common_hal_nativeio_touchin_construct(nativeio_touchin_obj_t* self,
|
void common_hal_nativeio_touchin_construct(nativeio_touchin_obj_t* self,
|
||||||
const mcu_pin_obj_t *pin) {
|
const mcu_pin_obj_t *pin) {
|
||||||
if (!pin->has_touch) {
|
if (!pin->has_touch) {
|
||||||
|
@ -189,50 +190,78 @@ void common_hal_nativeio_touchin_construct(nativeio_touchin_obj_t* self,
|
||||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have touch capabilities", pin->name));
|
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 (selfcap_config.num_channels > 0) {
|
||||||
if (!ptc_initialized) {
|
// Deinit the touch sensor, we're going to reinitialize it.
|
||||||
/* Setup and enable generic clock source for PTC module. */
|
touch_selfcap_sensors_deinit();
|
||||||
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. */
|
// Remove holes in the active list from sensors that may have been
|
||||||
status = touch_selfcap_sensors_init_with_rs_table(&touch_config,
|
// disabled.
|
||||||
PRIV_SELFCAP_RS_TABLE_INIT, PRIV_NM_TABLE_INIT,
|
int first_hole = -1;
|
||||||
PRIV_FREQ_AUTO_TUNE_CHK, PRIV_MOIS_TOLERANCE_CHK);
|
for (int i = 0; i < selfcap_config.num_channels; i++) {
|
||||||
if (status != TOUCH_SUCCESS) {
|
if (active_touchin_obj[i] == NULL && first_hole == -1) {
|
||||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch init failed (%d)", status));
|
first_hole = i;
|
||||||
|
} else if (active_touchin_obj[i] != NULL && first_hole != -1) {
|
||||||
|
active_touchin_obj[first_hole] = active_touchin_obj[i];
|
||||||
|
first_hole = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ptc_initialized = true;
|
if (first_hole > -1) {
|
||||||
}
|
selfcap_config.num_channels = first_hole;
|
||||||
// Map Y line to channel. Boards can switch the order.
|
selfcap_config.num_sensors = first_hole;
|
||||||
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));
|
// Add our sensor to the end of the list.
|
||||||
}
|
self->pin = pin;
|
||||||
status = touch_selfcap_sensor_config(SENSOR_TYPE_KEY, channel, channel,
|
selfcap_y_nodes[selfcap_config.num_channels++] = Y(pin->touch_y_line);
|
||||||
NO_AKS_GROUP, 10u, HYST_25, RES_8_BIT, &self->sensor_id);
|
active_touchin_obj[selfcap_config.num_sensors++] = self;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
touch_ret_t status;
|
||||||
|
/* 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) {
|
if (status != TOUCH_SUCCESS) {
|
||||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch pad config failed (%d)", status));
|
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch init failed (%d)", status));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < selfcap_config.num_channels; i++) {
|
||||||
|
status = touch_selfcap_sensor_config(SENSOR_TYPE_KEY, i, i,
|
||||||
|
NO_AKS_GROUP, 10u, HYST_25, RES_8_BIT, &active_touchin_obj[i]->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);
|
status = touch_selfcap_sensors_calibrate(AUTO_TUNE_RSEL);
|
||||||
if (status != TOUCH_SUCCESS) {
|
if (status != TOUCH_SUCCESS) {
|
||||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch pad calibration failed (%d)", status));
|
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Touch pad calibration failed (%d)", status));
|
||||||
}
|
}
|
||||||
|
|
||||||
self->pin = pin;
|
// Run a measurement to get calibrated.
|
||||||
|
common_hal_nativeio_touchin_get_value(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This may get called twice, once on exit or deinit and once from the finaliser
|
||||||
|
// (__del__). We need the finaliser to reduce the chance of us writing to memory
|
||||||
|
// we no longer own because we keep track of Python pointers in active_touchin_obj.
|
||||||
void common_hal_nativeio_touchin_deinit(nativeio_touchin_obj_t* self) {
|
void common_hal_nativeio_touchin_deinit(nativeio_touchin_obj_t* self) {
|
||||||
touch_selfcap_sensor_disable(self->sensor_id);
|
touch_selfcap_sensor_disable(self->sensor_id);
|
||||||
|
// Remove ourselves from the list of active objects. We don't change the
|
||||||
|
// selfcap settings at all because we don't want to reinit now. Instead,
|
||||||
|
// we'll collect blank spots later on reinit.
|
||||||
|
for (int i = 0; i < DEF_SELFCAP_NUM_CHANNELS; i++) {
|
||||||
|
if (active_touchin_obj[i] == self) {
|
||||||
|
active_touchin_obj[i] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile bool touch_read_ready = false;
|
volatile bool touch_read_ready = false;
|
||||||
|
@ -263,6 +292,9 @@ bool common_hal_nativeio_touchin_get_value(nativeio_touchin_obj_t *self) {
|
||||||
|
|
||||||
while(!touch_read_ready && ticks_ms - start_ticks < 1000) {
|
while(!touch_read_ready && ticks_ms - start_ticks < 1000) {
|
||||||
// wait
|
// wait
|
||||||
|
#ifdef MICROPY_VM_HOOK_LOOP
|
||||||
|
MICROPY_VM_HOOK_LOOP
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,5 +302,5 @@ bool common_hal_nativeio_touchin_get_value(nativeio_touchin_obj_t *self) {
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch read failed"));
|
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;
|
return (p_selfcap_measure_data->p_sensor_states[self->sensor_id / 8] & (1 << (self->sensor_id % 8))) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
#include "asf/sam0/drivers/system/system.h"
|
#include "asf/sam0/drivers/system/system.h"
|
||||||
#include <board.h>
|
#include <board.h>
|
||||||
|
|
||||||
#ifdef SPI_FLASH_SECTOR_SIZE
|
#ifdef EXPRESS_BOARD
|
||||||
|
#include "common-hal/nativeio/types.h"
|
||||||
#include "QTouch/touch_api_ptc.h"
|
#include "QTouch/touch_api_ptc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -128,7 +129,10 @@ void reset_mp(void) {
|
||||||
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool ptc_initialized;
|
#ifdef EXPRESS_BOARD
|
||||||
|
extern nativeio_touchin_obj_t *active_touchin_obj[DEF_SELFCAP_NUM_CHANNELS];
|
||||||
|
extern touch_selfcap_config_t selfcap_config;
|
||||||
|
#endif
|
||||||
void reset_samd21(void) {
|
void reset_samd21(void) {
|
||||||
// Reset all SERCOMs except the one being used by the SPI flash.
|
// Reset all SERCOMs except the one being used by the SPI flash.
|
||||||
Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
|
Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
|
||||||
|
@ -146,9 +150,13 @@ void reset_samd21(void) {
|
||||||
sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
|
sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPI_FLASH_SECTOR_SIZE
|
#ifdef EXPRESS_BOARD
|
||||||
touch_selfcap_sensors_deinit();
|
touch_selfcap_sensors_deinit();
|
||||||
ptc_initialized = false;
|
for (int i = 0; i < selfcap_config.num_channels; i++) {
|
||||||
|
active_touchin_obj[i] = NULL;
|
||||||
|
}
|
||||||
|
selfcap_config.num_channels = 0;
|
||||||
|
selfcap_config.num_sensors = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct system_pinmux_config config;
|
struct system_pinmux_config config;
|
||||||
|
|
|
@ -132,6 +132,7 @@ extern const struct _mp_obj_module_t samd_module;
|
||||||
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
|
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
|
||||||
#define EXTRA_BUILTIN_MODULES \
|
#define EXTRA_BUILTIN_MODULES \
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }
|
||||||
|
#define EXPRESS_BOARD
|
||||||
#else
|
#else
|
||||||
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
|
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
|
||||||
#define EXTRA_BUILTIN_MODULES
|
#define EXTRA_BUILTIN_MODULES
|
||||||
|
|
|
@ -126,6 +126,7 @@ mp_obj_property_t nativeio_touchin_value_obj = {
|
||||||
STATIC const mp_rom_map_elem_t nativeio_touchin_locals_dict_table[] = {
|
STATIC const mp_rom_map_elem_t nativeio_touchin_locals_dict_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_touchin___enter___obj) },
|
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_touchin___enter___obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_touchin___exit___obj) },
|
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_touchin___exit___obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&nativeio_touchin_deinit_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_touchin_deinit_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_touchin_deinit_obj) },
|
||||||
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), MP_ROM_PTR(&nativeio_touchin_value_obj)},
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), MP_ROM_PTR(&nativeio_touchin_value_obj)},
|
||||||
|
|
Loading…
Reference in New Issue