diff --git a/Core/Inc/events.h b/Core/Inc/events.h index dc67b02..5d3152d 100644 --- a/Core/Inc/events.h +++ b/Core/Inc/events.h @@ -1,4 +1,60 @@ #ifndef __EVENTS_H #define __EVENTS_H +#include "stm32g441xx.h" + +#include + +typedef enum { + BTN_PRESS_PREV, + BTN_PRESS_R2D, + BTN_PRESS_OK, + BTN_PRESS_NEXT +} ButtonPressEvent; + +typedef enum { ENC0, ENC1 } Encoder; +typedef enum { ENC_CHANGE_INC, ENC_CHANGE_DEC } EncoderChangeDirection; +typedef struct { + Encoder encoder; + EncoderChangeDirection dir; +} EncoderChangeEvent; + +typedef enum { EV_BTN_PRESS, EV_ENC_CHANGE } EventType; + +typedef struct { + EventType type; + union { + ButtonPressEvent btn_press; + EncoderChangeEvent enc_change; + }; +} Event; + +#define EVENT_QUEUE_SIZE 32 +typedef struct { + Event ring_buffer[EVENT_QUEUE_SIZE]; + uint16_t read_idx; + uint16_t write_idx; +} EventQueue; + +/** + * @brief Push an event to the back of the queue. + * + * The event is deep-copied to the queue, so it can be deallocated after the + * call is complete. + */ +void event_push(Event *ev); +/** + * @brief Pop an event from the start of the queue. + * + * The value in the queue may be overwritten with the next event_push() call. + * Since that call can happen in an interrupt, i.e. is probably out of control + * of the event_pop() caller, we return by value here. + */ +Event event_pop(); + +uint16_t event_num_pending(); +uint16_t event_num_free(); + +void handle_events(); + #endif // __EVENTS_H \ No newline at end of file diff --git a/Core/Inc/main.h b/Core/Inc/main.h index f6dff43..9f8eeba 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -75,12 +75,16 @@ void Error_Handler(void); #define V_POT_GPIO_Port GPIOB #define BTN0_Pin GPIO_PIN_12 #define BTN0_GPIO_Port GPIOB +#define BTN0_EXTI_IRQn EXTI15_10_IRQn #define BTN1_Pin GPIO_PIN_13 #define BTN1_GPIO_Port GPIOB +#define BTN1_EXTI_IRQn EXTI15_10_IRQn #define BTN2_Pin GPIO_PIN_14 #define BTN2_GPIO_Port GPIOB +#define BTN2_EXTI_IRQn EXTI15_10_IRQn #define BTN3_Pin GPIO_PIN_15 #define BTN3_GPIO_Port GPIOB +#define BTN3_EXTI_IRQn EXTI15_10_IRQn #define DISP_RESET_Pin GPIO_PIN_15 #define DISP_RESET_GPIO_Port GPIOA #define ENC0A_Pin GPIO_PIN_4 diff --git a/Core/Inc/rpi.h b/Core/Inc/rpi.h index cc52a30..c51c892 100644 --- a/Core/Inc/rpi.h +++ b/Core/Inc/rpi.h @@ -28,5 +28,6 @@ extern size_t rpi_num_polls; void rpi_init(I2C_HandleTypeDef *handle); void rpi_update_tx_buffer(); +void rpi_update_tx_buffer_mission_select(); #endif // __RPI_H diff --git a/Core/Inc/state.h b/Core/Inc/state.h index 324251e..a3e6816 100644 --- a/Core/Inc/state.h +++ b/Core/Inc/state.h @@ -8,8 +8,33 @@ typedef enum { VIEW_TESTING = 3 } STWView; +typedef enum { + MISSION_NONE, + MISSION_ACCELERATION, + MISSION_SKIDPAD, + MISSION_AUTOCROSS, + MISSION_TRACKDRIVE, + MISSION_EBS_TEST, + MISSION_INSPECTION, + MISSION_MANUAL +} Mission; + +typedef struct { + Mission selection; +} MissionSelectState; + +typedef struct { + Mission current_mission; +} AMIState; + +typedef union { + MissionSelectState mission_select; + AMIState ami; +} ViewState; + typedef struct { STWView view; + ViewState view_state; } STWState; extern STWState stw_state; diff --git a/Core/Inc/stm32g4xx_it.h b/Core/Inc/stm32g4xx_it.h index 94f24b3..41b78e6 100644 --- a/Core/Inc/stm32g4xx_it.h +++ b/Core/Inc/stm32g4xx_it.h @@ -56,6 +56,7 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void I2C2_EV_IRQHandler(void); +void EXTI15_10_IRQHandler(void); /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/Core/Inc/user_inputs.h b/Core/Inc/user_inputs.h new file mode 100644 index 0000000..bdf34f7 --- /dev/null +++ b/Core/Inc/user_inputs.h @@ -0,0 +1,11 @@ +#ifndef __FT_USER_INPUTS_H +#define __FT_USER_INPUTS_H + +#include "events.h" +#include "stm32g4xx_hal.h" + +void handle_button_press(const ButtonPressEvent *ev); + +void handle_button_press_mission_select(const ButtonPressEvent *ev); + +#endif // __FT_USER_INPUTS_H \ No newline at end of file diff --git a/Core/Src/events.c b/Core/Src/events.c new file mode 100644 index 0000000..8b6deb0 --- /dev/null +++ b/Core/Src/events.c @@ -0,0 +1,64 @@ +#include "events.h" +#include "main.h" +#include "user_inputs.h" +#include + +static volatile EventQueue event_queue = {.read_idx = 0, .write_idx = 0}; + +void event_push(Event *ev) { + if (event_num_free() == 0) { + // TODO: How do we handle this? + return; + } + + event_queue.ring_buffer[event_queue.write_idx] = *ev; + event_queue.write_idx = (event_queue.write_idx + 1) % EVENT_QUEUE_SIZE; +} + +Event event_pop() { + if (event_num_pending() == 0) { + // TODO: How do we handle this? + Error_Handler(); + } + + Event result = event_queue.ring_buffer[event_queue.read_idx]; + event_queue.read_idx = (event_queue.read_idx + 1) % EVENT_QUEUE_SIZE; + return result; +} + +uint16_t event_num_pending() { + // Copy the values so we can be sure they don't change while we're computing + // this + uint16_t read_idx = event_queue.read_idx; + uint16_t write_idx = event_queue.write_idx; + if (write_idx >= read_idx) { + return write_idx - read_idx; + } else { + return write_idx + (EVENT_QUEUE_SIZE - read_idx); + } +} + +uint16_t event_num_free() { + // Copy the values so we can be sure they don't change while we're computing + // this + uint16_t read_idx = event_queue.read_idx; + uint16_t write_idx = event_queue.write_idx; + if (read_idx > write_idx) { + return read_idx - write_idx; + } else { + return read_idx + (EVENT_QUEUE_SIZE - write_idx); + } +} + +void handle_events() { + while (event_num_pending() > 0) { + Event ev = event_pop(); + switch (ev.type) { + case EV_BTN_PRESS: + handle_button_press(&ev.btn_press); + break; + default: + Error_Handler(); + } + } +} \ No newline at end of file diff --git a/Core/Src/main.c b/Core/Src/main.c index eb6ae19..51e4730 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -21,10 +21,12 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "events.h" #include "rpi.h" #include "state.h" #include "stm32g4xx_hal.h" +#include "stm32g4xx_hal_gpio.h" #include @@ -119,13 +121,7 @@ int main(void) { } else { HAL_GPIO_WritePin(DISP_RESET_GPIO_Port, DISP_RESET_Pin, GPIO_PIN_SET); } - if (rpi_num_polls > 0) { - if (rpi_active_since == 0) { - rpi_active_since = now; - } else if (now - rpi_active_since > 10000) { - stw_state.view = VIEW_AMI; - } - } + handle_events(); } /* USER CODE END 3 */ } @@ -343,13 +339,21 @@ static void MX_GPIO_Init(void) { GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /*Configure GPIO pins : BTN0_Pin BTN1_Pin BTN2_Pin BTN3_Pin - ENC0A_Pin ENC0B_Pin ENC1A_Pin ENC1B_Pin */ - GPIO_InitStruct.Pin = BTN0_Pin | BTN1_Pin | BTN2_Pin | BTN3_Pin | ENC0A_Pin | - ENC0B_Pin | ENC1A_Pin | ENC1B_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; + /*Configure GPIO pins : BTN0_Pin BTN1_Pin BTN2_Pin BTN3_Pin */ + GPIO_InitStruct.Pin = BTN0_Pin | BTN1_Pin | BTN2_Pin | BTN3_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /*Configure GPIO pins : ENC0A_Pin ENC0B_Pin ENC1A_Pin ENC1B_Pin */ + GPIO_InitStruct.Pin = ENC0A_Pin | ENC0B_Pin | ENC1A_Pin | ENC1B_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* EXTI interrupt init*/ + HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); } /* USER CODE BEGIN 4 */ diff --git a/Core/Src/rpi.c b/Core/Src/rpi.c index 57979f5..1642895 100644 --- a/Core/Src/rpi.c +++ b/Core/Src/rpi.c @@ -29,7 +29,19 @@ void rpi_init(I2C_HandleTypeDef *handle) { } } -void rpi_update_tx_buffer() { i2c_tx_buf[0] = stw_state.view; } +void rpi_update_tx_buffer() { + i2c_tx_buf[0] = stw_state.view; + switch (stw_state.view) { + case VIEW_MISSION_SELECT: + rpi_update_tx_buffer_mission_select(); + break; + default: + Error_Handler(); + } +} +void rpi_update_tx_buffer_mission_select() { + i2c_tx_buf[1] = stw_state.view_state.mission_select.selection; +} void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *handle) { switch (rpi_i2c_state) { diff --git a/Core/Src/state.c b/Core/Src/state.c index 8bb7a9b..06ca1f9 100644 --- a/Core/Src/state.c +++ b/Core/Src/state.c @@ -2,4 +2,7 @@ STWState stw_state; -void state_init() { stw_state.view = VIEW_MISSION_SELECT; } \ No newline at end of file +void state_init() { + stw_state.view = VIEW_MISSION_SELECT; + stw_state.view_state.mission_select.selection = MISSION_ACCELERATION; +} \ No newline at end of file diff --git a/Core/Src/stm32g4xx_it.c b/Core/Src/stm32g4xx_it.c index 7bb84bc..2d9b80d 100644 --- a/Core/Src/stm32g4xx_it.c +++ b/Core/Src/stm32g4xx_it.c @@ -212,6 +212,23 @@ void I2C2_EV_IRQHandler(void) /* USER CODE END I2C2_EV_IRQn 1 */ } +/** + * @brief This function handles EXTI line[15:10] interrupts. + */ +void EXTI15_10_IRQHandler(void) +{ + /* USER CODE BEGIN EXTI15_10_IRQn 0 */ + + /* USER CODE END EXTI15_10_IRQn 0 */ + HAL_GPIO_EXTI_IRQHandler(BTN0_Pin); + HAL_GPIO_EXTI_IRQHandler(BTN1_Pin); + HAL_GPIO_EXTI_IRQHandler(BTN2_Pin); + HAL_GPIO_EXTI_IRQHandler(BTN3_Pin); + /* USER CODE BEGIN EXTI15_10_IRQn 1 */ + + /* USER CODE END EXTI15_10_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/Core/Src/user_inputs.c b/Core/Src/user_inputs.c new file mode 100644 index 0000000..ec635f0 --- /dev/null +++ b/Core/Src/user_inputs.c @@ -0,0 +1,77 @@ +#include "user_inputs.h" + +#include "events.h" +#include "main.h" +#include "state.h" +#include "stm32g4xx_hal_gpio.h" + +void HAL_GPIO_EXTI_Callback(uint16_t pin) { + Event ev; + + GPIO_PinState state = HAL_GPIO_ReadPin(GPIOB, pin); + ev.type = state; + switch (pin) { + case BTN0_Pin: + ev.type = EV_BTN_PRESS; + ev.btn_press = BTN_PRESS_PREV; + break; + case BTN1_Pin: + ev.type = EV_BTN_PRESS; + ev.btn_press = BTN_PRESS_R2D; + break; + case BTN2_Pin: + ev.type = EV_BTN_PRESS; + ev.btn_press = BTN_PRESS_OK; + break; + case BTN3_Pin: + ev.type = EV_BTN_PRESS; + ev.btn_press = BTN_PRESS_NEXT; + break; + default: + Error_Handler(); + } + + event_push(&ev); +} + +void handle_button_press(const ButtonPressEvent *ev) { + switch (stw_state.view) { + case VIEW_MISSION_SELECT: + handle_button_press_mission_select(ev); + break; + case VIEW_AMI: + break; + default: + Error_Handler(); + } +} + +void handle_button_press_mission_select(const ButtonPressEvent *ev) { + switch (*ev) { + case BTN_PRESS_PREV: { + Mission *selection = &stw_state.view_state.mission_select.selection; + if (*selection == MISSION_ACCELERATION || *selection == MISSION_NONE) { + *selection = MISSION_MANUAL; + } else { + *selection = *selection - 1; + } + break; + } + case BTN_PRESS_R2D: + break; + case BTN_PRESS_OK: + stw_state.view_state.ami.current_mission = + stw_state.view_state.mission_select.selection; + stw_state.view = VIEW_AMI; + break; + case BTN_PRESS_NEXT: { + Mission *selection = &stw_state.view_state.mission_select.selection; + if (*selection == MISSION_MANUAL) { + *selection = MISSION_ACCELERATION; + } else { + *selection = *selection + 1; + } + break; + } + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index 8f3a71d..95f05b8 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Fri May 27 00:09:05 CEST 2022] +# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Sat May 28 00:49:24 CEST 2022] ########################################################################################################################## # ------------------------------------------------ @@ -56,11 +56,11 @@ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_fdcan.c \ +Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c.c \ +Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c_ex.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim_ex.c \ -Core/Src/system_stm32g4xx.c \ -Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c.c \ -Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c_ex.c +Core/Src/system_stm32g4xx.c # ASM sources ASM_SOURCES = \ diff --git a/STM32Make.make b/STM32Make.make index 2b516c6..0200136 100644 --- a/STM32Make.make +++ b/STM32Make.make @@ -36,12 +36,14 @@ BUILD_DIR = build ###################################### # C sources C_SOURCES = \ +Core/Src/events.c \ Core/Src/main.c \ Core/Src/rpi.c \ Core/Src/state.c \ Core/Src/stm32g4xx_hal_msp.c \ Core/Src/stm32g4xx_it.c \ Core/Src/system_stm32g4xx.c \ +Core/Src/user_inputs.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc.c \ Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc_ex.c \ @@ -81,7 +83,7 @@ PREFIX = arm-none-eabi- POSTFIX = " # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx) # either it can be added to the PATH environment variable. -GCC_PATH="/home/jasper/.config/Code/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/arm-none-eabi-gcc/10.3.1-2.3.1/.content/bin + ifdef GCC_PATH CXX = $(GCC_PATH)/$(PREFIX)g++$(POSTFIX) CC = $(GCC_PATH)/$(PREFIX)gcc$(POSTFIX) diff --git a/steering-wheel-stm.ioc b/steering-wheel-stm.ioc index b8b0a18..8c9cde0 100644 --- a/steering-wheel-stm.ioc +++ b/steering-wheel-stm.ioc @@ -55,6 +55,7 @@ MxCube.Version=6.5.0 MxDb.Version=DB.6.0.50 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true +NVIC.EXTI15_10_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true NVIC.I2C2_EV_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true @@ -115,36 +116,44 @@ PB11.GPIO_Label=V_POT PB11.Locked=true PB11.Mode=IN14-Single-Ended PB11.Signal=ADC1_IN14 -PB12.GPIOParameters=GPIO_Label +PB12.GPIOParameters=GPIO_PuPd,GPIO_Label PB12.GPIO_Label=BTN0 +PB12.GPIO_PuPd=GPIO_PULLUP PB12.Locked=true -PB12.Signal=GPIO_Input -PB13.GPIOParameters=GPIO_Label +PB12.Signal=GPXTI12 +PB13.GPIOParameters=GPIO_PuPd,GPIO_Label PB13.GPIO_Label=BTN1 +PB13.GPIO_PuPd=GPIO_PULLUP PB13.Locked=true -PB13.Signal=GPIO_Input -PB14.GPIOParameters=GPIO_Label +PB13.Signal=GPXTI13 +PB14.GPIOParameters=GPIO_PuPd,GPIO_Label PB14.GPIO_Label=BTN2 +PB14.GPIO_PuPd=GPIO_PULLUP PB14.Locked=true -PB14.Signal=GPIO_Input -PB15.GPIOParameters=GPIO_Label +PB14.Signal=GPXTI14 +PB15.GPIOParameters=GPIO_PuPd,GPIO_Label PB15.GPIO_Label=BTN3 +PB15.GPIO_PuPd=GPIO_PULLUP PB15.Locked=true -PB15.Signal=GPIO_Input -PB4.GPIOParameters=GPIO_Label +PB15.Signal=GPXTI15 +PB4.GPIOParameters=GPIO_PuPd,GPIO_Label PB4.GPIO_Label=ENC0A +PB4.GPIO_PuPd=GPIO_PULLUP PB4.Locked=true PB4.Signal=GPIO_Input -PB5.GPIOParameters=GPIO_Label +PB5.GPIOParameters=GPIO_PuPd,GPIO_Label PB5.GPIO_Label=ENC0B +PB5.GPIO_PuPd=GPIO_PULLUP PB5.Locked=true PB5.Signal=GPIO_Input -PB6.GPIOParameters=GPIO_Label +PB6.GPIOParameters=GPIO_PuPd,GPIO_Label PB6.GPIO_Label=ENC1A +PB6.GPIO_PuPd=GPIO_PULLUP PB6.Locked=true PB6.Signal=GPIO_Input -PB7.GPIOParameters=GPIO_Label +PB7.GPIOParameters=GPIO_PuPd,GPIO_Label PB7.GPIO_Label=ENC1B +PB7.GPIO_PuPd=GPIO_PULLUP PB7.Locked=true PB7.Signal=GPIO_Input PinOutPanel.RotationAngle=0 @@ -215,6 +224,14 @@ RCC.USART3Freq_Value=16000000 RCC.USBFreq_Value=64000000 RCC.VCOInputFreq_Value=16000000 RCC.VCOOutputFreq_Value=128000000 +SH.GPXTI12.0=GPIO_EXTI12 +SH.GPXTI12.ConfNb=1 +SH.GPXTI13.0=GPIO_EXTI13 +SH.GPXTI13.ConfNb=1 +SH.GPXTI14.0=GPIO_EXTI14 +SH.GPXTI14.ConfNb=1 +SH.GPXTI15.0=GPIO_EXTI15 +SH.GPXTI15.ConfNb=1 VP_SYS_VS_DBSignals.Mode=DisableDeadBatterySignals VP_SYS_VS_DBSignals.Signal=SYS_VS_DBSignals VP_SYS_VS_Systick.Mode=SysTick