diff --git a/.idea/f103-bluepill.iml b/.idea/f103-bluepill.iml index 4895957..7d4e586 100644 --- a/.idea/f103-bluepill.iml +++ b/.idea/f103-bluepill.iml @@ -5,11 +5,13 @@ + + @@ -19,26 +21,26 @@ + - - + - + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 578add8..28fbabd 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,6 @@ \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 57042b2..a32683a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,9 +1,9 @@ - + - + diff --git a/.mxproject b/.mxproject index e105cff..a24093e 100644 --- a/.mxproject +++ b/.mxproject @@ -1,12 +1,12 @@ +[PreviousLibFiles] +LibFiles=Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h;Drivers/STM32F1xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio_ex.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_cortex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pwr.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash_ex.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c;Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f100xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f102x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f100xe.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xg.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/system_stm32f1xx.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101xe.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xe.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f107xc.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f105xc.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f102xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101xg.h; + [PreviousGenFiles] -HeaderPath=/home/ondra/devel/f103-bluepill/Inc -SourcePath=/home/ondra/devel/f103-bluepill/Src +HeaderPath=/home/ondra/devel/f103-simon/Inc +SourcePath=/home/ondra/devel/f103-simon/Src SourceFiles=gpio.h;usart.h;stm32f1xx_it.h;stm32f1xx_hal_conf.h;mxconstants.h;gpio.c;usart.c;stm32f1xx_it.c;stm32f1xx_hal_msp.c;main.c; HeaderFiles=gpio.h;usart.h;stm32f1xx_it.h;stm32f1xx_hal_conf.h;mxconstants.h; -[PreviousLibFiles] -LibFiles=Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_tim_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h;Drivers/STM32F1xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio_ex.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma_ex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_cortex.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pwr.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash.h;Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash_ex.h;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c;Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c;Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/core_sc300.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f100xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f102x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f100xe.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xg.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/system_stm32f1xx.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101xe.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101x6.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xe.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f107xc.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f105xc.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f102xb.h;Drivers/CMSIS/Device/ST/STM32F1xx/Include/stm32f101xg.h; - [PreviousUsedRideFiles] HeaderPath=../Drivers/STM32F1xx_HAL_Driver/Inc;../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Include;../Drivers/CMSIS/Device/ST/STM32F1xx/Include; SourceFiles=../Src/main.c;../Src/gpio.c;../Src/usart.c;../Src/stm32f1xx_it.c;../Src/stm32f1xx_hal_msp.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c;../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c;../Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c;../Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/startup_stm32f103xb.s; diff --git a/Inc/mxconstants.h b/Inc/mxconstants.h index 0e9f6ba..13f35b0 100644 --- a/Inc/mxconstants.h +++ b/Inc/mxconstants.h @@ -43,6 +43,16 @@ #define LED1_Pin GPIO_PIN_13 #define LED1_GPIO_Port GPIOC +#define WSDATA_Pin GPIO_PIN_11 +#define WSDATA_GPIO_Port GPIOB +#define BTN1_Pin GPIO_PIN_5 +#define BTN1_GPIO_Port GPIOB +#define BTN2_Pin GPIO_PIN_6 +#define BTN2_GPIO_Port GPIOB +#define BTN3_Pin GPIO_PIN_7 +#define BTN3_GPIO_Port GPIOB +#define BTN4_Pin GPIO_PIN_8 +#define BTN4_GPIO_Port GPIOB /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ diff --git a/Src/gpio.c b/Src/gpio.c index b9ced21..53de217 100644 --- a/Src/gpio.c +++ b/Src/gpio.c @@ -60,17 +60,33 @@ void MX_GPIO_Init(void) /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(WSDATA_GPIO_Port, WSDATA_Pin, GPIO_PIN_RESET); + /*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = LED1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct); + /*Configure GPIO pin : PtPin */ + GPIO_InitStruct.Pin = WSDATA_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + HAL_GPIO_Init(WSDATA_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pins : PBPin PBPin PBPin PBPin */ + GPIO_InitStruct.Pin = BTN1_Pin|BTN2_Pin|BTN3_Pin|BTN4_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } /* USER CODE BEGIN 2 */ diff --git a/User/handlers.c b/User/handlers.c index bf6301e..af8bdab 100644 --- a/User/handlers.c +++ b/User/handlers.c @@ -3,20 +3,11 @@ // #include +#include "utils/ws2812.h" #include "utils/timebase.h" #include "utils/debug.h" #include "handlers.h" -/** - * @brief Handle a button press. Delete if not needed - a possible callback for debouncer. - * @param button: button identifier - * @param press: press state (1 = just pressed, 0 = just released) - */ -void ButtonHandler(uint32_t button, bool press) -{ - dbg("Button %d, state %d", button, press); -} - /** * Increment timebase counter each ms. * This is called by HAL, weak override. diff --git a/User/handlers.h b/User/handlers.h index 659d30e..a9f7221 100644 --- a/User/handlers.h +++ b/User/handlers.h @@ -7,8 +7,6 @@ #include -void ButtonHandler(uint32_t button, bool press); - void user_Error_Handler(); void user_assert_failed(uint8_t* file, uint32_t line); diff --git a/User/init.c b/User/init.c index f80314c..cea4d0d 100644 --- a/User/init.c +++ b/User/init.c @@ -5,7 +5,7 @@ #include #include "utils/debounce.h" #include "init.h" -#include "handlers.h" +#include "user_main.h" static void init_buttons() { @@ -15,9 +15,21 @@ static void init_buttons() debo.GPIOx = GPIOB; // All buttons are on port B debo.callback = ButtonHandler; - //debo.pin = BTN1_Pin; - //debo.cb_payload = 1; - //debo_register_pin(&debo); + debo.pin = BTN1_Pin; + debo.cb_payload = 0; + debo_register_pin(&debo); + + debo.pin = BTN2_Pin; + debo.cb_payload = 1; + debo_register_pin(&debo); + + debo.pin = BTN3_Pin; + debo.cb_payload = 2; + debo_register_pin(&debo); + + debo.pin = BTN4_Pin; + debo.cb_payload = 3; + debo_register_pin(&debo); } /** Init the application */ diff --git a/User/user_main.c b/User/user_main.c index d51f6bd..d8f3973 100644 --- a/User/user_main.c +++ b/User/user_main.c @@ -3,10 +3,221 @@ // #include +#include +#include "init.h" +#include "utils/ws2812.h" #include "utils/timebase.h" #include "utils/debug.h" #include "user_main.h" -#include "init.h" + +//region Colors + +#define C_DARK rgb(0,0,0) +#define C_DIMWHITE rgb(15,15,15) +#define C_OKGREEN rgb(5,40,0) +#define C_CRIMSON rgb(140,0,3) + +#define C_DIMRED rgb(20,0,0) +#define C_DIMGREEN rgb(0,20,0) +#define C_DIMBLUE rgb(0,0,35) +#define C_DIMYELLOW rgb(15,10,0) + +#define C_BRTRED rgb(120,0,0) +#define C_BRTGREEN rgb(2,80,0) +#define C_BRTBLUE rgb(0,0,180) +#define C_BRTYELLOW rgb(70,60,0) + +// assign to positions + +#define C_DIM1 C_DIMRED +#define C_DIM2 C_DIMGREEN +#define C_DIM3 C_DIMBLUE +#define C_DIM4 C_DIMYELLOW + +#define C_BRT1 C_BRTRED +#define C_BRT2 C_BRTGREEN +#define C_BRT3 C_BRTBLUE +#define C_BRT4 C_BRTYELLOW + +//endregion + +/** Current game state */ +enum GameState_enum { + STATE_NEW_GAME, // new game, waiting for key + STATE_REPLAY, // showing sequence + STATE_USER_INPUT, // waiting for user input of repeated sequence + STATE_SUCCESS_EFFECT, // entered OK, show some fireworks + STATE_FAIL_EFFECT, // entered wrong, show FAIL animation, then reset. +} GameState = STATE_NEW_GAME; + +/** Screen colors */ +uint32_t screen[4] = {0, 0, 0, 0}; +const uint32_t brt[4] = {C_BRT1, C_BRT2, C_BRT3, C_BRT4}; +const uint32_t dim[4] = {C_DIM1, C_DIM2, C_DIM3, C_DIM4}; +const uint32_t dark[4] = {C_DARK, C_DARK, C_DARK, C_DARK}; + +#define REPLAY_INTERVAL 400 +#define REPLAY_INTERVAL_GAP 75 +#define SUC_EFF_TIME 500 +#define FAIL_EFF_TIME 1000 + +/** Sequence of colors to show. Seed is constant thorough a game. + * rng_state is used by rand_r() for building the sequence. */ +uint32_t game_seed; +unsigned int game_rng_state; + +/** Nr of revealed colors in sequence */ +uint32_t game_revealed_n; +/** Nr of next color to replay/input */ +uint32_t game_replay_n; +/** Nr of succ repeated colors */ +uint32_t game_repeat_n; + +void enter_state(enum GameState_enum state); + +/** Show current screen colors */ +void show_screen() +{ + ws2812_send(WSDATA_GPIO_Port, WSDATA_Pin, screen, 4); +} + +/** Prepare rng sequence for replay / test */ +void reset_sequence() +{ + game_rng_state = game_seed; +} + +/** Get next item in the sequence */ +uint32_t get_next_item() +{ + return (uint32_t) rand_r(&game_rng_state) & 0x03; +} + +/** Enter state - callback for delayed state change */ +void deferred_enter_state(void *state) +{ + enter_state((enum GameState_enum) state); +} + +/** Future task CB in replay seq */ +void replay_callback(void *onOff) +{ + bool on = (bool) onOff; + + screen[0] = C_DARK; + screen[1] = C_DARK; + screen[2] = C_DARK; + screen[3] = C_DARK; + + if (on) { + uint32_t color = get_next_item(); + game_replay_n++; + screen[color] = brt[color]; + show_screen(); + schedule_task(replay_callback, (void *) 0, REPLAY_INTERVAL, false); + } else { + // turning off + show_screen(); + + // Schedule next turning ON + if (game_replay_n < game_revealed_n) { + schedule_task(replay_callback, (void *) 1, REPLAY_INTERVAL_GAP, false); + } else { + enter_state(STATE_USER_INPUT); + //schedule_task(deferred_enter_state, (void *) STATE_USER_INPUT, 50, false); + } + } +} + +/** SUCCESS effect */ +void suc_eff_callback(void *onOff) +{ + bool on = (bool) onOff; + + if (on) { + for (int i = 0; i < 4; i++) screen[i] = C_OKGREEN; + schedule_task(suc_eff_callback, 0, SUC_EFF_TIME, false); + } else { + for (int i = 0; i < 4; i++) screen[i] = C_DARK; + + schedule_task(deferred_enter_state, (void *) STATE_REPLAY, 200, false); + } + + show_screen(); +} + +/** ERROR effect */ +void fail_eff_callback(void *onOff) +{ + bool on = (bool) onOff; + + if (on) { + for (int i = 0; i < 4; i++) screen[i] = C_CRIMSON; + schedule_task(fail_eff_callback, 0, FAIL_EFF_TIME, false); + } else { + for (int i = 0; i < 4; i++) screen[i] = C_DARK; + + schedule_task(deferred_enter_state, (void *) STATE_NEW_GAME, 200, false); + } + + show_screen(); +} + +/** + * @brief Enter a game state + * @param state + */ +void enter_state(enum GameState_enum state) +{ + GameState = state; + + switch (state) { + case STATE_NEW_GAME: + // new game - idle state before new game is started + + // all dimly lit + for (int i = 0; i < 4; i++) screen[i] = C_DIMWHITE; + + break; + + case STATE_REPLAY: + game_replay_n = 0; + reset_sequence(); + + // Start replay + replay_callback((void *) 1); + break; + + case STATE_USER_INPUT: + memcpy(screen, dim, sizeof(screen)); + + // Start entering & checking + game_repeat_n = 0; + reset_sequence(); + break; + + case STATE_SUCCESS_EFFECT: + memcpy(screen, dim, sizeof(screen)); + //suc_eff_callback((void *) 1); + schedule_task(suc_eff_callback, (void *) 1, 250, false); + break; + + case STATE_FAIL_EFFECT: + memcpy(screen, dim, sizeof(screen)); + //fail_eff_callback((void *) 1); + schedule_task(fail_eff_callback, (void *) 1, 250, false); + break; + } + + show_screen(); +} + +/** Prepare new sequence, using time for seed. */ +void prepare_sequence() +{ + game_seed = ms_now(); + game_rng_state = game_seed; +} /** Main function, called from MX-generated main.c */ void user_main() @@ -15,6 +226,9 @@ void user_main() user_init(); + enter_state(STATE_NEW_GAME); + // we'll init the sequence when user first presses a button - the time is used as a seed + ms_time_t counter1 = 0; while (1) { if (ms_loop_elapsed(&counter1, 1000)) { @@ -23,3 +237,64 @@ void user_main() } } } + +/** + * @brief Handle a button press. Callback for debouncer. + * @param button: button identifier + * @param press: press state (1 = just pressed, 0 = just released) + */ +void ButtonHandler(uint32_t button, bool press) +{ + dbg("Button %d, state %d", button, press); + + switch (GameState) { + case STATE_NEW_GAME: + if (!press) { // released + // user wants to start playing + prepare_sequence(); + game_revealed_n = 1; // start with 1 revealed + + // darken + memcpy(screen, dark, sizeof(screen)); + show_screen(); + + // start playback with a delay + // this makes it obvious the playback is not a feedback to the pressed button + schedule_task(deferred_enter_state, (void *) STATE_REPLAY, 250, false); + //enter_state(STATE_REPLAY); + } + break; + case STATE_USER_INPUT: + // user is entering a color + memcpy(screen, dim, sizeof(screen)); + + if (press) { + // Button is down + screen[button] = brt[button]; + } else { + // Button is released + // Verify correctness + uint32_t expected = get_next_item(); + if (expected == button) { + // good! + game_repeat_n++; + if (game_repeat_n == game_revealed_n) { + // repeated all, good work! + game_revealed_n++; + enter_state(STATE_SUCCESS_EFFECT); + } + } else { + enter_state(STATE_FAIL_EFFECT); + } + } + + show_screen(); + + break; + + default: + // discard button press, not expecting input now + break; + + } +} diff --git a/User/user_main.h b/User/user_main.h index 91d13ae..2633a2f 100644 --- a/User/user_main.h +++ b/User/user_main.h @@ -7,6 +7,8 @@ #include +void ButtonHandler(uint32_t button, bool press); + void user_main(); #endif //MPORK_USER_MAIN_H diff --git a/User/utils/ws2812.c b/User/utils/ws2812.c new file mode 100644 index 0000000..c9c0dbe --- /dev/null +++ b/User/utils/ws2812.c @@ -0,0 +1,64 @@ +#include "ws2812.h" +#include "utils/timebase.h" + +#define LONG_DELAY() for (volatile uint32_t __j = 4; __j > 0; __j--) +#define SHORT_DELAY() for (volatile uint32_t __j = 1; __j > 0; __j--) + +static inline +__attribute__((always_inline)) +void ws2812_byte(GPIO_TypeDef *GPIOx, uint16_t pin, uint8_t b) +{ + for (register volatile uint8_t i = 0; i < 8; i++) { + GPIOx->BSRR = pin; // set pin high + + // duty cycle determines bit value + if (b & 0x80) { + LONG_DELAY(); + GPIOx->BRR = pin; // set pin low + SHORT_DELAY(); + } else { + SHORT_DELAY(); + GPIOx->BRR = pin; // set pin low + LONG_DELAY(); + } + + b <<= 1; // shift to next bit + } +} + +/** Set many RGBs */ +void ws2812_send(GPIO_TypeDef *GPIOx, uint16_t pin, uint32_t *rgbs, uint32_t count) +{ + __disable_irq(); + + for (int i = 0; i < count; i++) { + uint32_t rgb = *rgbs++; + ws2812_byte(GPIOx, pin, rgb_g(rgb)); + ws2812_byte(GPIOx, pin, rgb_r(rgb)); + ws2812_byte(GPIOx, pin, rgb_b(rgb)); + } + + __enable_irq(); + + ws2812_flip(); // show +} + +/** Send a single color. */ +void ws2812_single(GPIO_TypeDef *GPIOx, uint16_t pin, uint32_t rgb) +{ + __disable_irq(); + + ws2812_byte(GPIOx, pin, rgb_g(rgb)); + ws2812_byte(GPIOx, pin, rgb_r(rgb)); + ws2812_byte(GPIOx, pin, rgb_b(rgb)); + + __enable_irq(); +} + +/** + * @brief Wait the necessary time for the colors sent using ws2812_single() to show. + */ +void ws2812_flip() +{ + delay_us(50); // show +} diff --git a/User/utils/ws2812.h b/User/utils/ws2812.h new file mode 100644 index 0000000..ac5e99e --- /dev/null +++ b/User/utils/ws2812.h @@ -0,0 +1,92 @@ +#ifndef MPORK_WS2812_H +#define MPORK_WS2812_H + +/* Includes ------------------------------------------------------------------*/ + +#include + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +// PB8 - WS2812B data line +#define COLORLED_GPIO GPIOC +#define COLORLED_PIN GPIO15 + +#define RGB_RED rgb(255, 0, 0) +#define RGB_ORANGE rgb(255, 110, 0) +#define RGB_YELLOW rgb(255, 255, 0) +#define RGB_LIME rgb(160, 255, 0) +#define RGB_GREEN rgb( 0, 255, 0) +#define RGB_CYAN rgb( 0, 255, 120) +#define RGB_BLUE rgb( 0, 0, 255) +#define RGB_MAGENTA rgb(255, 0, 255) +#define RGB_WHITE rgb(255, 255, 255) +#define RGB_BLACK rgb( 0, 0, 0) + +/* Exported macros -----------------------------------------------------------*/ + +/** + * @brief Compose an RGB color. + * @param r, g, b - components 0xFF + * @returns integer 0xRRGGBB + */ +#define rgb(r, g, b) (((0xFF & (r)) << 16) | ((0xFF & (g)) << 8) | (0xFF & (b))) + +/* Get components */ +#define rgb_r(rgb) (((rgb) >> 16) & 0xFF) +#define rgb_g(rgb) (((rgb) >> 8) & 0xFF) +#define rgb_b(rgb) ((rgb) & 0xFF) + +/* Exported functions --------------------------------------------------------*/ + +/** + * @brief Struct for easy manipulation of RGB colors. + * + * Set components in the xrgb.r (etc.) and you will get + * the hex in xrgb.num. + */ +typedef union { + + /** Struct for access to individual color components */ + struct __attribute__((packed)) { + uint8_t b; + uint8_t g; + uint8_t r; + }; + + /** RGB color as a single uint32_t */ + uint32_t num; + +} ws2812_rgb_t; + + +/** + * @brief Macro to compose the RGB struct. + * + * You can also use {.num = 0xFF0000} to set the hex directly. + */ +#define WS2812_RGB(r, g, b) {.num = (((r) & 0xFF) << 16) | (((g) & 0xFF) << 8) | ((b) & 0xFF)} + +/** + * @brief Send a sequence of colors, then display it. + * @param GPIOx + * @param pin + * @param rgbs : array of colors + * @param count : array length + */ +void ws2812_send(GPIO_TypeDef *GPIOx, uint16_t pin, uint32_t *rgbs, uint32_t count); + +/** + * @brief Send a single color. + * @param GPIOx + * @param pin + * @param rgb : color to show + */ +void ws2812_single(GPIO_TypeDef *GPIOx, uint16_t pin, uint32_t rgb); + +/** + * @brief Wait the necessary time for the colors sent using ws2812_single() to show. + */ +void ws2812_flip(); + +#endif //MPORK_WS2812_H diff --git a/f103-bluepill.ioc b/f103-bluepill.ioc index 9b32b20..5dec468 100644 --- a/f103-bluepill.ioc +++ b/f103-bluepill.ioc @@ -11,14 +11,19 @@ Mcu.Name=STM32F103C(8-B)Tx Mcu.Package=LQFP48 Mcu.Pin0=PC13-TAMPER-RTC Mcu.Pin1=PC14-OSC32_IN +Mcu.Pin10=PB7 +Mcu.Pin11=PB8 +Mcu.Pin12=VP_SYS_VS_ND +Mcu.Pin13=VP_SYS_VS_Systick Mcu.Pin2=PC15-OSC32_OUT Mcu.Pin3=PD0-OSC_IN Mcu.Pin4=PD1-OSC_OUT -Mcu.Pin5=PA9 -Mcu.Pin6=PA10 -Mcu.Pin7=VP_SYS_VS_ND -Mcu.Pin8=VP_SYS_VS_Systick -Mcu.PinsNb=9 +Mcu.Pin5=PB11 +Mcu.Pin6=PA9 +Mcu.Pin7=PA10 +Mcu.Pin8=PB5 +Mcu.Pin9=PB6 +Mcu.PinsNb=14 Mcu.UserConstants= Mcu.UserName=STM32F103C8Tx MxCube.Version=4.16.0 @@ -37,6 +42,31 @@ PA10.Mode=Asynchronous PA10.Signal=USART1_RX PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PB11.GPIOParameters=GPIO_Speed,GPIO_Label +PB11.GPIO_Label=WSDATA +PB11.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM +PB11.Locked=true +PB11.Signal=GPIO_Output +PB5.GPIOParameters=GPIO_PuPd,GPIO_Label +PB5.GPIO_Label=BTN1 +PB5.GPIO_PuPd=GPIO_PULLUP +PB5.Locked=true +PB5.Signal=GPIO_Input +PB6.GPIOParameters=GPIO_PuPd,GPIO_Label +PB6.GPIO_Label=BTN2 +PB6.GPIO_PuPd=GPIO_PULLUP +PB6.Locked=true +PB6.Signal=GPIO_Input +PB7.GPIOParameters=GPIO_PuPd,GPIO_Label +PB7.GPIO_Label=BTN3 +PB7.GPIO_PuPd=GPIO_PULLUP +PB7.Locked=true +PB7.Signal=GPIO_Input +PB8.GPIOParameters=GPIO_PuPd,GPIO_Label +PB8.GPIO_Label=BTN4 +PB8.GPIO_PuPd=GPIO_PULLUP +PB8.Locked=true +PB8.Signal=GPIO_Input PC13-TAMPER-RTC.GPIOParameters=GPIO_Label PC13-TAMPER-RTC.GPIO_Label=LED1 PC13-TAMPER-RTC.Locked=true