kopia lustrzana https://github.com/OpenRTX/OpenRTX
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-553pull/193/head
rodzic
9a445f3b31
commit
df853c8527
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue