diff options
| -rw-r--r-- | shared-bindings/gamepad/GamePad.c | 68 | ||||
| -rw-r--r-- | shared-bindings/gamepad/GamePad.h | 1 | ||||
| -rw-r--r-- | shared-bindings/gamepad/__init__.c | 1 | ||||
| -rw-r--r-- | shared-module/gamepad/GamePad.c | 21 | ||||
| -rw-r--r-- | shared-module/gamepad/GamePad.h | 9 | ||||
| -rw-r--r-- | shared-module/gamepad/__init__.c | 36 |
6 files changed, 119 insertions, 17 deletions
diff --git a/shared-bindings/gamepad/GamePad.c b/shared-bindings/gamepad/GamePad.c index 4458c972f..b211e229d 100644 --- a/shared-bindings/gamepad/GamePad.c +++ b/shared-bindings/gamepad/GamePad.c @@ -35,6 +35,15 @@ #include "supervisor/shared/translate.h" #include "GamePad.h" +digitalio_digitalinout_obj_t *validate_pin(mp_obj_t obj) { + if (!MP_OBJ_IS_TYPE(obj, &digitalio_digitalinout_type)) { + mp_raise_TypeError(translate("expected a DigitalInOut")); + } + digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(obj); + raise_error_if_deinited( + common_hal_digitalio_digitalinout_deinited(pin)); + return pin; +} //| .. currentmodule:: gamepad //| @@ -100,19 +109,52 @@ STATIC mp_obj_t gamepad_make_new(const mp_obj_type_t *type, size_t n_args, mp_raise_TypeError(translate("too many arguments")); } for (size_t i = 0; i < n_args; ++i) { - if (!MP_OBJ_IS_TYPE(args[i], &digitalio_digitalinout_type)) { - mp_raise_TypeError(translate("expected a DigitalInOut")); - } - digitalio_digitalinout_obj_t *pin = MP_OBJ_TO_PTR(args[i]); - raise_error_if_deinited( - common_hal_digitalio_digitalinout_deinited(pin)); + validate_pin(args[i]); + } + if (!MP_STATE_VM(gamepad_singleton)) { + gamepad_obj_t* gamepad_singleton = m_new_obj(gamepad_obj_t); + gamepad_singleton->base.type = &gamepad_type; + MP_STATE_VM(gamepad_singleton) = gc_make_long_lived(gamepad_singleton); } + gamepad_init_pins(n_args, args); + return MP_OBJ_FROM_PTR(MP_STATE_VM(gamepad_singleton)); +} + + +//| .. class:: GamePadShift(data, clock, latch) +//| +//| Initializes button scanning routines. +//| +//| The ``data``, ``clock`` and ``latch`` parameters are ``DigitalInOut`` +//| objects connected to the shift register controlling the buttons. +//| +//| They button presses are accumulated, until the ``get_pressed`` method +//| is called, at which point the button state is cleared, and the new +//| button presses start to be recorded. +//| +STATIC mp_obj_t gamepadshift_make_new(const mp_obj_type_t *type, size_t n_args, + const mp_obj_t *pos_args, mp_map_t *kw_args) { + + enum { ARG_data, ARG_clock, ARG_latch }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ}, + { MP_QSTR_latch, MP_ARG_REQUIRED | MP_ARG_OBJ}, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), + allowed_args, args); + + digitalio_digitalinout_obj_t *data_pin = validate_pin(args[ARG_data].u_obj); + digitalio_digitalinout_obj_t *clock_pin = validate_pin(args[ARG_clock].u_obj); + digitalio_digitalinout_obj_t *latch_pin = validate_pin(args[ARG_latch].u_obj); + if (!MP_STATE_VM(gamepad_singleton)) { gamepad_obj_t* gamepad_singleton = m_new_obj(gamepad_obj_t); gamepad_singleton->base.type = &gamepad_type; MP_STATE_VM(gamepad_singleton) = gc_make_long_lived(gamepad_singleton); } - gamepad_init(n_args, args); + gamepad_init_shift(data_pin, clock_pin, latch_pin); return MP_OBJ_FROM_PTR(MP_STATE_VM(gamepad_singleton)); } @@ -158,3 +200,15 @@ const mp_obj_type_t gamepad_type = { .make_new = gamepad_make_new, .locals_dict = (mp_obj_dict_t*)&gamepad_locals_dict, }; + +STATIC const mp_rom_map_elem_t gamepadshift_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_get_pressed), MP_ROM_PTR(&gamepad_get_pressed_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gamepad_deinit_obj)}, +}; +STATIC MP_DEFINE_CONST_DICT(gamepadshift_locals_dict, gamepadshift_locals_dict_table); +const mp_obj_type_t gamepadshift_type = { + { &mp_type_type }, + .name = MP_QSTR_GamePadShift, + .make_new = gamepadshift_make_new, + .locals_dict = (mp_obj_dict_t*)&gamepadshift_locals_dict, +}; diff --git a/shared-bindings/gamepad/GamePad.h b/shared-bindings/gamepad/GamePad.h index 172c95ace..350331193 100644 --- a/shared-bindings/gamepad/GamePad.h +++ b/shared-bindings/gamepad/GamePad.h @@ -29,5 +29,6 @@ #define MICROPY_INCLUDED_SHARED_BINDINGS_GAMEPAD_GAMEPAD_H extern const mp_obj_type_t gamepad_type; +extern const mp_obj_type_t gamepadshift_type; #endif // MICROPY_INCLUDED_SHARED_BINDINGS_GAMEPAD_GAMEPAD_H diff --git a/shared-bindings/gamepad/__init__.c b/shared-bindings/gamepad/__init__.c index 0c99d0d52..0775d6abf 100644 --- a/shared-bindings/gamepad/__init__.c +++ b/shared-bindings/gamepad/__init__.c @@ -44,6 +44,7 @@ STATIC const mp_rom_map_elem_t gamepad_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gamepad) }, { MP_OBJ_NEW_QSTR(MP_QSTR_GamePad), MP_ROM_PTR(&gamepad_type)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_GamePadShift), MP_ROM_PTR(&gamepadshift_type)}, }; STATIC MP_DEFINE_CONST_DICT(gamepad_module_globals, gamepad_module_globals_table); diff --git a/shared-module/gamepad/GamePad.c b/shared-module/gamepad/GamePad.c index 2c14fa02a..ed574db53 100644 --- a/shared-module/gamepad/GamePad.c +++ b/shared-module/gamepad/GamePad.c @@ -35,7 +35,7 @@ #include "shared-bindings/util.h" -void gamepad_init(size_t n_pins, const mp_obj_t* pins) { +void gamepad_init_pins(size_t n_pins, const mp_obj_t* pins) { gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton); for (size_t i = 0; i < 8; ++i) { gamepad_singleton->pins[i] = NULL; @@ -57,4 +57,23 @@ void gamepad_init(size_t n_pins, const mp_obj_t* pins) { gamepad_singleton->pins[i] = pin; } gamepad_singleton->last = 0; + gamepad_singleton->kind = GAMEPAD_KIND_PINS; +} + +void gamepad_init_shift(digitalio_digitalinout_obj_t *data_pin, + digitalio_digitalinout_obj_t *clock_pin, + digitalio_digitalinout_obj_t *latch_pin) { + gamepad_obj_t* gamepad_singleton = MP_STATE_VM(gamepad_singleton); + + common_hal_digitalio_digitalinout_switch_to_input(data_pin, PULL_NONE); + gamepad_singleton->pins[0] = data_pin; + + common_hal_digitalio_digitalinout_switch_to_output(clock_pin, 0, DRIVE_MODE_PUSH_PULL); + gamepad_singleton->pins[1] = clock_pin; + + common_hal_digitalio_digitalinout_switch_to_output(clock_pin, 1, DRIVE_MODE_PUSH_PULL); + gamepad_singleton->pins[2] = latch_pin; + + gamepad_singleton->last = 0; + gamepad_singleton->kind = GAMEPAD_KIND_PINS; } diff --git a/shared-module/gamepad/GamePad.h b/shared-module/gamepad/GamePad.h index 9fd5c9626..9bc5a711c 100644 --- a/shared-module/gamepad/GamePad.h +++ b/shared-module/gamepad/GamePad.h @@ -37,8 +37,15 @@ typedef struct { volatile uint8_t last; volatile uint8_t pressed; uint8_t pulls; + uint8_t kind; } gamepad_obj_t; -void gamepad_init(size_t n_pins, const mp_obj_t* pins); +#define GAMEPAD_KIND_PINS 0 +#define GAMEPAD_KIND_SHIFT 1 + +void gamepad_init_pins(size_t n_pins, const mp_obj_t* pins); +void gamepad_init_shift(digitalio_digitalinout_obj_t *data_pin, + digitalio_digitalinout_obj_t *clock_pin, + digitalio_digitalinout_obj_t *latch_pin); #endif // MICROPY_INCLUDED_GAMEPAD_GAMEPAD_H diff --git a/shared-module/gamepad/__init__.c b/shared-module/gamepad/__init__.c index 8414ddfbe..c79ee30ba 100644 --- a/shared-module/gamepad/__init__.c +++ b/shared-module/gamepad/__init__.c @@ -40,17 +40,37 @@ void gamepad_tick(void) { } uint8_t gamepad_current = 0; uint8_t bit = 1; - for (int i = 0; i < 8; ++i) { - digitalio_digitalinout_obj_t* pin = gamepad_singleton->pins[i]; - if (!pin) { - break; + switch (gamepad_singleton->kind) { + case GAMEPAD_KIND_PINS: + for (int i = 0; i < 8; ++i) { + digitalio_digitalinout_obj_t* pin = gamepad_singleton->pins[i]; + if (!pin) { + break; + } + if (common_hal_digitalio_digitalinout_get_value(pin)) { + gamepad_current |= bit; + } + bit <<= 1; } - if (common_hal_digitalio_digitalinout_get_value(pin)) { - gamepad_current |= bit; + gamepad_current ^= gamepad_singleton->pulls; + break; + case GAMEPAD_KIND_SHIFT: + bit = 1; + digitalio_digitalinout_obj_t* data_pin = gamepad_singleton->pins[0]; + digitalio_digitalinout_obj_t* clock_pin = gamepad_singleton->pins[1]; + digitalio_digitalinout_obj_t* latch_pin = gamepad_singleton->pins[2]; + common_hal_digitalio_digitalinout_set_value(latch_pin, 0); + for (int i = 0; i < 8; ++i) { + common_hal_digitalio_digitalinout_set_value(clock_pin, 1); + if (common_hal_digitalio_digitalinout_get_value(data_pin)) { + gamepad_current |= bit; + } + bit <<= 1; + common_hal_digitalio_digitalinout_set_value(clock_pin, 0); } - bit <<= 1; + common_hal_digitalio_digitalinout_set_value(latch_pin, 1); + break; } - gamepad_current ^= gamepad_singleton->pulls; gamepad_singleton->pressed |= gamepad_singleton->last & gamepad_current; gamepad_singleton->last = gamepad_current; } |
