Merge pull request #320 from mrkusypl/feature_update_v5_2

Major code refactoring (412 B)
This commit is contained in:
Armel FAUVEAU authored and GitHub committed 2026-04-29 18:43:21 +02:00
commit 9013f83734
14 files changed
+131 -235

No files matched your search

+1 -1
View File
@@ -212,7 +212,7 @@ void ACTION_Scan(bool bRestart)
DTMF_clear_RX();
#endif
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
DTMF_clear_input_box_memory();
RADIO_SelectVfos();
+2 -2
View File
@@ -1560,7 +1560,7 @@ void APP_TimeSlice500ms(void)
{
if (gDTMF_RX_live[0] != 0)
{
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
DTMF_clear_input_box_memory();
gUpdateDisplay = true;
}
}
@@ -1908,7 +1908,7 @@ static void ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
if (Key == KEY_EXIT && bKeyHeld) { // exit key held pressed
// clear the live DTMF decoder
if (gDTMF_RX_live[0] != 0) {
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
DTMF_clear_input_box_memory();
gDTMF_RX_live_timeout = 0;
gUpdateDisplay = true;
}
+101 -203
View File
@@ -25,9 +25,8 @@ static uint8_t blockAnim = 0;
static bool isInitialized = false;
bool isPaused = false;
bool isBeep = false;
uint8_t levelCountBreackout = 1;
uint8_t levelCountBreakout = 1;
uint16_t tone = 0;
uint16_t score = 0;
@@ -42,115 +41,7 @@ Brick brick[BRICK_NUMBER];
Racket racket;
Ball ball;
const uint8_t BITMAP_block[4][15] =
{
{
0b00011110,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00011110,
},
{
0b00011110,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00011110,
},
{
0b00011110,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00011110,
},
{
0b00011110,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00110001,
0b00101001,
0b00100101,
0b00100011,
0b00011110,
}
};
const uint8_t BITMAP_blockOn[15] =
{
0b00011110,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00111111,
0b00011110,
};
const uint8_t BITMAP_blockEmpty[15] =
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
};
static const uint8_t BRICK_ANIM_PATTERNS[4] = {0b00110001, 0b00101001, 0b00100101, 0b00100011};
// Initialise seed
void srand_custom(uint32_t seed) {
@@ -172,7 +63,7 @@ int randInt(int min, int max) {
void reset(void)
{
ballCount = BALL_NUMBER;
levelCountBreackout = 1;
levelCountBreakout = 1;
score = 0;
}
@@ -191,10 +82,10 @@ void playBeep(uint16_t tone)
void drawScore()
{
// Clean status line
memset(gStatusLine, 0, sizeof(gStatusLine));
UI_StatusClear();
// Level
sprintf(str, "Level %02u", levelCountBreackout);
sprintf(str, "Level %02u", levelCountBreakout);
GUI_DisplaySmallest(str, 0, 1, true, true);
// Ball
@@ -206,6 +97,12 @@ void drawScore()
GUI_DisplaySmallest(str, 88, 1, true, true);
}
// Render the ball
void renderBall(bool state) {
UI_DrawRectangleBuffer(gFrameBuffer, ball.x, ball.y, ball.x + ball.w - 1, ball.y + ball.h - 1, state);
UI_DrawLineBuffer(gFrameBuffer, ball.x - 1, ball.y + 1, ball.x + ball.w, ball.y + 1, state);
}
// Init ball
void initBall() {
ball.x = 62;
@@ -215,21 +112,25 @@ void initBall() {
ball.dx = 0;
ball.dy = 1;
UI_DrawRectangleBuffer(gFrameBuffer, ball.x, ball.y, ball.x + ball.w -1, ball.y + ball.h - 1, true);
UI_DrawLineBuffer(gFrameBuffer, ball.x - 1, ball.y + 1, ball.x + ball.w, ball.y + 1, true);
renderBall(true);
}
// Calculate the direction of the bounced ball
void directionBall(int16_t x, uint8_t w, int8_t num) {
ball.dx = map(x + w - ball.x, 0, w, num, -num);
ball.dy *= -1;
}
// Draw ball
void drawBall() {
UI_DrawRectangleBuffer(gFrameBuffer, ball.x, ball.y, ball.x + ball.w -1, ball.y + ball.h -1, false);
UI_DrawLineBuffer(gFrameBuffer, ball.x - 1, ball.y + 1, ball.x + ball.w, ball.y + 1, false);
renderBall(false);
ball.x += ball.dx;
ball.y += ball.dy;
if (ball.y <= 0) // Up
{
ball.dx = map(randInt(0, 7), 0, 7, 3, -3);
ball.dx = randInt(-3, 3);
ball.dy = 1;
}
else if (ball.x <= 2) // Left
@@ -243,9 +144,7 @@ void drawBall() {
// And now Down...
if (ball.y == 47) {
if (ball.x + 1 >= racket.x && ball.x - 1 <= racket.x + racket.w) {
ball.dx = map(racket.x + racket.w - ball.x, 0, racket.w, 3, -3);
ball.dy *= -1;
isBeep = true;
directionBall(racket.x, racket.w, 3);
tone = 400;
}
}
@@ -253,7 +152,6 @@ void drawBall() {
ballCount--;
UI_DisplayClear();
drawScore();
isBeep = true;
tone = 800;
if (ballCount < 0) {
reset();
@@ -261,15 +159,13 @@ void drawBall() {
drawWall();
isPaused = true;
UI_PrintStringSmallBold("GAME", 32, 0, 4);
UI_PrintStringSmallBold("OVER", 66, 0, 4);
UI_PrintStringSmallBold("GAME OVER", 0, LCD_WIDTH - 1, 4);
}
initRacket();
initBall();
}
UI_DrawRectangleBuffer(gFrameBuffer, ball.x, ball.y, ball.x + ball.w -1, ball.y + ball.h - 1, true);
UI_DrawLineBuffer(gFrameBuffer, ball.x - 1, ball.y + 1, ball.x + ball.w, ball.y + 1, true);
renderBall(true);
}
// Init wall
@@ -289,7 +185,6 @@ void initWall() {
brick[i].y = -8 + 8 * k;
brick[i].w = 14;
brick[i].h = 5;
brick[i].s = randInt(0, 3);
brick[i].destroy = false;
j++;
@@ -302,6 +197,11 @@ void drawWall() {
for (i = 0; i < BRICK_NUMBER; i++) {
if (brick[i].destroy == false) {
uint8_t *fb_ptr = gFrameBuffer[brick[i].y / 8] + brick[i].x;
fb_ptr[0] = 0b00011110;
fb_ptr[14] = 0b00011110;
if ((ball.x + 1 >= brick[i].x &&
ball.x - 1 <= brick[i].x + brick[i].w) &&
((ball.y + 1 >= brick[i].y &&
@@ -309,32 +209,37 @@ void drawWall() {
brick[i].destroy = true;
score++;
ball.dx = map(brick[i].x + brick[i].w - ball.x, 0, brick[i].w, 2, -2);
ball.dy *= -1;
directionBall(brick[i].x, brick[i].w, 2);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
memcpy(gFrameBuffer[brick[i].y / 8] + brick[i].x, BITMAP_blockOn, sizeof(BITMAP_blockOn));
memset(fb_ptr + 1, 0b00111111, 13);
ST7565_BlitLine(brick[i].y / 8);
playBeep(600);
memcpy(gFrameBuffer[brick[i].y / 8] + brick[i].x, BITMAP_blockEmpty, sizeof(BITMAP_blockEmpty));
memset(fb_ptr + 0, 0b00000000, 15);
ST7565_BlitLine(brick[i].y / 8);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
if (score % BRICK_NUMBER == 0) {
levelCountBreackout++;
levelCountBreakout++;
ballCount++;
initWall();
return;
}
}
if (brick[i].destroy == false) {
memcpy(gFrameBuffer[brick[i].y / 8] + brick[i].x, BITMAP_block[(brick[i].s + blockAnim) % 4], sizeof(BITMAP_block[(brick[i].s + blockAnim) % 4]));
} else {
for(uint8_t k = 0; k < 13; k++) {
fb_ptr[k + 1] = BRICK_ANIM_PATTERNS[(blockAnim + k) % 4];
}
}
}
}
}
// Render the racket shape
void renderRacket(int x, bool state) {
UI_DrawRectangleBuffer(gFrameBuffer, x + 1, racket.y, x + racket.w - 2, racket.y + racket.h, state);
UI_DrawLineBuffer(gFrameBuffer, x, racket.y + 1, x + racket.w - 1, racket.y + 1, state);
}
// Init racket
void initRacket() {
racket.w = 24;
@@ -343,18 +248,15 @@ void initRacket() {
racket.h = 2;
racket.p = racket.x;
UI_DrawRectangleBuffer(gFrameBuffer, racket.x + 1, racket.y, racket.x + racket.w - 2, racket.y + racket.h, true);
UI_DrawLineBuffer(gFrameBuffer, racket.x, racket.y + 1, racket.x + racket.w - 1, racket.y + 1, true);
renderRacket(racket.x, true);
}
// Draw racket
void drawRacket() {
if (racket.p != racket.x) {
UI_DrawRectangleBuffer(gFrameBuffer, racket.p + 1, racket.y, racket.p + racket.w - 2, racket.y + racket.h, false);
UI_DrawLineBuffer(gFrameBuffer, racket.p, racket.y + 1, racket.p + racket.w - 1, racket.y + 1, false);
renderRacket(racket.p, false);
racket.p = racket.x;
UI_DrawRectangleBuffer(gFrameBuffer, racket.x + 1, racket.y, racket.x + racket.w - 2, racket.y + racket.h, true);
UI_DrawLineBuffer(gFrameBuffer, racket.x, racket.y + 1, racket.x + racket.w - 1, racket.y + 1, true);
renderRacket(racket.x, true);
}
}
@@ -382,7 +284,7 @@ static void OnKeyDown(uint8_t key)
kbd.counter = 0;
if(isPaused)
{
UI_PrintStringSmallBold("PAUSE", 0, 128, 4);
UI_PrintStringSmallBold("PAUSE", 0, LCD_WIDTH - 1, 4);
}
break;
case KEY_EXIT:
@@ -416,17 +318,13 @@ static bool HandleUserInput()
if (kbd.current == KEY_INVALID)
return true;
// Movement keys: dispatch on every tick while held
if (kbd.current == KEY_UP || kbd.current == KEY_DOWN ||
kbd.current == KEY_4 || kbd.current == KEY_0)
{
OnKeyDown(kbd.current);
return true;
}
// Action keys (MENU, EXIT): dispatch only on rising edge
if (kbd.current != kbd.prev)
{
if (
// Movement keys: dispatch on every tick while held
(kbd.current == KEY_UP || kbd.current == KEY_DOWN ||
kbd.current == KEY_4 || kbd.current == KEY_0) ||
// Action keys (MENU, EXIT): dispatch only on rising edge
(kbd.current != kbd.prev)
){
OnKeyDown(kbd.current);
}
@@ -441,62 +339,62 @@ static void Tick()
// APP_RunBreakout
void APP_RunBreakout(void) {
static uint8_t swap = 0;
static uint8_t swap = 0;
// Init seed
srand_custom(BK4819_ReadRegister(BK4819_REG_67) & 0x01FF * gBatteryVoltageAverage * gEeprom.VfoInfo[0].pRX->Frequency);
// Init seed
srand_custom(BK4819_ReadRegister(BK4819_REG_67) & 0x01FF * gBatteryVoltageAverage * gEeprom.VfoInfo[0].pRX->Frequency);
// Init led
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
// Init led
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
// Finish the brightness fade if it is in progress
BACKLIGHT_UpdateTickless();
// Finish the brightness fade if it is in progress
BACKLIGHT_UpdateTickless();
// Init game
UI_DisplayClear();
reset();
initWall();
initRacket();
initBall();
memset(gStatusLine, 0, sizeof(gStatusLine));
isInitialized = true;
// Init game
UI_DisplayClear();
reset();
initWall();
initRacket();
initBall();
UI_StatusClear();
isInitialized = true;
while(isInitialized)
while(isInitialized)
{
Tick();
if(!isPaused)
{
Tick();
if(!isPaused)
if(swap == 0)
{
if(swap == 0)
{
blockAnim = (blockAnim + 1) % 4;
}
swap = (swap + 1) % 4;
drawScore();
drawWall();
drawRacket();
drawBall();
if(isBeep)
{
playBeep(tone);
isBeep = false;
}
else
{
SYSTEM_DelayMs(40 - MIN(levelCountBreackout - 1, 20)); // Add more fun...
}
blockAnim = (blockAnim + 1) % 4;
}
swap = (swap + 1) % 4;
ST7565_BlitStatusLine(); // Blank status line
ST7565_BlitFullScreen();
#ifdef ENABLE_FEAT_F4HWN_SCREENSHOT
if(isPaused || swap == 0)
{
SCREENSHOT_Update(false);
}
#endif
drawScore();
drawWall();
drawRacket();
drawBall();
if(tone != 0)
{
playBeep(tone);
tone = 0;
}
else
{
SYSTEM_DelayMs(40 - MIN(levelCountBreakout - 1, 20)); // Add more fun...
}
}
ST7565_BlitStatusLine(); // Blank status line
ST7565_BlitFullScreen();
#ifdef ENABLE_FEAT_F4HWN_SCREENSHOT
if(isPaused || swap == 0)
{
SCREENSHOT_Update(false);
}
#endif
}
}
-1
View File
@@ -49,7 +49,6 @@ typedef struct {
uint8_t y; // y
uint8_t w; // width
uint8_t h; // height
uint8_t s; // style
bool destroy; // active, if true, check this button, else bypass
} Brick;
+4
View File
@@ -212,6 +212,10 @@ DTMF_CallMode_t DTMF_CheckGroupCall(const char *pMsg, const unsigned int size)
}
#endif
void DTMF_clear_input_box_memory() {
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
}
void DTMF_clear_input_box(void)
{
memset(gDTMF_InputBox, 0, sizeof(gDTMF_InputBox));
+1
View File
@@ -82,6 +82,7 @@ extern DTMF_ReplyState_t gDTMF_ReplyState;
bool DTMF_ValidateCodes(char *pCode, const unsigned int size);
char DTMF_GetCharacter(const unsigned int code);
void DTMF_clear_input_box_memory(void);
void DTMF_clear_input_box(void);
void DTMF_Append(const char code);
void DTMF_Reply(void);
+1 -1
View File
@@ -800,7 +800,7 @@ void MENU_AcceptSetting(void)
case MENU_D_LIVE_DEC:
gSetting_live_DTMF_decoder = gSubMenuSelection;
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
DTMF_clear_input_box_memory();
if (!gSetting_live_DTMF_decoder)
BK4819_DisableDTMF();
gFlagReconfigureVfos = true;
+6 -11
View File
@@ -1574,6 +1574,11 @@ static void ShowChannelName(uint32_t f)
static uint32_t channelF = 0;
static char channelName[12];
// Channel name starts at x=43 (fixed), leaving room for the dBm
// string on the left (max ~40 px) and battery indicator at x=116.
// Clear first so a shorter name doesn't leave stale pixels.
memset(&gStatusLine[43], 0, 116 - 43);
if (isListening)
{
if (f != channelF) {
@@ -1593,19 +1598,9 @@ static void ShowChannelName(uint32_t f)
}
}
if (channelName[0] != 0) {
// Channel name starts at x=43 (fixed), leaving room for the dBm
// string on the left (max ~40 px) and battery indicator at x=116.
// Clear first so a shorter name doesn't leave stale pixels.
memset(&gStatusLine[43], 0, 116 - 43);
UI_PrintStringSmallBufferNormal(channelName, gStatusLine + 43);
} else {
memset(&gStatusLine[43], 0, 116 - 43);
}
}
else
{
memset(&gStatusLine[43], 0, 116 - 43);
}
ST7565_BlitStatusLine();
}
@@ -1948,7 +1943,7 @@ static void RenderFreqInput() { UI_PrintString(freqInputString, 2, 127, 0, 8); }
static void RenderStatus()
{
memset(gStatusLine, 0, sizeof(gStatusLine));
UI_StatusClear();
DrawStatus();
ST7565_BlitStatusLine();
}
+1 -1
View File
@@ -151,7 +151,7 @@ void FUNCTION_Transmit()
// clear the DTMF RX live decoder buffer
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
DTMF_clear_input_box_memory();
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
+5
View File
@@ -406,3 +406,8 @@ void UI_DisplayClear()
{
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
}
void UI_StatusClear()
{
memset(gStatusLine, 0, sizeof(gStatusLine));
}
+1
View File
@@ -45,5 +45,6 @@ void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x
void UI_DrawRectangleBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black);
void UI_DisplayClear();
void UI_StatusClear();
#endif
+2 -11
View File
@@ -34,7 +34,7 @@ static void Render(void)
unsigned int i;
char String[7];
memset(gStatusLine, 0, sizeof(gStatusLine));
UI_StatusClear();
UI_DisplayClear();
UI_PrintString("PASSWORD", 0, 127, 1, 10);
@@ -80,16 +80,7 @@ void UI_DisplayLock(void)
switch (Key)
{
case KEY_0:
case KEY_1:
case KEY_2:
case KEY_3:
case KEY_4:
case KEY_5:
case KEY_6:
case KEY_7:
case KEY_8:
case KEY_9:
case KEY_0...KEY_9:
INPUTBOX_Append(Key - KEY_0);
if (gInputBoxIndex < 6) // 6 frequency digits
+1 -1
View File
@@ -59,7 +59,7 @@ void UI_DisplayStatus()
char str[8] = "";
gUpdateStatus = false;
memset(gStatusLine, 0, sizeof(gStatusLine));
UI_StatusClear();
uint8_t *line = gStatusLine;
unsigned int x = 0;
+5 -3
View File
@@ -189,7 +189,7 @@ void UI_DrawQRCode(bool wiki, uint8_t origin_x, uint8_t origin_y)
void UI_DisplayReleaseKeys(void)
{
memset(gStatusLine, 0, sizeof(gStatusLine));
UI_StatusClear();
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv();
#endif
@@ -209,7 +209,7 @@ void UI_DisplayWelcome(void)
char WelcomeString2[16];
char WelcomeString3[32];
memset(gStatusLine, 0, sizeof(gStatusLine));
UI_StatusClear();
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv();
@@ -222,11 +222,13 @@ void UI_DisplayWelcome(void)
if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_SOUND) {
ST7565_FillScreen(0x00);
}
#else
if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_NONE || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_FULL_SCREEN) {
ST7565_FillScreen(0xFF);
}
#endif
} else {
else {
memset(WelcomeString0, 0, sizeof(WelcomeString0));
memset(WelcomeString1, 0, sizeof(WelcomeString1));