diff --git a/platform/drivers/keyboard/keyboard_ttwrplus.c b/platform/drivers/keyboard/keyboard_ttwrplus.c new file mode 100644 index 00000000..ac82f833 --- /dev/null +++ b/platform/drivers/keyboard/keyboard_ttwrplus.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#include +#include +#include +#include + +static const struct device *const buttons_dev = DEVICE_DT_GET(DT_NODELABEL(buttons)); + +static int8_t old_pos = 0; +static keyboard_t keys = 0; + + +static void gpio_keys_cb_handler(struct input_event *evt) +{ + uint32_t keyCode = 0; + + // Map betweek Zephyr keys and OpenRTX keys + switch(evt->code) + { + case INPUT_KEY_VOLUMEDOWN: + keyCode = KEY_DOWN; + break; + + case INPUT_BTN_START: + keyCode = KEY_ENTER; + break; + + case INPUT_BTN_SELECT: + keyCode = KEY_ESC; + break; + } + + if(evt->value != 0) + keys |= keyCode; + else + keys &= ~keyCode; +} + +INPUT_LISTENER_CB_DEFINE(buttons_dev, gpio_keys_cb_handler); + + +void kbd_init() +{ + // Initialise old position + old_pos = platform_getChSelector(); +} + +void kbd_terminate() +{ +} + +keyboard_t kbd_getKeys() +{ + keys &= ~KNOB_LEFT; + keys &= ~KNOB_RIGHT; + + // Read rotary encoder to send KNOB_LEFT and KNOB_RIGHT events + int8_t new_pos = platform_getChSelector(); + if (old_pos != new_pos) + { + int8_t delta = new_pos - old_pos; + + // Normal case: handle up/down by looking at the pulse difference + if(delta > 0) + keys |= KNOB_LEFT; + else if (delta < 0) + keys |= KNOB_RIGHT; + + // Corner case 1: rollover from negative (old) to positive (new) value. + // Delta is positive but it counts as a down key. + if((old_pos < 0) && (new_pos > 0)) + { + keys &= ~KNOB_LEFT; + keys |= KNOB_RIGHT; + } + + // Corner case 2: rollover from positive (old) to negative (new) value. + // Delta is negative but it counts as an up key. + if((old_pos > 0) && (new_pos < 0)) + { + keys &= ~KNOB_RIGHT; + keys |= KNOB_LEFT; + } + + old_pos = new_pos; + } + + return keys; +} diff --git a/platform/targets/ttwrplus/CMakeLists.txt b/platform/targets/ttwrplus/CMakeLists.txt index 6d8206ad..27432980 100644 --- a/platform/targets/ttwrplus/CMakeLists.txt +++ b/platform/targets/ttwrplus/CMakeLists.txt @@ -12,10 +12,10 @@ target_sources(app ${OPENRTX_ROOT}/platform/targets/ttwrplus/platform.c ${OPENRTX_ROOT}/platform/drivers/display/SH1106_ttwrplus.c + ${OPENRTX_ROOT}/platform/drivers/keyboard/keyboard_ttwrplus.c ${OPENRTX_ROOT}/platform/drivers/stubs/audio_stub.c ${OPENRTX_ROOT}/platform/drivers/stubs/cps_io_stub.c - ${OPENRTX_ROOT}/platform/drivers/stubs/keyboard_stub.c ${OPENRTX_ROOT}/platform/drivers/stubs/nvmem_stub.c ${OPENRTX_ROOT}/platform/drivers/stubs/radio_stub.c ) diff --git a/platform/targets/ttwrplus/platform.c b/platform/targets/ttwrplus/platform.c index efc98794..b70e9888 100644 --- a/platform/targets/ttwrplus/platform.c +++ b/platform/targets/ttwrplus/platform.c @@ -20,6 +20,14 @@ #include #include +#include +#include + +#define BUTTON_PTT_NODE DT_NODELABEL(button_ptt) + +static const struct gpio_dt_spec button_ptt = GPIO_DT_SPEC_GET_OR(BUTTON_PTT_NODE, gpios, {0}); +static const struct device *const qdec_dev = DEVICE_DT_GET(DT_ALIAS(qdec0)); + static const hwInfo_t hwInfo = { .uhf_maxFreq = 430, @@ -31,6 +39,20 @@ static const hwInfo_t hwInfo = void platform_init() { + // Setup GPIO for PTT and rotary encoder + if(gpio_is_ready_dt(&button_ptt) == false) + printk("Error: button device %s is not ready\n", button_ptt.port->name); + + int ret = gpio_pin_configure_dt(&button_ptt, GPIO_INPUT); + if (ret != 0) + { + printk("Error %d: failed to configure %s pin %d\n", ret, + button_ptt.port->name, button_ptt.pin); + } + + // Rotary encoder is read using hardware pulse counter + if(device_is_ready(qdec_dev) == false) + printk("Qdec device is not ready\n"); } void platform_terminate() @@ -54,12 +76,29 @@ uint8_t platform_getVolumeLevel() int8_t platform_getChSelector() { - return 0; + int rc = sensor_sample_fetch(qdec_dev); + if (rc != 0) + { + printk("Failed to fetch sample (%d)\n", rc); + return 0; + } + + struct sensor_value val; + rc = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &val); + if (rc != 0) + { + printk("Failed to get data (%d)\n", rc); + return 0; + } + + // The esp32-pcnt sensor returns a signed 16-bit value: we remap it into a + // signed 8-bit one. + return (int8_t) val.val1; } bool platform_getPttStatus() { - return false; + return gpio_pin_get_dt(&button_ptt); } bool platform_pwrButtonStatus() @@ -84,6 +123,7 @@ void platform_beepStart(uint16_t freq) void platform_beepStop() { + ; } const hwInfo_t *platform_getHwInfo() diff --git a/platform/targets/ttwrplus/ttwrplus.dts b/platform/targets/ttwrplus/ttwrplus.dts index 8ff7a232..d1f1faf9 100644 --- a/platform/targets/ttwrplus/ttwrplus.dts +++ b/platform/targets/ttwrplus/ttwrplus.dts @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,8 @@ aliases { i2c-0 = &i2c0; watchdog0 = &wdt0; + radio = &uart0; + qdec0 = &pcnt; }; chosen { @@ -26,23 +29,27 @@ zephyr,display = &ssd1306; }; - aliases { - radio = &uart0; - }; + buttons: buttons { + compatible = "zephyr,gpio-keys"; - buttons { - compatible = "gpio-keys"; - - sw_boot: button_0 { + button_boot: button_0 { gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; + zephyr,code = ; label = "BOOT Button"; }; - sw_user: button_1 { - gpios = <&gpio0 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; - label = "USER Button"; + button_user: button_1 { + gpios = <&gpio0 21 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "Encoder Button"; }; - }; + + button_ptt: button_2 { + gpios = <&gpio0 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "PTT Button"; + }; + }; }; &cpu0 { @@ -88,6 +95,27 @@ }; }; +&pcnt { + pinctrl-0 = <&pcnt_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + unit0@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + filter = <100>; + channelA@0 { + reg = <0>; + sig-pos-mode = <2>; + sig-neg-mode = <1>; + ctrl-h-mode = <0>; + ctrl-l-mode = <1>; + }; + }; +}; + &timer0 { status = "disabled"; }; @@ -133,6 +161,14 @@ output-high; }; }; + + pcnt_default: pcnt_default { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; }; &flash0 { diff --git a/platform/targets/ttwrplus/ttwrplus_defconfig b/platform/targets/ttwrplus/ttwrplus_defconfig index 74021a02..cdcb1c52 100644 --- a/platform/targets/ttwrplus/ttwrplus_defconfig +++ b/platform/targets/ttwrplus/ttwrplus_defconfig @@ -10,3 +10,5 @@ CONFIG_DYNAMIC_THREAD_PREFER_POOL=y CONFIG_DYNAMIC_THREAD_POOL_SIZE=4 CONFIG_COMMON_LIBC_MALLOC=y CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=131072 +CONFIG_INPUT=y +CONFIG_SENSOR=y