Еще больше рефакторинга
- Выделение меню в отдельную группу - Добавление отдельных модулей для функционала игр и для функционала часов - Переход на 5 компилятор, чтобы прошивка меньше весила (не влезает в C6) - Фикс варнингов для 5 компилятора
This commit is contained in:
@@ -23,4 +23,4 @@ void ClockManager_SetDuty(uint8_t value);
|
||||
// Сброс времени на 00:00:00
|
||||
void ClockManager_ResetTime(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -104,4 +104,4 @@ void Melody_Update(MelodyHandle* mh) {
|
||||
|
||||
uint8_t Melody_IsPlaying(MelodyHandle* mh) {
|
||||
return mh->is_playing;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ void Melody_Stop(MelodyHandle* mh);
|
||||
void Melody_Update(MelodyHandle* mh);
|
||||
uint8_t Melody_IsPlaying(MelodyHandle* mh);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -158,4 +158,4 @@ typedef struct {
|
||||
#define NOTE_REST 0
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -13,13 +13,13 @@ volatile uint8_t GLOBAL_BRIGHTNESS = 100; // Глобальная ярко
|
||||
#define SWAP_BIT5_BIT6(x) (((x) & 0x9F) | (((x) & 0x20) << 1) | (((x) & 0x40) >> 1))
|
||||
|
||||
// Макросы для быстрой работы с пинами (вместо HAL_GPIO_WritePin)
|
||||
#define SET_SEGMENT_A(val) SEGMENT_A_GPIO_Port->BSRR = (SEGMENT_A_Pin << 16) | ((val) ? 0 : SEGMENT_A_Pin)
|
||||
#define SET_SEGMENT_B(val) SEGMENT_B_GPIO_Port->BSRR = (SEGMENT_B_Pin << 16) | ((val) ? 0 : SEGMENT_B_Pin)
|
||||
#define SET_SEGMENT_C(val) SEGMENT_C_GPIO_Port->BSRR = (SEGMENT_C_Pin << 16) | ((val) ? 0 : SEGMENT_C_Pin)
|
||||
#define SET_SEGMENT_D(val) SEGMENT_D_GPIO_Port->BSRR = (SEGMENT_D_Pin << 16) | ((val) ? 0 : SEGMENT_D_Pin)
|
||||
#define SET_SEGMENT_E(val) SEGMENT_E_GPIO_Port->BSRR = (SEGMENT_E_Pin << 16) | ((val) ? 0 : SEGMENT_E_Pin)
|
||||
#define SET_SEGMENT_F(val) SEGMENT_F_GPIO_Port->BSRR = (SEGMENT_F_Pin << 16) | ((val) ? 0 : SEGMENT_F_Pin)
|
||||
#define SET_SEGMENT_G(val) SEGMENT_G_GPIO_Port->BSRR = (SEGMENT_G_Pin << 16) | ((val) ? 0 : SEGMENT_G_Pin)
|
||||
#define SET_SEGMENT_A(val) SEGMENT_A_GPIO_Port->BSRR = ((uint32_t)SEGMENT_A_Pin << 16) | ((val) ? 0 : SEGMENT_A_Pin)
|
||||
#define SET_SEGMENT_B(val) SEGMENT_B_GPIO_Port->BSRR = ((uint32_t)SEGMENT_B_Pin << 16) | ((val) ? 0 : SEGMENT_B_Pin)
|
||||
#define SET_SEGMENT_C(val) SEGMENT_C_GPIO_Port->BSRR = ((uint32_t)SEGMENT_C_Pin << 16) | ((val) ? 0 : SEGMENT_C_Pin)
|
||||
#define SET_SEGMENT_D(val) SEGMENT_D_GPIO_Port->BSRR = ((uint32_t)SEGMENT_D_Pin << 16) | ((val) ? 0 : SEGMENT_D_Pin)
|
||||
#define SET_SEGMENT_E(val) SEGMENT_E_GPIO_Port->BSRR = ((uint32_t)SEGMENT_E_Pin << 16) | ((val) ? 0 : SEGMENT_E_Pin)
|
||||
#define SET_SEGMENT_F(val) SEGMENT_F_GPIO_Port->BSRR = ((uint32_t)SEGMENT_F_Pin << 16) | ((val) ? 0 : SEGMENT_F_Pin)
|
||||
#define SET_SEGMENT_G(val) SEGMENT_G_GPIO_Port->BSRR = ((uint32_t)SEGMENT_G_Pin << 16) | ((val) ? 0 : SEGMENT_G_Pin)
|
||||
|
||||
// ==================== Таблица символов ====================
|
||||
// Для общего анода: 0 - сегмент горит, 1 - сегмент не горит
|
||||
|
||||
@@ -31,4 +31,4 @@ void Segment_SetBrightness(uint8_t percent);
|
||||
// Вызывается каждые PROCESS_INTERVAL_US микросекунд или из таймера
|
||||
void Segment_Process(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -123,4 +123,4 @@ static const Note_t Polyphia_PlayingGod_Notes[] = {
|
||||
{SI2, NOTE_SIXTEENTH},
|
||||
{MI3, NOTE_SIXTEENTH},
|
||||
};
|
||||
static Melody_t Polyphia_PlayingGod = {song_length(Polyphia_PlayingGod_Notes), Polyphia_PlayingGod_Notes};
|
||||
static Melody_t Polyphia_PlayingGod = {song_length(Polyphia_PlayingGod_Notes), Polyphia_PlayingGod_Notes};
|
||||
|
||||
@@ -51,4 +51,4 @@ static const Note_t SFX_Alarm_Notes[] = {
|
||||
{NOTE_REST, NOTE_EIGHTH},
|
||||
{LA4, NOTE_EIGHTH}
|
||||
};
|
||||
static Melody_t SFX_Alarm = {song_length(SFX_Alarm_Notes), SFX_Alarm_Notes};
|
||||
static Melody_t SFX_Alarm = {song_length(SFX_Alarm_Notes), SFX_Alarm_Notes};
|
||||
|
||||
208
Core/Menu/clock.c
Normal file
208
Core/Menu/clock.c
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "menu_items.h"
|
||||
#include "segment.h"
|
||||
#include "clock_manager.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t startTime;
|
||||
uint32_t elapsedTime; // Íàêîïëåííîå âðåìÿ ïðè ïàóçå
|
||||
bool running;
|
||||
uint8_t state; // 0 = Ñáðîøåí, 1 = Çàïóùåí, 2 = Ïàóçà
|
||||
} StopwatchData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t targetTime; // Öåëåâîå âðåìÿ â ìñ
|
||||
uint32_t startTime;
|
||||
uint32_t elapsedTime; // Íàêîïëåííîå âðåìÿ ïðè ïàóçå
|
||||
uint8_t editStep; // 0-5: ðàçðÿäû, 6: ãîòîâî
|
||||
uint8_t state; // 0 = Íàñòðîéêà, 1 = Çàïóùåí, 2 = Ïàóçà, 3 = Çàâåðøåí
|
||||
bool running;
|
||||
bool blinkState;
|
||||
uint32_t lastBlink;
|
||||
} TimerData;
|
||||
|
||||
static StopwatchData g_stopwatch;
|
||||
static TimerData g_timer;
|
||||
|
||||
// Âñïîìîãàòåëüíàÿ ôóíêöèÿ äëÿ ôîðìàòèðîâàíèÿ ìì:ññ:öñ
|
||||
static void FormatTime(uint32_t ms, char* buf) {
|
||||
uint32_t total_sec = ms / 1000;
|
||||
uint32_t minutes = total_sec / 60;
|
||||
uint32_t seconds = total_sec % 60;
|
||||
uint32_t centiseconds = (ms % 1000) / 10;
|
||||
|
||||
if (minutes > 0) {
|
||||
sprintf(buf, "%2d%02d%02d", minutes, seconds, centiseconds);
|
||||
} else {
|
||||
sprintf(buf, " %2d%02d", seconds, centiseconds);
|
||||
}
|
||||
}
|
||||
|
||||
/////// CLOCK ////////
|
||||
static void Display_Clock(void) {
|
||||
time_t now = ClockManager_GetTime(1);
|
||||
char buf[7];
|
||||
sprintf(buf, "%02d%02d%02d", now.hour, now.min, now.sec);
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void OnEnter_Clock(void) {
|
||||
g_currentActivity = &g_clockNode;
|
||||
g_rootMenu.parent = &g_clockNode;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void Clock_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
/////// ÑÅÊÓÍÄÎÌÅÐ ////////
|
||||
static void Display_Stopwatch(void) {
|
||||
char buf[7];
|
||||
uint32_t current_ms = 0;
|
||||
|
||||
switch (g_stopwatch.state) {
|
||||
case 0: // Ñáðîøåí
|
||||
sprintf(buf, " 000");
|
||||
break;
|
||||
case 1: // Çàïóùåí
|
||||
current_ms = (HAL_GetTick() - g_stopwatch.startTime) + g_stopwatch.elapsedTime;
|
||||
FormatTime(current_ms, buf);
|
||||
break;
|
||||
case 2: // Ïàóçà
|
||||
FormatTime(g_stopwatch.elapsedTime, buf);
|
||||
break;
|
||||
default:
|
||||
sprintf(buf, "ERROR");
|
||||
break;
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void OnUpdate_Stopwatch(void) {
|
||||
// Äëÿ ñåêóíäîìåðà íå íóæåí îòäåëüíûé update,
|
||||
// ò.ê. Display îáíîâëÿåòñÿ ïî òàéìåðó ìåíþ
|
||||
static uint32_t lastUpdate = 0;
|
||||
if (g_stopwatch.state == 1) {
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (tick - lastUpdate >= 10) { // Îáíîâëåíèå êàæäûå 10 ìñ
|
||||
lastUpdate = tick;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OnEnter_Stopwatch(void) {
|
||||
g_currentActivity = &g_stopwatchNode;
|
||||
g_rootMenu.parent = &g_stopwatchNode;
|
||||
g_stopwatch.state = 0;
|
||||
g_stopwatch.running = false;
|
||||
g_stopwatch.elapsedTime = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void Stopwatch_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t tick = HAL_GetTick();
|
||||
|
||||
if (g_stopwatch.state == 0 && btn == BUTTON_SELECT) {
|
||||
// Ñòàðò
|
||||
g_stopwatch.state = 1;
|
||||
g_stopwatch.running = true;
|
||||
g_stopwatch.startTime = tick;
|
||||
g_stopwatch.elapsedTime = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_stopwatch.state == 1 && btn == BUTTON_SELECT) {
|
||||
// Ïàóçà
|
||||
g_stopwatch.state = 2;
|
||||
g_stopwatch.running = false;
|
||||
g_stopwatch.elapsedTime += tick - g_stopwatch.startTime;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_stopwatch.state == 2 && btn == BUTTON_SELECT) {
|
||||
// Ïðîäîëæèòü
|
||||
g_stopwatch.state = 1;
|
||||
g_stopwatch.running = true;
|
||||
g_stopwatch.startTime = tick;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((g_stopwatch.state == 1 || g_stopwatch.state == 2) && btn == BUTTON_BACK) {
|
||||
// Ñáðîñ
|
||||
g_stopwatch.state = 0;
|
||||
g_stopwatch.running = false;
|
||||
g_stopwatch.elapsedTime = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/////// ÒÀÉÌÅÐ ////////
|
||||
|
||||
static void Display_Timer(void) {
|
||||
Segment_SetString("FUTURE");
|
||||
}
|
||||
|
||||
static void OnUpdate_Timer(void) {
|
||||
}
|
||||
|
||||
static void OnEnter_Timer(void) {
|
||||
}
|
||||
|
||||
static void Timer_OnButton(Button_Type btn, bool longPress) {
|
||||
}
|
||||
|
||||
// NODES
|
||||
MenuNode g_clockNode = {
|
||||
.name = "CLOC",
|
||||
.parent = NULL,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.needsRedraw = 1,
|
||||
.display = Display_Clock,
|
||||
.onEnter = OnEnter_Clock,
|
||||
.onUpdate = NULL,
|
||||
.onButton = Clock_OnButton,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
MenuNode g_stopwatchNode = {
|
||||
.name = "SECOND",
|
||||
.parent = NULL,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.needsRedraw = 1,
|
||||
.display = Display_Stopwatch,
|
||||
.onEnter = OnEnter_Stopwatch,
|
||||
.onUpdate = OnUpdate_Stopwatch,
|
||||
.onButton = Stopwatch_OnButton,
|
||||
.data = &g_stopwatch
|
||||
};
|
||||
|
||||
MenuNode g_timerNode = {
|
||||
.name = "TIMER",
|
||||
.parent = NULL,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.needsRedraw = 1,
|
||||
.display = Display_Timer,
|
||||
.onEnter = OnEnter_Timer,
|
||||
.onUpdate = OnUpdate_Timer,
|
||||
.onButton = Timer_OnButton,
|
||||
.data = &g_timer
|
||||
};
|
||||
9
Core/Menu/clock.h
Normal file
9
Core/Menu/clock.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef GAMES_H
|
||||
#define GAMES_H
|
||||
|
||||
#include "menu.h"
|
||||
extern MenuNode g_clockNode;
|
||||
extern MenuNode g_timerNode;
|
||||
extern MenuNode g_stopwatchNode;
|
||||
|
||||
#endif
|
||||
275
Core/Menu/games.c
Normal file
275
Core/Menu/games.c
Normal file
@@ -0,0 +1,275 @@
|
||||
#include "menu_items.h"
|
||||
#include "segment.h"
|
||||
#include "clock_manager.h"
|
||||
#include "menu_items.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t startTime;
|
||||
uint32_t pressTime;
|
||||
bool celebrating;
|
||||
bool result;
|
||||
int32_t diff_ms;
|
||||
uint8_t state;
|
||||
} Game1SecData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t waitStart;
|
||||
uint32_t ledOnTime;
|
||||
uint32_t reactionTime;
|
||||
uint8_t state;
|
||||
} GameReactionData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t endTime;
|
||||
uint16_t clicks;
|
||||
bool active;
|
||||
bool finished;
|
||||
} GameClickerData;
|
||||
|
||||
static Game1SecData g_game1sec;
|
||||
static GameReactionData g_gameReaction;
|
||||
static GameClickerData g_gameClicker;
|
||||
|
||||
|
||||
/////// ZERO MILLIS ////////
|
||||
static void Display_ZeroMillis(void) {
|
||||
char buf[7];
|
||||
switch (g_game1sec.state) {
|
||||
case 0:
|
||||
g_game1sec.celebrating = 0;
|
||||
sprintf(buf, "START"); break;
|
||||
case 1:
|
||||
g_game1sec.diff_ms = (HAL_GetTick() - g_game1sec.startTime);
|
||||
case 2:
|
||||
sprintf(buf, " %4d", g_game1sec.diff_ms/10);
|
||||
break;
|
||||
default: sprintf(buf, "ERROR"); break;
|
||||
}
|
||||
if(g_game1sec.state == 2)
|
||||
{
|
||||
if((g_game1sec.diff_ms/10)%100 == 0)
|
||||
{
|
||||
if(!g_game1sec.celebrating)
|
||||
{
|
||||
g_game1sec.celebrating = 1;
|
||||
Melody_Play(&melody, &Polyphia_PlayingGod, 134);
|
||||
}
|
||||
}
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void OnEnter_ZeroMillis(void) {
|
||||
g_game1sec.state = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void ZeroMillis_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (g_game1sec.state == 0 && btn == BUTTON_SELECT) {
|
||||
g_game1sec.state = 1;
|
||||
g_game1sec.startTime = tick;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((btn == BUTTON_SELECT) && (g_game1sec.state == 1)) {
|
||||
g_game1sec.state = 2;
|
||||
g_game1sec.pressTime = HAL_GetTick();
|
||||
g_game1sec.diff_ms = (g_game1sec.pressTime - g_game1sec.startTime);
|
||||
if (g_game1sec.diff_ms < 0) g_game1sec.diff_ms = -g_game1sec.diff_ms;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((g_game1sec.state == 2) && (btn == BUTTON_SELECT))
|
||||
{
|
||||
g_game1sec.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////// REACTION ////////
|
||||
static void OnUpdate_Reaction(void) {
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (g_gameReaction.state == 1) {
|
||||
if (tick - g_gameReaction.waitStart >= g_gameReaction.ledOnTime) {
|
||||
g_gameReaction.state = 2;
|
||||
g_gameReaction.waitStart = tick;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
else if (g_gameReaction.state == 2) {
|
||||
if (tick - g_gameReaction.waitStart >= 2000) {
|
||||
g_gameReaction.state = 3;
|
||||
g_gameReaction.reactionTime = 999;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Display_Reaction(void) {
|
||||
char buf[7];
|
||||
switch (g_gameReaction.state) {
|
||||
case 0: sprintf(buf, "START"); break;
|
||||
case 1: sprintf(buf, " "); break;
|
||||
case 2: sprintf(buf, "888888"); break;
|
||||
case 3: sprintf(buf, "%6d", g_gameReaction.reactionTime); break;
|
||||
case 4: sprintf(buf, "FAIL"); break;
|
||||
default: sprintf(buf, "ERROR"); break;
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
|
||||
static void OnEnter_Reaction(void) {
|
||||
g_gameReaction.state = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void Reaction_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (g_gameReaction.state == 0 && btn == BUTTON_SELECT) {
|
||||
g_gameReaction.state = 1;
|
||||
g_gameReaction.waitStart = tick;
|
||||
g_gameReaction.ledOnTime = 500 + (rand() % 2000);
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameReaction.state == 1 && btn == BUTTON_SELECT) {
|
||||
g_gameReaction.reactionTime = 0;
|
||||
g_gameReaction.state = 4;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameReaction.state == 2 && btn == BUTTON_SELECT) {
|
||||
g_gameReaction.reactionTime = tick - g_gameReaction.waitStart;
|
||||
g_gameReaction.state = 3;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((g_gameReaction.state >= 3) && (btn == BUTTON_SELECT))
|
||||
{
|
||||
g_gameReaction.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////// CLICLER ////////
|
||||
static void Display_Clicker(void) {
|
||||
char buf[7];
|
||||
if (!g_gameClicker.active && !g_gameClicker.finished) {
|
||||
sprintf(buf, "START");
|
||||
} else if (g_gameClicker.active) {
|
||||
uint32_t remaining = (g_gameClicker.endTime - HAL_GetTick()) / 1000;
|
||||
sprintf(buf, "%2d %3d", remaining, g_gameClicker.clicks);
|
||||
} else {
|
||||
sprintf(buf, " %3d", g_gameClicker.clicks);
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void OnEnter_Clicker(void) {
|
||||
g_gameClicker.active = false;
|
||||
g_gameClicker.finished = false;
|
||||
g_gameClicker.clicks = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void OnUpdate_Clicker(void) {
|
||||
if (g_gameClicker.active && HAL_GetTick() >= g_gameClicker.endTime) {
|
||||
g_gameClicker.active = false;
|
||||
g_gameClicker.finished = true;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
static void Clicker_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
|
||||
if (!g_gameClicker.active && !g_gameClicker.finished && btn == BUTTON_SELECT) {
|
||||
g_gameClicker.active = true;
|
||||
g_gameClicker.endTime = HAL_GetTick() + 10000;
|
||||
g_gameClicker.clicks = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameClicker.active && btn == BUTTON_UP) {
|
||||
g_gameClicker.clicks++;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameClicker.finished && (btn == BUTTON_SELECT))
|
||||
{
|
||||
g_gameClicker.finished = 0;
|
||||
g_gameClicker.active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NODES
|
||||
MenuNode g_ZeroMillisNode = {
|
||||
.name = "00 SEC",
|
||||
.parent = &g_gamesNode,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.needsRedraw = 1,
|
||||
.display = Display_ZeroMillis,
|
||||
.onEnter = OnEnter_ZeroMillis,
|
||||
.onUpdate = NULL,
|
||||
.onButton = ZeroMillis_OnButton,
|
||||
.data = &g_game1sec
|
||||
};
|
||||
|
||||
MenuNode g_ReactionTimeNode = {
|
||||
.name = "CSTEST",
|
||||
.parent = &g_gamesNode,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Reaction,
|
||||
.onEnter = OnEnter_Reaction,
|
||||
.onUpdate = OnUpdate_Reaction,
|
||||
.onButton = Reaction_OnButton,
|
||||
.data = &g_gameReaction
|
||||
};
|
||||
|
||||
MenuNode g_ClickerTimeNode = {
|
||||
.name = "CLICER",
|
||||
.parent = &g_gamesNode,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Clicker,
|
||||
.onEnter = OnEnter_Clicker,
|
||||
.onUpdate = OnUpdate_Clicker,
|
||||
.onButton = Clicker_OnButton,
|
||||
.data = &g_gameClicker
|
||||
};
|
||||
|
||||
MenuNode* g_gamesChildren[3] = {
|
||||
&g_ZeroMillisNode,
|
||||
&g_ReactionTimeNode,
|
||||
&g_ClickerTimeNode
|
||||
};
|
||||
11
Core/Menu/games.h
Normal file
11
Core/Menu/games.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef GAMES_H
|
||||
#define GAMES_H
|
||||
|
||||
#include "menu.h"
|
||||
extern MenuNode g_ZeroMillisNode;
|
||||
extern MenuNode g_ReactionTimeNode;
|
||||
extern MenuNode g_ClickerTimeNode;
|
||||
extern MenuNode* g_gamesChildren[3];
|
||||
|
||||
|
||||
#endif
|
||||
@@ -62,18 +62,20 @@ void Menu_HandleButton(Button_Type btn, bool longPress) {
|
||||
switch (btn) {
|
||||
case BUTTON_UP:
|
||||
SOUND_CLICK;
|
||||
if (g_ctx.currentNode->selectedChild > 0) {
|
||||
g_ctx.currentNode->selectedChild--;
|
||||
g_ctx.needsRedraw = true;
|
||||
g_ctx.currentNode->selectedChild--;
|
||||
if (g_ctx.currentNode->selectedChild > g_ctx.currentNode->childCount - 1) {
|
||||
g_ctx.currentNode->selectedChild = g_ctx.currentNode->childCount - 1;
|
||||
}
|
||||
g_ctx.needsRedraw = true;
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
SOUND_CLICK;
|
||||
if (g_ctx.currentNode->selectedChild < g_ctx.currentNode->childCount - 1) {
|
||||
g_ctx.currentNode->selectedChild++;
|
||||
g_ctx.needsRedraw = true;
|
||||
g_ctx.currentNode->selectedChild++;
|
||||
if (g_ctx.currentNode->selectedChild > g_ctx.currentNode->childCount - 1) {
|
||||
g_ctx.currentNode->selectedChild = 0;
|
||||
}
|
||||
g_ctx.needsRedraw = true;
|
||||
break;
|
||||
|
||||
case BUTTON_SELECT: {
|
||||
@@ -192,4 +194,4 @@ void Menu_Sound_Toggle(void) {
|
||||
|
||||
uint8_t Menu_Sound_IsEnabled(void) {
|
||||
return g_sound_enabled;
|
||||
}
|
||||
}
|
||||
@@ -67,4 +67,4 @@ void Menu_Sound_Off(void);
|
||||
void Menu_Sound_Toggle(void);
|
||||
uint8_t Menu_Sound_IsEnabled(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,19 +1,13 @@
|
||||
#include "menu_items.h"
|
||||
#include "segment.h"
|
||||
#include "clock_manager.h"
|
||||
#include "games.h"
|
||||
#include "clock.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static MenuNode g_rootMenu;
|
||||
// Сначала объявляем узлы активностей
|
||||
MenuNode g_clockNode;
|
||||
MenuNode g_timerNode;
|
||||
MenuNode g_stopwatchNode;
|
||||
MenuNode g_ZeroMillisNode;
|
||||
MenuNode g_ReactionTimeNode;
|
||||
MenuNode g_ClickerTimeNode;
|
||||
|
||||
// Потом объявляем узлы меню
|
||||
MenuNode g_rootMenu;
|
||||
// объявляем узлы меню
|
||||
MenuNode g_gamesNode;
|
||||
MenuNode g_settingsNode;
|
||||
MenuNode g_timeEditNode;
|
||||
@@ -33,106 +27,14 @@ typedef struct {
|
||||
uint32_t lastBlink;
|
||||
} TimeEditData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t startTime;
|
||||
uint32_t pressTime;
|
||||
bool celebrating;
|
||||
bool result;
|
||||
int32_t diff_ms;
|
||||
uint8_t state;
|
||||
} Game1SecData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t waitStart;
|
||||
uint32_t ledOnTime;
|
||||
uint32_t reactionTime;
|
||||
uint8_t state;
|
||||
} GameReactionData;
|
||||
|
||||
typedef struct {
|
||||
uint32_t endTime;
|
||||
uint16_t clicks;
|
||||
bool active;
|
||||
bool finished;
|
||||
} GameClickerData;
|
||||
|
||||
static TimeEditData g_timeData;
|
||||
static uint8_t g_originalDuty;
|
||||
static uint8_t g_editDuty;
|
||||
static Game1SecData g_game1sec;
|
||||
static GameReactionData g_gameReaction;
|
||||
static GameClickerData g_gameClicker;
|
||||
|
||||
// Текущая активность в корне
|
||||
static MenuNode* g_currentActivity = NULL;
|
||||
MenuNode* g_currentActivity = NULL;
|
||||
|
||||
// ==================== Функции отображения активностей ====================
|
||||
static void Display_Clock(void) {
|
||||
time_t now = ClockManager_GetTime(1);
|
||||
char buf[7];
|
||||
sprintf(buf, "%02d%02d%02d", now.hour, now.min, now.sec);
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void Display_Timer(void) {
|
||||
Segment_SetString("TIMER ");
|
||||
}
|
||||
|
||||
static void Display_Stopwatch(void) {
|
||||
Segment_SetString("SECOND ");
|
||||
}
|
||||
|
||||
static void Display_ZeroMillis(void) {
|
||||
char buf[7];
|
||||
switch (g_game1sec.state) {
|
||||
case 0:
|
||||
g_game1sec.celebrating = 0;
|
||||
sprintf(buf, "START"); break;
|
||||
case 1:
|
||||
g_game1sec.diff_ms = (HAL_GetTick() - g_game1sec.startTime);
|
||||
case 2:
|
||||
sprintf(buf, " %4d", g_game1sec.diff_ms/10);
|
||||
break;
|
||||
default: sprintf(buf, "ERROR"); break;
|
||||
}
|
||||
if(g_game1sec.state == 2)
|
||||
{
|
||||
if((g_game1sec.diff_ms/10)%100 == 0)
|
||||
{
|
||||
if(!g_game1sec.celebrating)
|
||||
{
|
||||
g_game1sec.celebrating = 1;
|
||||
Melody_Play(&melody, &Polyphia_PlayingGod, 134);
|
||||
}
|
||||
}
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void Display_Reaction(void) {
|
||||
char buf[7];
|
||||
switch (g_gameReaction.state) {
|
||||
case 0: sprintf(buf, "START"); break;
|
||||
case 1: sprintf(buf, " "); break;
|
||||
case 2: sprintf(buf, "888888"); break;
|
||||
case 3: sprintf(buf, "%6d", g_gameReaction.reactionTime); break;
|
||||
default: sprintf(buf, "ERROR"); break;
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void Display_Clicker(void) {
|
||||
char buf[7];
|
||||
if (!g_gameClicker.active && !g_gameClicker.finished) {
|
||||
sprintf(buf, "START");
|
||||
} else if (g_gameClicker.active) {
|
||||
uint32_t remaining = (g_gameClicker.endTime - HAL_GetTick()) / 1000;
|
||||
sprintf(buf, "%2d %3d", remaining, g_gameClicker.clicks);
|
||||
} else {
|
||||
sprintf(buf, " %3d", g_gameClicker.clicks);
|
||||
}
|
||||
Segment_SetString(buf);
|
||||
}
|
||||
|
||||
static void Display_MenuItem(void) {
|
||||
MenuNode* current = Menu_GetCurrentNode();
|
||||
@@ -172,37 +74,6 @@ static void Display_Reset(void) {
|
||||
}
|
||||
|
||||
// ==================== Вход в активности ====================
|
||||
static void OnEnter_Clock(void) {
|
||||
g_currentActivity = &g_clockNode;
|
||||
g_rootMenu.parent = &g_clockNode;
|
||||
}
|
||||
|
||||
static void OnEnter_Timer(void) {
|
||||
g_currentActivity = &g_timerNode;
|
||||
g_rootMenu.parent = &g_timerNode;
|
||||
}
|
||||
|
||||
static void OnEnter_Stopwatch(void) {
|
||||
g_currentActivity = &g_stopwatchNode;
|
||||
g_rootMenu.parent = &g_stopwatchNode;
|
||||
}
|
||||
|
||||
static void OnEnter_ZeroMillis(void) {
|
||||
g_game1sec.state = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void OnEnter_Reaction(void) {
|
||||
g_gameReaction.state = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void OnEnter_Clicker(void) {
|
||||
g_gameClicker.active = false;
|
||||
g_gameClicker.finished = false;
|
||||
g_gameClicker.clicks = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
|
||||
static void OnEnter_TimeEdit(void) {
|
||||
g_timeData.editTime = ClockManager_GetTime(0);
|
||||
@@ -229,134 +100,7 @@ static void OnUpdate_TimeEdit(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void OnUpdate_Reaction(void) {
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (g_gameReaction.state == 1) {
|
||||
if (tick - g_gameReaction.waitStart >= g_gameReaction.ledOnTime) {
|
||||
g_gameReaction.state = 2;
|
||||
g_gameReaction.waitStart = tick;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
else if (g_gameReaction.state == 2) {
|
||||
if (tick - g_gameReaction.waitStart >= 2000) {
|
||||
g_gameReaction.state = 3;
|
||||
g_gameReaction.reactionTime = 999;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OnUpdate_Clicker(void) {
|
||||
if (g_gameClicker.active && HAL_GetTick() >= g_gameClicker.endTime) {
|
||||
g_gameClicker.active = false;
|
||||
g_gameClicker.finished = true;
|
||||
Menu_Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Обработчики кнопок активностей ====================
|
||||
static void Clock_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
}
|
||||
}
|
||||
|
||||
static void Timer_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
}
|
||||
}
|
||||
|
||||
static void Stopwatch_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
}
|
||||
}
|
||||
|
||||
static void ZeroMillis_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (g_game1sec.state == 0 && btn == BUTTON_SELECT) {
|
||||
g_game1sec.state = 1;
|
||||
g_game1sec.startTime = tick;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((btn == BUTTON_SELECT) && (g_game1sec.state == 1)) {
|
||||
g_game1sec.state = 2;
|
||||
g_game1sec.pressTime = HAL_GetTick();
|
||||
g_game1sec.diff_ms = (g_game1sec.pressTime - g_game1sec.startTime);
|
||||
if (g_game1sec.diff_ms < 0) g_game1sec.diff_ms = -g_game1sec.diff_ms;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((g_game1sec.state == 2) && (btn == BUTTON_SELECT))
|
||||
{
|
||||
g_game1sec.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void Reaction_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
|
||||
uint32_t tick = HAL_GetTick();
|
||||
if (g_gameReaction.state == 0 && btn == BUTTON_SELECT) {
|
||||
g_gameReaction.state = 1;
|
||||
g_gameReaction.waitStart = tick;
|
||||
g_gameReaction.ledOnTime = 1000 + (rand() % 4000);
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameReaction.state == 2 && btn == BUTTON_SELECT) {
|
||||
g_gameReaction.reactionTime = tick - g_gameReaction.waitStart;
|
||||
g_gameReaction.state = 3;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if ((g_gameReaction.state == 3) && (btn == BUTTON_SELECT))
|
||||
{
|
||||
g_gameReaction.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void Clicker_OnButton(Button_Type btn, bool longPress) {
|
||||
if (longPress && btn == BUTTON_SELECT) {
|
||||
Menu_OpenMenu(&g_rootMenu);
|
||||
return;
|
||||
}
|
||||
|
||||
if (btn == BUTTON_BACK) {
|
||||
Menu_GoBack();
|
||||
}
|
||||
|
||||
if (!g_gameClicker.active && !g_gameClicker.finished && btn == BUTTON_SELECT) {
|
||||
g_gameClicker.active = true;
|
||||
g_gameClicker.endTime = HAL_GetTick() + 10000;
|
||||
g_gameClicker.clicks = 0;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameClicker.active && btn == BUTTON_UP) {
|
||||
g_gameClicker.clicks++;
|
||||
Menu_Refresh();
|
||||
}
|
||||
else if (g_gameClicker.finished && (btn == BUTTON_SELECT))
|
||||
{
|
||||
g_gameClicker.finished = 0;
|
||||
g_gameClicker.active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void TimeEdit_OnButton(Button_Type btn, bool longPress) {
|
||||
(void)longPress;
|
||||
|
||||
@@ -491,86 +235,6 @@ static void Reset_OnButton(Button_Type btn, bool longPress) {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Узлы активностей (корень) ====================
|
||||
MenuNode g_clockNode = {
|
||||
.name = "CLOC",
|
||||
.parent = NULL,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Clock,
|
||||
.onEnter = OnEnter_Clock,
|
||||
.onUpdate = NULL,
|
||||
.onButton = Clock_OnButton,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
MenuNode g_timerNode = {
|
||||
.name = "TIMER",
|
||||
.parent = NULL,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Timer,
|
||||
.onEnter = OnEnter_Timer,
|
||||
.onUpdate = NULL,
|
||||
.onButton = Timer_OnButton,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
MenuNode g_stopwatchNode = {
|
||||
.name = "SECOND",
|
||||
.parent = NULL,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Stopwatch,
|
||||
.onEnter = OnEnter_Stopwatch,
|
||||
.onUpdate = NULL,
|
||||
.onButton = Stopwatch_OnButton,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
MenuNode g_ZeroMillisNode = {
|
||||
.name = "00 SEC",
|
||||
.parent = &g_gamesNode,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.needsRedraw = 1,
|
||||
.display = Display_ZeroMillis,
|
||||
.onEnter = OnEnter_ZeroMillis,
|
||||
.onUpdate = NULL,
|
||||
.onButton = ZeroMillis_OnButton,
|
||||
.data = &g_game1sec
|
||||
};
|
||||
|
||||
MenuNode g_ReactionTimeNode = {
|
||||
.name = "CSTEST",
|
||||
.parent = &g_gamesNode,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Reaction,
|
||||
.onEnter = OnEnter_Reaction,
|
||||
.onUpdate = OnUpdate_Reaction,
|
||||
.onButton = Reaction_OnButton,
|
||||
.data = &g_gameReaction
|
||||
};
|
||||
|
||||
MenuNode g_ClickerTimeNode = {
|
||||
.name = "CLICER",
|
||||
.parent = &g_gamesNode,
|
||||
.children = NULL,
|
||||
.childCount = 0,
|
||||
.selectedChild = 0,
|
||||
.display = Display_Clicker,
|
||||
.onEnter = OnEnter_Clicker,
|
||||
.onUpdate = OnUpdate_Clicker,
|
||||
.onButton = Clicker_OnButton,
|
||||
.data = &g_gameClicker
|
||||
};
|
||||
|
||||
// ==================== Узлы меню ====================
|
||||
MenuNode g_gamesNode;
|
||||
MenuNode g_settingsNode;
|
||||
@@ -582,12 +246,6 @@ MenuNode g_PowerOnSongNode;
|
||||
MenuNode g_SongNode;
|
||||
MenuNode g_resetNode;
|
||||
|
||||
static MenuNode* g_gamesChildren[] = {
|
||||
&g_ZeroMillisNode,
|
||||
&g_ReactionTimeNode,
|
||||
&g_ClickerTimeNode
|
||||
};
|
||||
|
||||
static MenuNode* g_settingsChildren[] = {
|
||||
&g_timeEditNode,
|
||||
&g_dutyEditNode,
|
||||
@@ -606,7 +264,7 @@ static MenuNode* g_mainMenuChildren[] = {
|
||||
&g_settingsNode
|
||||
};
|
||||
|
||||
static MenuNode g_rootMenu = {
|
||||
MenuNode g_rootMenu = {
|
||||
.name = "MAIN",
|
||||
.parent = NULL,
|
||||
.children = g_mainMenuChildren,
|
||||
@@ -624,7 +282,7 @@ void MenuItems_Init(void) {
|
||||
.name = "PLAY",
|
||||
.parent = &g_rootMenu,
|
||||
.children = g_gamesChildren,
|
||||
.childCount = 3,
|
||||
.childCount = sizeof(g_gamesChildren)/sizeof(g_gamesChildren[0]),
|
||||
.selectedChild = 0,
|
||||
.display = Display_MenuItem,
|
||||
.onEnter = NULL,
|
||||
@@ -637,7 +295,7 @@ void MenuItems_Init(void) {
|
||||
.name = "SETUP",
|
||||
.parent = &g_rootMenu,
|
||||
.children = g_settingsChildren,
|
||||
.childCount = 7,
|
||||
.childCount = sizeof(g_settingsChildren)/sizeof(g_settingsChildren[0]),
|
||||
.selectedChild = 0,
|
||||
.display = Display_MenuItem,
|
||||
.onEnter = NULL,
|
||||
@@ -692,4 +350,4 @@ MenuNode* Menu_GetRootMenu(void) {
|
||||
|
||||
MenuNode* Menu_GetCurrentActivity(void) {
|
||||
return g_currentActivity;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
extern MenuNode* g_currentActivity;
|
||||
// Глобальные узлы меню (для доступа из main.c)
|
||||
extern MenuNode g_rootMenu;
|
||||
extern MenuNode g_clockNode;
|
||||
extern MenuNode g_timerNode;
|
||||
extern MenuNode g_stopwatchNode;
|
||||
@@ -16,4 +18,4 @@ extern MenuNode g_resetNode;
|
||||
// Инициализация всех пунктов меню
|
||||
void MenuItems_Init(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user