123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /*
- * Copyright (C) 2023 Daniele Lacamera <root@danielinux.net>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <stdint.h>
- #include <stdlib.h>
- #include "system.h"
- #include "button.h"
- #include "unicore-mx/stm32/gpio.h"
- #include "unicore-mx/stm32/exti.h"
- #include "unicore-mx/stm32/rcc.h"
- #include "unicore-mx/stm32/adc.h"
- #include "unicore-mx/stm32/f7/nvic.h"
- #include "unicore-mx/stm32/f4/adc.h"
- #include "systick.h"
- #include "task.h"
- #include "adc.h"
- #define BUTTON_DEBOUNCE_TIME 100
- #define TS_DEBOUNCE_TIME 0
- #define PSEL_0 (1 << 0)
- #define PSEL_1 (1 << 1)
- #define PSEL_2 (1 << 2)
- /* Input lines: PH6, PA8, PB15, PB14 */
- #define PLINE_0 (1 << 6)
- #define PLINE_1 (1 << 8)
- #define PLINE_2 (1 << 15)
- #define PLINE_3 (1 << 14)
- #define TS_PIN (1 << 13) /* GPIO I13 */
- static volatile int button_current_latch = 0;
- static uint32_t button_latch_switchtime;
- static volatile int button_press_pending = 0;
- static void input_run(uint32_t ev, void *arg);
- static void input_init(void);
- const char button_task_name[] = "Input";
- struct task input_task = {
- .init = input_init,
- .run = input_run,
- .events = EV_SYSTICK,
- .name = button_task_name
- };
- static void button_setup(void)
- {
- int i;
- uint32_t exti_irq;
- rcc_periph_clock_enable(RCC_SYSCFG);
- rcc_periph_clock_enable(RCC_GPIOA);
- rcc_periph_clock_enable(RCC_GPIOB);
- rcc_periph_clock_enable(RCC_GPIOH);
- rcc_periph_clock_enable(RCC_GPIOI);
- gpio_mode_setup(GPIOI, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, PSEL_0 | PSEL_1 | PSEL_2);
- gpio_clear(GPIOI, PSEL_0 | PSEL_1 | PSEL_2);
- nvic_enable_irq(NVIC_EXTI15_10_IRQ);
- nvic_enable_irq(NVIC_EXTI9_5_IRQ);
- nvic_set_priority(NVIC_EXTI15_10_IRQ, 1);
- nvic_set_priority(NVIC_EXTI9_5_IRQ, 1);
- gpio_mode_setup(GPIOH, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, PLINE_0);
- gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, PLINE_1);
- gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, PLINE_2 | PLINE_3);
- /* Set touch screen interrupt line */
- gpio_mode_setup(GPIOI, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TS_PIN);
- exti_select_source(PLINE_0, GPIOH);
- exti_select_source(PLINE_1, GPIOA);
- exti_select_source(PLINE_2, GPIOB);
- exti_select_source(PLINE_3, GPIOB);
- exti_select_source(TS_PIN, GPIOI);
- }
- static void button_start_read(void)
- {
- exti_set_trigger(PLINE_0 | PLINE_1 | PLINE_2 | PLINE_3 | TS_PIN, EXTI_TRIGGER_RISING);
- exti_enable_request(PLINE_0 | PLINE_1 | PLINE_2 | PLINE_3|TS_PIN);
- }
- void isr_exti15_10(void)
- {
- exti_reset_request(PLINE_2);
- exti_reset_request(PLINE_3);
- if (exti_get_flag_status(TS_PIN))
- exti_reset_request(TS_PIN);
- button_press_pending++;
- }
- void isr_exti9_5(void)
- {
- exti_reset_request(PLINE_1);
- exti_reset_request(PLINE_0);
- button_press_pending++;
- }
- /*** Event generation interface ***/
- struct input_status Input_status = {};
- #define TS_TOUCH_NONE 0
- #define TS_TOUCH_DETECTED 1
- int input_detect_touch(void)
- {
- uint8_t n_touch = 0;
- n_touch = ft5336_TS_DetectTouch(TS_I2C_ADDR);
- if (n_touch > 0) {
- uint16_t x, y;
- ft5336_TS_GetXY(TS_I2C_ADDR, &y, &x);
- Input_status.ts.Y = y;
- Input_status.ts.X = x;
- Input_status.start_touch = jiffies;
- return TS_TOUCH_DETECTED;
- } else
- return TS_TOUCH_NONE;
- }
-
- static int input_process_buttons(void)
- {
- int b_pressed = -1;
- struct user_button *b;
- uint8_t n_touch = 0;
- if (button_press_pending) {
- n_touch = input_detect_touch();
- if (n_touch != TS_TOUCH_NONE) {
- b = &Input_status.b[TOUCHSCREEN];
- b->pressed = 1;
- return 1;
- } else if (gpio_get(GPIOH, PLINE_0))
- b_pressed = 0;
- else if (gpio_get(GPIOA, PLINE_1))
- b_pressed = 1;
- else if (gpio_get(GPIOB, PLINE_2))
- b_pressed = 2;
- else if (gpio_get(GPIOB, PLINE_3))
- b_pressed = 3;
- else {
- button_press_pending = 0;
- return 0;
- }
- b_pressed += 4 * button_current_latch;
- if (b_pressed >= N_BUTTONS)
- return 0;
- b = &Input_status.b[b_pressed];
- if (b->transition_start_timestamp == 0U) {
- b->transition_start_timestamp = jiffies;
- return 0;
- }
- if ((jiffies - b->transition_start_timestamp) > BUTTON_DEBOUNCE_TIME) {
- button_press_pending = 0;
- b->pressed = 1;
- return 1;
- }
- } else if (jiffies >= button_latch_switchtime) {
- int i, start = 4 *button_current_latch,
- end = start + 4;
- button_latch_switchtime = jiffies + 5;
- for (i = start; i < end; i++)
- Input_status.b[i].transition_start_timestamp = 0;
- switch (button_current_latch) {
- case 0:
- gpio_clear(GPIOI, PSEL_0 | PSEL_2);
- gpio_set(GPIOI, PSEL_1);
- button_current_latch = 1;
- break;
- case 1:
- gpio_clear(GPIOI, PSEL_0 | PSEL_1);
- gpio_set(GPIOI, PSEL_2);
- button_current_latch = 2;
- break;
- case 2:
- default:
- gpio_clear(GPIOI, PSEL_1 | PSEL_2);
- gpio_set(GPIOI, PSEL_0);
- button_current_latch = 0;
- break;
- }
- }
- return 0;
- }
- int input_get_swl(void)
- {
- return gpio_get(GPIOF, (1 << 10) );
- }
- int input_get_swr(void)
- {
- return gpio_get(GPIOF, (1 << 7) );
- }
- static void adc_setup(void)
- {
- int i;
- rcc_periph_clock_enable(RCC_ADC3);
- rcc_periph_clock_enable(RCC_GPIOA);
- rcc_periph_clock_enable(RCC_GPIOF);
- gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, 0, GPIO0);
- gpio_mode_setup(GPIOF, GPIO_MODE_ANALOG, 0, GPIO6 | GPIO8 | GPIO9);
- adc_init();
- }
- void input_init(void)
- {
- button_setup();
- adc_setup();
- button_start_read();
- }
- void input_run(uint32_t ev, void *arg)
- {
- int p = input_process_buttons();
- if (p > 0) {
- trigger_event(EV_BUTTON);
- }
- }
- void input_setup(void)
- {
- register_task(&input_task);
- }
|