ttwrplus: add support for keys using Zephyr bindings

Zephyr already provides button support based on gpios. We are mapping
Zephyr keycodes to OpenRTX therefore future targets will only need to
configure their devicetrees to have button support.

Rotary encoder readout leverages the hardware pulse counter. PTT in
this device is also bound to KEY_ESC, that matched the behaviour
observed in many commercial radios.

TG-553
pull/193/head
Niccolò Izzo 2023-07-30 12:14:20 +02:00 zatwierdzone przez Silvano Seva
rodzic 9a445f3b31
commit df853c8527
5 zmienionych plików z 200 dodań i 14 usunięć

Wyświetl plik

@ -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 <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <zephyr/input/input.h>
#include <interfaces/keyboard.h>
#include <interfaces/platform.h>
#include <hwconfig.h>
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;
}

Wyświetl plik

@ -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
)

Wyświetl plik

@ -20,6 +20,14 @@
#include <interfaces/platform.h>
#include <hwconfig.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/sensor.h>
#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()

Wyświetl plik

@ -6,6 +6,7 @@
#include <espressif/esp32s3/esp32s3_wroom_n16r8.dtsi>
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
#include <dt-bindings/pinctrl/esp32s3-pinctrl.h>
#include <dt-bindings/input/input-event-codes.h>
#include <zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h>
#include <zephyr/dt-bindings/led/led.h>
@ -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 = <INPUT_KEY_VOLUMEDOWN>;
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 = <INPUT_BTN_START>;
label = "Encoder Button";
};
};
button_ptt: button_2 {
gpios = <&gpio0 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
zephyr,code = <INPUT_BTN_SELECT>;
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 = <PCNT0_CH0SIG_GPIO46>,
<PCNT0_CH0CTRL_GPIO47>;
bias-pull-up;
};
};
};
&flash0 {

Wyświetl plik

@ -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