diff --git a/boards/arm/stm32/olimex-stm32-p407/include/board.h b/boards/arm/stm32/olimex-stm32-p407/include/board.h index e5f5992e70..6d203554f9 100644 --- a/boards/arm/stm32/olimex-stm32-p407/include/board.h +++ b/boards/arm/stm32/olimex-stm32-p407/include/board.h @@ -209,23 +209,31 @@ /* The Olimex STM32-P407 supports seven buttons: */ -#define BUTTON_TAMPER 0 -#define BUTTON_WKUP 1 -#define BUTTON_RIGHT 2 -#define BUTTON_UP 3 -#define BUTTON_LEFT 4 -#define BUTTON_DOWN 5 -#define BUTTON_CENTER 6 +#define BUTTON_TAMPER 0 +#define BUTTON_WKUP 1 -#define NUM_BUTTONS 7 +#ifdef CONFIG_DJOYSTICK +# define NUM_BUTTONS 2 +#else +# define JOYSTICK_RIGHT 2 +# define JOYSTICK_UP 3 +# define JOYSTICK_LEFT 4 +# define JOYSTICK_DOWN 5 +# define JOYSTICK_CENTER 6 -#define BUTTON_TAMPER_BIT (1 << BUTTON_TAMPER) -#define BUTTON_WKUP_BIT (1 << BUTTON_WKUP) -#define BUTTON_RIGHT_BIT (1 << BUTTON_RIGHT) -#define BUTTON_UP_BIT (1 << BUTTON_UP) -#define BUTTON_LEFT_BIT (1 << BUTTON_LEFT) -#define BUTTON_DOWN_BIT (1 << BUTTON_DOWN) -#define BUTTON_CENTER_BIT (1 << BUTTON_CENTER) +# define NUM_BUTTONS 7 +#endif + +#define BUTTON_TAMPER_BIT (1 << BUTTON_TAMPER) +#define BUTTON_WKUP_BIT (1 << BUTTON_WKUP) + +#ifndef CONFIG_DJOYSTICK +# define JOYSTICK_RIGHT_BIT (1 << JOYSTICK_RIGHT) +# define JOYSTICK_UP_BIT (1 << JOYSTICK_UP) +# define JOYSTICK_LEFT_BIT (1 << JOYSTICK_LEFT) +# define JOYSTICK_DOWN_BIT (1 << JOYSTICK_DOWN) +# define JOYSTICK_CENTER_BIT (1 << JOYSTICK_CENTER) +#endif /* Alternate function pin selections ****************************************/ diff --git a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs index 7274cc9e1b..d6a2691589 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs +++ b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs @@ -71,6 +71,10 @@ ifeq ($(CONFIG_AUDIO_CS4344),y) CSRCS += stm32_cs4344.c endif +ifeq ($(CONFIG_DJOYSTICK),y) + CSRCS += stm32_djoystick.c +endif + DEPPATH += --dep-path board VPATH += :board CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board) diff --git a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h index c5e380aacd..0f25f50004 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h +++ b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h @@ -159,17 +159,24 @@ /* BUTTONS -- NOTE that all have EXTI interrupts configured */ -#define MIN_IRQBUTTON BUTTON_TAMPER -#define MAX_IRQBUTTON BUTTON_CENTER -#define NUM_IRQBUTTONS 7 +#ifdef CONFIG_DJOYSTICK +# define MIN_IRQBUTTON BUTTON_TAMPER +# define MAX_IRQBUTTON BUTTON_WKUP +# define NUM_IRQBUTTONS 2 +#else +# define MIN_IRQBUTTON BUTTON_TAMPER +# define MAX_IRQBUTTON JOYSTICK_CENTER +# define NUM_IRQBUTTONS 7 +#endif #define GPIO_BTN_TAMPER (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTC|GPIO_PIN13) #define GPIO_BTN_WKUP (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTA|GPIO_PIN0) -#define GPIO_BTN_RIGHT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN6) -#define GPIO_BTN_UP (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN7) -#define GPIO_BTN_LEFT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN11) -#define GPIO_BTN_DOWN (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN8) -#define GPIO_BTN_CENTER (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN15) + +#define GPIO_JOY_RIGHT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN6) +#define GPIO_JOY_UP (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN7) +#define GPIO_JOY_LEFT (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN11) +#define GPIO_JOY_DOWN (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN8) +#define GPIO_JOY_CENTER (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTG|GPIO_PIN15) /* USB OTG FS * @@ -324,5 +331,17 @@ int stm32_can_setup(void); int stm32_cs4344_initialize(int minor); #endif +/**************************************************************************** + * Name: stm32_djoy_initialize + * + * Description: + * Initialize and register the discrete joystick driver + * + ****************************************************************************/ + +#ifdef CONFIG_DJOYSTICK +int stm32_djoy_initialize(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_STM32_OLIMEX_STM32_P407_SRC_H */ diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c index 7431d87e85..9be036973d 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c +++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c @@ -219,7 +219,15 @@ int stm32_bringup(void) ret = stm32_cs4344_initialize(1); if (ret != OK) { - serr("Failed to initialize CS43L22 audio: %d\n", ret); + syslog(LOG_ERR, "Failed to initialize CS4344 audio: %d\n", ret); + } +#endif + +#ifdef CONFIG_DJOYSTICK + ret = stm32_djoy_initialize(); + if (ret != OK) + { + syslog(LOG_ERR, "Failed to register djoystick driver: %d\n", ret); } #endif diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_buttons.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_buttons.c index 2a3c0f92dd..12cf7ac528 100644 --- a/boards/arm/stm32/olimex-stm32-p407/src/stm32_buttons.c +++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_buttons.c @@ -64,11 +64,19 @@ static const uint32_t g_buttons[NUM_BUTTONS] = { GPIO_BTN_TAMPER, GPIO_BTN_WKUP, - GPIO_BTN_RIGHT, - GPIO_BTN_UP, - GPIO_BTN_LEFT, - GPIO_BTN_DOWN, - GPIO_BTN_CENTER + + /* The Joystick is treated like the other buttons unless CONFIG_DJOYSTICK + * is defined, then it is assumed that they should be used by the discrete + * joystick driver. + */ + +#ifndef CONFIG_DJOYSTICK + GPIO_JOY_RIGHT, + GPIO_JOY_UP, + GPIO_JOY_LEFT, + GPIO_JOY_DOWN, + GPIO_JOY_CENTER +#endif }; /**************************************************************************** @@ -122,30 +130,32 @@ uint32_t board_buttons(void) ret |= BUTTON_WKUP_BIT; } - if (stm32_gpioread(g_buttons[BUTTON_RIGHT])) +#ifndef CONFIG_DJOYSTICK + if (stm32_gpioread(g_buttons[JOYSTICK_RIGHT])) { - ret |= BUTTON_RIGHT_BIT; + ret |= JOYSTICK_RIGHT_BIT; } - if (stm32_gpioread(g_buttons[BUTTON_UP])) + if (stm32_gpioread(g_buttons[JOYSTICK_UP])) { - ret |= BUTTON_UP_BIT; + ret |= JOYSTICK_UP_BIT; } - if (stm32_gpioread(g_buttons[BUTTON_LEFT])) + if (stm32_gpioread(g_buttons[JOYSTICK_LEFT])) { - ret |= BUTTON_LEFT_BIT; + ret |= JOYSTICK_LEFT_BIT; } - if (stm32_gpioread(g_buttons[BUTTON_DOWN])) + if (stm32_gpioread(g_buttons[JOYSTICK_DOWN])) { - ret |= BUTTON_DOWN_BIT; + ret |= JOYSTICK_DOWN_BIT; } - if (stm32_gpioread(g_buttons[BUTTON_CENTER])) + if (stm32_gpioread(g_buttons[JOYSTICK_CENTER])) { - ret |= BUTTON_CENTER_BIT; + ret |= JOYSTICK_CENTER_BIT; } +#endif return ret; } diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_djoystick.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_djoystick.c new file mode 100644 index 0000000000..28c717e991 --- /dev/null +++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_djoystick.c @@ -0,0 +1,296 @@ +/**************************************************************************** + * boards/arm/stm32/olimex-stm32-p407/src/stm32_djoystick.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "stm32_gpio.h" +#include "olimex-stm32-p407.h" + +#ifdef CONFIG_DJOYSTICK + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Number of Joystick discretes */ + +#define DJOY_NGPIOS 5 + +/* Bitset of supported Joystick discretes */ + +#define DJOY_SUPPORTED (DJOY_UP_BIT | DJOY_DOWN_BIT | DJOY_LEFT_BIT | \ + DJOY_RIGHT_BIT | DJOY_BUTTON_SELECT_BIT) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static djoy_buttonset_t + djoy_supported(FAR const struct djoy_lowerhalf_s *lower); +static djoy_buttonset_t + djoy_sample(FAR const struct djoy_lowerhalf_s *lower); +static void djoy_enable(FAR const struct djoy_lowerhalf_s *lower, + djoy_buttonset_t press, djoy_buttonset_t release, + djoy_interrupt_t handler, FAR void *arg); + +static void djoy_disable(void); +static int djoy_interrupt(int irq, FAR void *context, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Pin configuration for each Olimex-P407 joystick "button." Index using + * DJOY_* definitions in include/nuttx/input/djoystick.h. + */ + +static const uint16_t g_joygpio[DJOY_NGPIOS] = +{ + GPIO_JOY_UP, GPIO_JOY_DOWN, GPIO_JOY_LEFT, GPIO_JOY_RIGHT, GPIO_JOY_CENTER +}; + +/* Current interrupt handler and argument */ + +static djoy_interrupt_t g_djoyhandler; +static FAR void *g_djoyarg; + +/* This is the discrete joystick lower half driver interface */ + +static const struct djoy_lowerhalf_s g_djoylower = +{ + .dl_supported = djoy_supported, + .dl_sample = djoy_sample, + .dl_enable = djoy_enable, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: djoy_supported + * + * Description: + * Return the set of buttons supported on the discrete joystick device + * + ****************************************************************************/ + +static djoy_buttonset_t + djoy_supported(FAR const struct djoy_lowerhalf_s *lower) +{ + iinfo("Supported: %02x\n", DJOY_SUPPORTED); + return (djoy_buttonset_t)DJOY_SUPPORTED; +} + +/**************************************************************************** + * Name: djoy_sample + * + * Description: + * Return the current state of all discrete joystick buttons + * + ****************************************************************************/ + +static djoy_buttonset_t djoy_sample(FAR const struct djoy_lowerhalf_s *lower) +{ + djoy_buttonset_t ret = 0; + int i; + + /* Read each joystick GPIO value */ + + for (i = 0; i < DJOY_NGPIOS; i++) + { + bool released = stm32_gpioread(g_joygpio[i]); + if (!released) + { + ret |= (1 << i); + } + } + + iinfo("Retuning: %02x\n", DJOY_SUPPORTED); + return ret; +} + +/**************************************************************************** + * Name: djoy_enable + * + * Description: + * Enable interrupts on the selected set of joystick buttons. And empty + * set will disable all interrupts. + * + ****************************************************************************/ + +static void djoy_enable(FAR const struct djoy_lowerhalf_s *lower, + djoy_buttonset_t press, djoy_buttonset_t release, + djoy_interrupt_t handler, FAR void *arg) +{ + irqstate_t flags; + djoy_buttonset_t either = press | release; + djoy_buttonset_t bit; + bool rising; + bool falling; + int i; + + /* Start with all interrupts disabled */ + + flags = enter_critical_section(); + djoy_disable(); + + iinfo("press: %02x release: %02x handler: %p arg: %p\n", + press, release, handler, arg); + + /* If no events are indicated or if no handler is provided, then this + * must really be a request to disable interrupts. + */ + + if (either && handler) + { + /* Save the new the handler and argument */ + + g_djoyhandler = handler; + g_djoyarg = arg; + + /* Check each GPIO. */ + + for (i = 0; i < DJOY_NGPIOS; i++) + { + /* Enable interrupts on each pin that has either a press or + * release event associated with it. + */ + + bit = (1 << i); + if ((either & bit) != 0) + { + /* Active low so a press corresponds to a falling edge and + * a release corresponds to a rising edge. + */ + + falling = ((press & bit) != 0); + rising = ((release & bit) != 0); + + iinfo("GPIO %d: rising: %d falling: %d\n", + i, rising, falling); + + stm32_gpiosetevent(g_joygpio[i], rising, falling, + true, djoy_interrupt, NULL); + } + } + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: djoy_disable + * + * Description: + * Disable all joystick interrupts + * + ****************************************************************************/ + +static void djoy_disable(void) +{ + irqstate_t flags; + int i; + + /* Disable each joystick interrupt */ + + flags = enter_critical_section(); + for (i = 0; i < DJOY_NGPIOS; i++) + { + stm32_gpiosetevent(g_joygpio[i], false, false, false, NULL, NULL); + } + + leave_critical_section(flags); + + /* Nullify the handler and argument */ + + g_djoyhandler = NULL; + g_djoyarg = NULL; +} + +/**************************************************************************** + * Name: djoy_interrupt + * + * Description: + * Discrete joystick interrupt handler + * + ****************************************************************************/ + +static int djoy_interrupt(int irq, FAR void *context, FAR void *arg) +{ + DEBUGASSERT(g_djoyhandler); + if (g_djoyhandler) + { + g_djoyhandler(&g_djoylower, g_djoyarg); + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_djoy_initialize + * + * Description: + * Initialize and register the discrete joystick driver + * + ****************************************************************************/ + +int stm32_djoy_initialize(void) +{ + int i; + + /* Configure the GPIO pins as inputs. NOTE: This is unnecessary for + * interrupting pins since it will also be done by stm32_gpiosetevent(). + */ + + for (i = 0; i < DJOY_NGPIOS; i++) + { + stm32_configgpio(g_joygpio[i]); + } + + /* Make sure that all interrupts are disabled */ + + djoy_disable(); + + /* Register the joystick device as /dev/djoy0 */ + + return djoy_register("/dev/djoy0", &g_djoylower); +} + +#endif /* CONFIG_DJOYSTICK */