diff --git a/src/codal_app/microbithal.cpp b/src/codal_app/microbithal.cpp index 249606b..258e4de 100644 --- a/src/codal_app/microbithal.cpp +++ b/src/codal_app/microbithal.cpp @@ -78,6 +78,7 @@ static const PullMode pin_pull_mode_mapping[] = { }; static uint8_t pin_pull_state[32 + 6]; +static uint16_t touch_state[4]; static uint16_t button_state[2]; extern "C" { @@ -202,11 +203,32 @@ void microbit_hal_pin_write_analog_u10(int pin, int value) { pin_obj[pin]->setAnalogValue(value); } -int microbit_hal_pin_is_touched(int pin) { - if (pin == MICROBIT_HAL_PIN_LOGO) { - // For touch on the logo pin, delegate to the TouchButton instance. - return uBit.logo.buttonActive(); +int microbit_hal_pin_touch_state(int pin, int *was_touched, int *num_touches) { + if (was_touched != NULL || num_touches != NULL) { + int pin_state_index; + if (pin == MICROBIT_HAL_PIN_LOGO) { + pin_state_index = 3; + } else { + pin_state_index = pin; // pin0/1/2 + } + int t = pin_obj[pin]->wasTouched(); + uint16_t state = touch_state[pin_state_index]; + if (t) { + // Update state based on number of touches since last call. + // Low bit is "was touched at least once", upper bits are "number of touches". + state = (state + (t << 1)) | 1; + } + if (was_touched != NULL) { + *was_touched = state & 1; + state &= ~1; + } + if (num_touches != NULL) { + *num_touches = state >> 1; + state &= 1; + } + touch_state[pin_state_index] = state; } + return pin_obj[pin]->isTouched(); } diff --git a/src/codal_app/microbithal.h b/src/codal_app/microbithal.h index e8840dc..ca137f3 100644 --- a/src/codal_app/microbithal.h +++ b/src/codal_app/microbithal.h @@ -123,7 +123,7 @@ int microbit_hal_pin_read(int pin); void microbit_hal_pin_write(int pin, int value); int microbit_hal_pin_read_analog_u10(int pin); void microbit_hal_pin_write_analog_u10(int pin, int value); -int microbit_hal_pin_is_touched(int pin); +int microbit_hal_pin_touch_state(int pin, int *was_touched, int *num_touches); void microbit_hal_pin_write_ws2812(int pin, const uint8_t *buf, size_t len); int microbit_hal_i2c_init(int scl, int sda, int freq); diff --git a/src/codal_port/microbit_pin.c b/src/codal_port/microbit_pin.c index 4c9e79b..9e2712a 100644 --- a/src/codal_port/microbit_pin.c +++ b/src/codal_port/microbit_pin.c @@ -155,17 +155,35 @@ mp_obj_t microbit_pin_get_analog_period_microseconds(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_get_analog_period_microseconds_obj, microbit_pin_get_analog_period_microseconds); -mp_obj_t microbit_pin_is_touched(mp_obj_t self_in) { +static int microbit_pin_get_touch_state(mp_obj_t self_in, int *was_touched, int *num_touches) { microbit_pin_obj_t *self = (microbit_pin_obj_t*)self_in; const microbit_pinmode_t *mode = microbit_pin_get_mode(self); if (mode != microbit_pin_mode_touch && mode != microbit_pin_mode_button) { microbit_obj_pin_acquire(self, microbit_pin_mode_touch); // set NO_PULL on pin } - return mp_obj_new_bool(microbit_hal_pin_is_touched(self->name)); + return microbit_hal_pin_touch_state(self->name, was_touched, num_touches); +} + +mp_obj_t microbit_pin_is_touched(mp_obj_t self_in) { + return mp_obj_new_bool(microbit_pin_get_touch_state(self_in, NULL, NULL)); } MP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_is_touched_obj, microbit_pin_is_touched); +mp_obj_t microbit_pin_was_touched(mp_obj_t self_in) { + int was_touched; + microbit_pin_get_touch_state(self_in, &was_touched, NULL); + return mp_obj_new_bool(was_touched); +} +MP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_was_touched_obj, microbit_pin_was_touched); + +mp_obj_t microbit_pin_get_touches(mp_obj_t self_in) { + int num_touches; + microbit_pin_get_touch_state(self_in, NULL, &num_touches); + return MP_OBJ_NEW_SMALL_INT(num_touches); +} +MP_DEFINE_CONST_FUN_OBJ_1(microbit_pin_get_touches_obj, microbit_pin_get_touches); + mp_obj_t microbit_pin_set_touch_mode(mp_obj_t self_in, mp_obj_t mode_in) { microbit_pin_obj_t *self = (microbit_pin_obj_t *)self_in; const microbit_pinmode_t *mode = microbit_pin_get_mode(self); @@ -238,6 +256,8 @@ STATIC const mp_rom_map_elem_t microbit_touch_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_analog_period_microseconds), MP_ROM_PTR(µbit_pin_set_analog_period_microseconds_obj) }, { MP_ROM_QSTR(MP_QSTR_get_analog_period_microseconds), MP_ROM_PTR(µbit_pin_get_analog_period_microseconds_obj) }, { MP_ROM_QSTR(MP_QSTR_is_touched), MP_ROM_PTR(µbit_pin_is_touched_obj) }, + { MP_ROM_QSTR(MP_QSTR_was_touched), MP_ROM_PTR(µbit_pin_was_touched_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_touches), MP_ROM_PTR(µbit_pin_get_touches_obj) }, { MP_ROM_QSTR(MP_QSTR_get_pull), MP_ROM_PTR(µbit_pin_get_pull_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pull), MP_ROM_PTR(µbit_pin_set_pull_obj) }, { MP_ROM_QSTR(MP_QSTR_get_mode), MP_ROM_PTR(µbit_pin_get_mode_obj) }, @@ -256,6 +276,8 @@ MP_DEFINE_CONST_OBJ_TYPE( STATIC const mp_rom_map_elem_t microbit_touch_only_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_is_touched), MP_ROM_PTR(µbit_pin_is_touched_obj) }, + { MP_ROM_QSTR(MP_QSTR_was_touched), MP_ROM_PTR(µbit_pin_was_touched_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_touches), MP_ROM_PTR(µbit_pin_get_touches_obj) }, { MP_ROM_QSTR(MP_QSTR_set_touch_mode), MP_ROM_PTR(µbit_pin_set_touch_mode_obj) }, TOUCH_CONSTANTS, };