drivers: gpio: Add SDL emulated GPIO support

This commit adds a driver to simulate GPIO state and interrupts
using the keyboard when using SDL.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
This commit is contained in:
Pieter De Gendt 2022-09-09 10:57:01 +02:00 committed by Carles Cufí
parent bd71698a66
commit ff8a90b1de
5 changed files with 172 additions and 0 deletions

View file

@ -38,6 +38,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_LPC11U6X gpio_lpc11u6x.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_XLNX_AXI gpio_xlnx_axi.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_NPCX gpio_npcx.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_EMUL gpio_emul.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_EMUL_SDL gpio_emul_sdl.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_PSOC6 gpio_psoc6.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_PCAL6408A gpio_pcal6408a.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_EOS_S3 gpio_eos_s3.c)

View file

@ -110,6 +110,8 @@ source "drivers/gpio/Kconfig.npcx"
source "drivers/gpio/Kconfig.emul"
source "drivers/gpio/Kconfig.emul_sdl"
source "drivers/gpio/Kconfig.psoc6"
source "drivers/gpio/Kconfig.pcal6408a"

View file

@ -0,0 +1,13 @@
# GPIO emulation using SDL keyboard events
#
# Copyright (c) 2022, Basalte bv
# SPDX-License-Identifier: Apache-2.0
config GPIO_EMUL_SDL
bool "SDL GPIO emulation"
default y
depends on DT_HAS_ZEPHYR_GPIO_EMUL_SDL_ENABLED
depends on GPIO_EMUL
depends on HAS_SDL
help
Enable GPIO emulation using SDL keyboard events.

View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2022, Basalte bv
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT zephyr_gpio_emul_sdl
#include <zephyr/drivers/gpio/gpio_emul.h>
#include <zephyr/logging/log.h>
#include <SDL.h>
LOG_MODULE_REGISTER(gpio_emul_sdl, CONFIG_GPIO_LOG_LEVEL);
struct gpio_sdl_config {
const struct device *emul;
const SDL_Scancode *codes;
uint8_t num_codes;
};
static int sdl_filter(void *arg, SDL_Event *event)
{
const struct device *port = arg;
const struct gpio_sdl_config *config = port->config;
int ret;
gpio_pin_t pin = 0;
/* Only handle keyboard events */
switch (event->type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
break;
default:
return 1;
}
/* Search for the corresponding scancode */
while (pin < config->num_codes) {
if (config->codes[pin] == event->key.keysym.scancode) {
break;
}
pin++;
}
if (pin == config->num_codes) {
/* Not tracked */
return 1;
}
/* Lock the scheduler so we can't be preempted,
* as the gpio_emul driver keeps a mutex locked
* for as long as there are pending interrupts
*/
k_sched_lock();
/* Update the pin state */
ret = gpio_emul_input_set(config->emul, pin, event->type == SDL_KEYDOWN ? 1 : 0);
k_sched_unlock();
if (ret < 0) {
LOG_WRN("Failed to emulate input (%d)", ret);
}
return 0;
}
static int gpio_sdl_init(const struct device *dev)
{
const struct gpio_sdl_config *config = dev->config;
for (uint8_t pin = 0; pin < config->num_codes; ++pin) {
if (config->codes[pin] != SDL_SCANCODE_UNKNOWN) {
LOG_INF("GPIO %s:%u = %u", dev->name, pin, config->codes[pin]);
}
}
SDL_AddEventWatch(sdl_filter, (void *)dev);
return 0;
}
#define GPIO_SDL_DEFINE(inst) \
BUILD_ASSERT(DT_NODE_HAS_COMPAT_STATUS(DT_INST_PARENT(inst), \
zephyr_gpio_emul, okay), \
"Enabled parent zephyr,gpio-emul node is required"); \
\
static const SDL_Scancode gpio_sdl_##inst##_codes[] \
= DT_INST_PROP(inst, scancodes); \
\
static const struct gpio_sdl_config gpio_sdl_##inst##_config = { \
.emul = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
.codes = gpio_sdl_##inst##_codes, \
.num_codes = DT_INST_PROP_LEN(inst, scancodes), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, gpio_sdl_init, NULL, NULL, \
&gpio_sdl_##inst##_config, POST_KERNEL, \
CONFIG_GPIO_INIT_PRIORITY, NULL);
DT_INST_FOREACH_STATUS_OKAY(GPIO_SDL_DEFINE)

View file

@ -0,0 +1,53 @@
# Copyright 2022, Basalte bv
# SPDX-License-Identifier: Apache-2.0
description: |
SDL keyboard GPIO input Emulator
Simulate GPIO state/interrupts using SDL keyboard events. This node has
to be a child of a `zephyr,gpio-emul` compatible.
Add a list of scancodes for the desired keys to be mapped.
Refer to https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
section Keyboard/Keypad (p53) for a list of scancode values.
The following example maps the first 3 numeric keys to GPIO pins:
/* gpio0 has to be a zephyr,gpio-emul device */
&gpio0 {
ngpios = <3>;
sdl_gpio {
compatible = "zephyr,gpio-emul-sdl";
scancodes = <30 31 32>;
};
};
keypad: keypad {
compatible = "gpio-keys";
key1: key1 {
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
};
key1: key2 {
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
};
key3: key3 {
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
};
};
The limitations of usage are:
- Only active high as we don't get events for keys that aren't pressed
- Pressing multiple keys is best effort, state will be kept but no events
are generated once the last key is released
compatible: "zephyr,gpio-emul-sdl"
include: base.yaml
properties:
scancodes:
type: array
required: true
description: |
An array of SDL scancodes mapped to its GPIO index