OpenRTX/platform/drivers/keyboard/keyboard_ttwrplus.c

128 lines
4.0 KiB
C

/***************************************************************************
* Copyright (C) 2020 - 2025 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"
#include "pmu.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;
// Defined in ttwrplus/platform.c to implement volume control
extern uint8_t volume_level;
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_VOLDOWN;
if(evt->value != 0 && volume_level > 9)
volume_level -= 10;
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_CALLBACK_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() / 2;
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 && new_pos % 2 == 0)
keys |= KNOB_LEFT;
else if (delta < 0 && new_pos % 2 != 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;
}
/*
* The power key is only connected to the PMU and its state is detected through
* the PMU interrupts.
*/
if (pmu_pwrBtnStatus() == 1)
{
// Update the volume only once when key is pressed
if (!(keys & KEY_VOLUP) && volume_level < 246)
volume_level += 10;
keys |= KEY_VOLUP;
}
else
keys &= ~KEY_VOLUP;
return keys;
}