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