Merge pull request #413 from armel/feature_update_v4

Feature update v4
This commit is contained in:
Armel FAUVEAU authored and GitHub committed 2025-07-05 01:34:56 +02:00
commit 8b851a0f79
20 files changed
+715 -50

No files matched your search

+2 -1
View File
@@ -1,4 +1,5 @@
FROM --platform=amd64 archlinux:latest
ARG BUILDPLATFORM
FROM --platform=${BUILDPLATFORM} archlinux:latest
RUN pacman -Syyu base-devel --noconfirm
RUN pacman -Syyu arm-none-eabi-gcc --noconfirm
RUN pacman -Syyu arm-none-eabi-newlib --noconfirm
+8 -1
View File
@@ -41,6 +41,7 @@ ENABLE_BYP_RAW_DEMODULATORS ?= 0
ENABLE_BLMIN_TMP_OFF ?= 0
ENABLE_SCAN_RANGES ?= 1
ENABLE_FEAT_F4HWN ?= 1
ENABLE_FEAT_F4HWN_GAME ?= 0
ENABLE_FEAT_F4HWN_SCREENSHOT ?= 0
ENABLE_FEAT_F4HWN_SPECTRUM ?= 1
ENABLE_FEAT_F4HWN_RX_TX_TIMER ?= 1
@@ -153,6 +154,9 @@ OBJS += app/menu.o
ifeq ($(ENABLE_SPECTRUM), 1)
OBJS += app/spectrum.o
endif
ifeq ($(ENABLE_FEAT_F4HWN_GAME), 1)
OBJS += app/breakout.o
endif
OBJS += app/scanner.o
ifeq ($(ENABLE_UART),1)
OBJS += app/uart.o
@@ -230,7 +234,7 @@ ifeq ($(ENABLE_FEAT_F4HWN),1)
VERSION_STRING_1 ?= v0.22
AUTHOR_STRING_2 ?= F4HWN
VERSION_STRING_2 ?= v4.0
VERSION_STRING_2 ?= v4.1
EDITION_STRING ?= Custom
@@ -430,6 +434,9 @@ ifeq ($(ENABLE_FEAT_F4HWN),1)
else
CFLAGS += -DSQL_TONE=550
endif
ifeq ($(ENABLE_FEAT_F4HWN_GAME),1)
CFLAGS += -DENABLE_FEAT_F4HWN_GAME
endif
ifeq ($(ENABLE_FEAT_F4HWN_SCREENSHOT),1)
CFLAGS += -DENABLE_FEAT_F4HWN_SCREENSHOT
endif
+1 -1
View File
@@ -26,7 +26,7 @@ Anyway, have fun.
# Donations
Special thanks to Jean-Cyrille F6IWW (2 times), Fabrice 14RC123, David F4BPP, Olivier 14RC206, Frédéric F4ESO, Stéphane F5LGW, Jorge Ornelas (4 times), Laurent F4AXK, Christophe Morel, Clayton W0LED, Pierre Antoine F6FWB, Jean-Claude 14FRS3306, Thierry F4GVO, Eric F1NOU, PricelessToolkit, Ady M6NYJ, Tom McGovern (3 times), Joseph Roth, Pierre-Yves Colin, Frank DJ7FG, Marcel Testaz, Brian Frobisher, Yannick F4JFO, Paolo Bussola, Dirk DL8DF, Levente Szőke (2 times), Bernard-Michel Herrera, Jérôme Saintespes, Paul Davies, RS (3 times), Johan F4WAT, Robert Wörle, Rafael Sundorf, Paul Harker, Peter Fintl, Pascal F4ICR (2 times), Mike DL2MF, Eric KI1C (2 times), Phil G0ELM, Jérôme Lambert, Meinhard Frank Günther, Eliot Vedel, Alfonso EA7KDF, Jean-François F1EVM, Robert DC1RDB, Ian KE2CHJ and Daryl VK3AWA for their [donations](https://www.paypal.com/paypalme/F4HWN). That’s so kind of them. Thanks so much 🙏🏻
Special thanks to Jean-Cyrille F6IWW (2 times), Fabrice 14RC123, David F4BPP, Olivier 14RC206, Frédéric F4ESO, Stéphane F5LGW, Jorge Ornelas (4 times), Laurent F4AXK, Christophe Morel, Clayton W0LED, Pierre Antoine F6FWB, Jean-Claude 14FRS3306, Thierry F4GVO, Eric F1NOU, PricelessToolkit, Ady M6NYJ, Tom McGovern (3 times), Joseph Roth, Pierre-Yves Colin, Frank DJ7FG, Marcel Testaz, Brian Frobisher, Yannick F4JFO, Paolo Bussola, Dirk DL8DF, Levente Szőke (2 times), Bernard-Michel Herrera, Jérôme Saintespes, Paul Davies, RS (3 times), Johan F4WAT, Robert Wörle, Rafael Sundorf, Paul Harker, Peter Fintl, Pascal F4ICR (2 times), Mike DL2MF, Eric KI1C (2 times), Phil G0ELM, Jérôme Lambert, Meinhard Frank Günther, Eliot Vedel, Alfonso EA7KDF, Jean-François F1EVM, Robert DC1RDB, Ian KE2CHJ, Daryl VK3AWA, Roberto Brunelli, Robert Boardman and Stephen Oliver for their [donations](https://www.paypal.com/paypalme/F4HWN). That’s so kind of them. Thanks so much 🙏🏻
## Table of Contents
+504
View File
@@ -0,0 +1,504 @@
/* Copyright 2025 Armel F4HWN
* https://github.com/armel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "app/breakout.h"
static uint32_t randSeed = 1;
static uint8_t blockAnim = 0;
bool isInitialized = false;
bool isPaused = false;
bool isBeep = false;
uint8_t levelCountBreackout = 1;
uint16_t tone = 0;
uint16_t score = 0;
int16_t ballCount = BALL_NUMBER;
char str[12];
KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
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,
};
// Initialise seed
void srand_custom(uint32_t seed) {
randSeed = seed;
}
// Return pseudo-random from 0 to RAND_MAX (here 32767)
int rand_custom(void) {
randSeed = randSeed * 1103515245 + 12345;
return (randSeed >> 16) & 0x7FFF; // 15 bits
}
// Return integer from min to max include
int randInt(int min, int max) {
return min + (rand_custom() % (max - min + 1));
}
// Reset
void reset(void)
{
ballCount = BALL_NUMBER;
levelCountBreackout = 1;
score = 0;
}
// PlayBeep
void playBeep(uint16_t tone)
{
BK4819_PlayTone(tone, true); // 500 Hz ON
AUDIO_AudioPathOn();
BK4819_ExitTxMute();
SYSTEM_DelayMs(100);
BK4819_EnterTxMute();
AUDIO_AudioPathOff();
}
// Draw score
void drawScore()
{
// Clean status line
memset(gStatusLine, 0, sizeof(gStatusLine));
// Level
sprintf(str, "Level %02u", levelCountBreackout);
GUI_DisplaySmallest(str, 0, 1, true, true);
// Ball
sprintf(str, "Ball %02u", (ballCount < 0) ? 0 : ballCount);
GUI_DisplaySmallest(str, 45, 1, true, true);
// Score
sprintf(str, "Score %04u", score);
GUI_DisplaySmallest(str, 88, 1, true, true);
}
// Init ball
void initBall() {
ball.x = 62;
ball.y = 30;
ball.w = 3;
ball.h = 3;
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);
}
// 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);
ball.x += ball.dx;
ball.y += ball.dy;
if (ball.y <= 0) // Up
{
ball.dx = map(randInt(0, 7), 0, 7, 3, -3);
ball.dy = 1;
}
else if (ball.x <= 2) // Left
{
ball.dx = abs(ball.dx);
}
else if (ball.x >= 124) // Right
{
ball.dx = -abs(ball.dx);
}
// 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;
tone = 400;
}
}
else if(ball.y > 49) {
ballCount--;
UI_DisplayClear();
drawScore();
isBeep = true;
tone = 800;
if (ballCount < 0) {
reset();
initWall();
drawWall();
isPaused = true;
UI_PrintStringSmallBold("GAME", 32, 0, 4);
UI_PrintStringSmallBold("OVER", 66, 0, 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);
}
// Init wall
void initWall() {
uint8_t offset = 6;
uint8_t i = 0;
uint8_t j = 0;
uint8_t k = 0;
for (i = 0; i < BRICK_NUMBER; i++) {
if (i % 6 == 0) {
j = 0;
k++;
}
brick[i].x = offset + (20 * j);
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++;
}
}
// Draw wall
void drawWall() {
uint8_t i = 0;
for (i = 0; i < BRICK_NUMBER; i++) {
if (brick[i].destroy == false) {
if ((ball.x + 1 >= brick[i].x &&
ball.x - 1 <= brick[i].x + brick[i].w) &&
((ball.y + 1 >= brick[i].y &&
ball.y - 1 <= brick[i].y + brick[i].h))) {
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;
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
memcpy(gFrameBuffer[brick[i].y / 8] + brick[i].x, BITMAP_blockOn, sizeof(BITMAP_blockOn));
ST7565_BlitLine(brick[i].y / 8);
playBeep(600);
memcpy(gFrameBuffer[brick[i].y / 8] + brick[i].x, BITMAP_blockEmpty, sizeof(BITMAP_blockEmpty));
ST7565_BlitLine(brick[i].y / 8);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
if (score % BRICK_NUMBER == 0) {
levelCountBreackout++;
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]));
}
}
}
}
// Init racket
void initRacket() {
racket.w = 24;
racket.x = (64) - (racket.w / 2);
racket.y = 50;
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);
}
// 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);
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);
}
}
// OnKeyDown
static void OnKeyDown(uint8_t key)
{
bool wasPaused = isPaused;
switch (key)
{
case KEY_4:
case KEY_UP:
if(!isPaused && racket.x > 0)
racket.x -= 2;
isPaused = false;
break;
case KEY_0:
case KEY_DOWN:
if(!isPaused && racket.x < 102)
racket.x += 2;
isPaused = false;
break;
case KEY_MENU:
isPaused = !isPaused;
kbd.counter = 0;
if(isPaused)
{
UI_PrintStringSmallBold("PAUSE", 0, 128, 4);
}
break;
case KEY_EXIT:
isPaused = false;
isInitialized = false;
break;
}
if(wasPaused == true && isPaused == false)
{
// Clear the pause text
for(uint8_t i = 0; i < 8; i++)
{
UI_DrawLineBuffer(gFrameBuffer, 32, 32 + i, 96, 32 + i, false);
}
}
}
// Key
KEY_Code_t GetKey()
{
KEY_Code_t btn = KEYBOARD_Poll();
if (btn == KEY_INVALID && !GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT))
{
btn = KEY_PTT;
}
return btn;
}
// HandleUserInput
bool HandleUserInput()
{
// Store previous key state
kbd.prev = kbd.current;
// Get the current key
kbd.current = GetKey();
// Detect valid key press continuation (same key still pressed)
if (kbd.current != KEY_INVALID && kbd.current == kbd.prev)
{
kbd.counter = 1;
}
else
{
kbd.counter = 0;
}
// Process the key if counter indicates it should be handled
if (kbd.counter == 1)
{
OnKeyDown(kbd.current);
// Special handling for MENU key
if(kbd.current == KEY_MENU)
{
kbd.counter = 0;
SYSTEM_DelayMs(250);
}
}
return true;
}
// Tick
static void Tick()
{
HandleUserInput();
HandleUserInput();
}
// APP_RunBreakout
void APP_RunBreakout(void) {
static uint8_t swap = 0;
// 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 game
UI_DisplayClear();
reset();
initWall();
initRacket();
initBall();
memset(gStatusLine, 0, sizeof(gStatusLine));
isInitialized = true;
while(isInitialized)
{
Tick();
if(!isPaused)
{
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...
}
}
ST7565_BlitStatusLine(); // Blank status line
ST7565_BlitFullScreen();
}
}
+80
View File
@@ -0,0 +1,80 @@
/* Copyright 2025 Armel F4HWN
* https://github.com/armel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../bitmaps.h"
#include "../board.h"
#include "../bsp/dp32g030/gpio.h"
#include "../driver/bk4819-regs.h"
#include "../driver/bk4819.h"
#include "../driver/gpio.h"
#include "../driver/keyboard.h"
#include "../driver/st7565.h"
#include "../driver/system.h"
#include "../driver/systick.h"
#include "../external/printf/printf.h"
#include "../font.h"
#include "../helper/battery.h"
#include "../misc.h"
#include "../radio.h"
#include "../settings.h"
#include "../ui/helper.h"
#include "../audio.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#define BRICK_NUMBER 18
#define BALL_NUMBER 5
typedef struct {
uint8_t x; // x
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;
typedef struct {
int8_t x; // x
uint8_t y; // y
uint8_t w; // width
uint8_t h; // height
uint8_t p; // previous x
} Racket;
typedef struct {
int16_t x; // x
int8_t y; // y
uint8_t w; // width
uint8_t h; // height
int8_t dx; // move x
int8_t dy; // move y
} Ball;
typedef struct KeyboardState
{
KEY_Code_t current;
KEY_Code_t prev;
uint8_t counter;
} KeyboardState;
void initWall(void);
void drawWall(void);
void initRacket(void);
void drawRacket(void);
void APP_RunBreakout(void);
+12 -1
View File
@@ -31,6 +31,10 @@
#include "app/spectrum.h"
#endif
#ifdef ENABLE_FEAT_F4HWN_GAME
#include "app/breakout.h"
#endif
#include "audio.h"
#include "board.h"
#include "driver/bk4819.h"
@@ -582,6 +586,13 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
ACTION_BackLight();
return;
}
#ifdef ENABLE_FEAT_F4HWN_GAME
else if(Key == 7)
{
APP_RunBreakout();
return;
}
#endif
processFKeyFunction(Key, true);
}
@@ -660,7 +671,7 @@ static void MAIN_Key_MENU(bool bKeyPressed, bool bKeyHeld)
// Exclude work with list 1, 2, 3 or all list
if(gScanStateDir != SCAN_OFF)
{
if(FUNCTION_IsRx())
if(FUNCTION_IsRx() || gScanPauseDelayIn_10ms > 9)
{
gMR_ChannelExclude[gTxVfo->CHANNEL_SAVE] = true;
+29 -2
View File
@@ -103,11 +103,18 @@ RegisterSpec registerSpecs[] = {
{},
{"LNAs", BK4819_REG_13, 8, 0b11, 1},
{"LNA", BK4819_REG_13, 5, 0b111, 1},
{"PGA", BK4819_REG_13, 0, 0b111, 1},
{"IF", BK4819_REG_3D, 0, 0xFFFF, 0x2aaa},
{"VGA", BK4819_REG_13, 0, 0b111, 1},
{"BPF", BK4819_REG_3D, 0, 0xFFFF, 0x2aaa},
// {"MIX", 0x13, 3, 0b11, 1}, // TODO: hidden
};
#ifdef ENABLE_FEAT_F4HWN_SPECTRUM
const int8_t LNAsOptions[] = {-19, -16, -11, 0};
const int8_t LNAOptions[] = {-24, -19, -14, -9, -6, -4, -2, 0};
const int8_t VGAOptions[] = {-33, -27, -21, -15, -9, -6, -3, 0};
const char *BPFOptions[] = {"8.46", "7.25", "6.35", "5.64", "5.08", "4.62", "4.23"};
#endif
uint16_t statuslineUpdateTimer = 0;
#ifdef ENABLE_FEAT_F4HWN_SPECTRUM
@@ -1387,7 +1394,27 @@ static void RenderStill()
sprintf(String, "%s", registerSpecs[idx].name);
GUI_DisplaySmallest(String, offset + 2, row * 8 + 2, false,
menuState != idx);
#ifdef ENABLE_FEAT_F4HWN_SPECTRUM
if(idx == 1)
{
sprintf(String, "%ddB", LNAsOptions[GetRegMenuValue(idx)]);
}
else if(idx == 2)
{
sprintf(String, "%ddB", LNAOptions[GetRegMenuValue(idx)]);
}
else if(idx == 3)
{
sprintf(String, "%ddB", VGAOptions[GetRegMenuValue(idx)]);
}
else if(idx == 4)
{
sprintf(String, "%skHz", BPFOptions[(GetRegMenuValue(idx) / 0x2aaa)]);
}
#else
sprintf(String, "%u", GetRegMenuValue(idx));
#endif
GUI_DisplaySmallest(String, offset + 2, (row + 1) * 8 + 1, false,
menuState != idx);
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+76 -43
View File
@@ -1,26 +1,38 @@
#!/bin/sh
#export DOCKER_DEFAULT_PLATFORM=linux/amd64
#export DOCKER_NETWORK="--network=host"
IMAGE_NAME="uvk5"
rm "${PWD}/compiled-firmware/*"
echo "Building docker image $IMAGE_NAME"
if ! docker build -t $DOCKER_NETWORK $IMAGE_NAME .
then
echo "Failed to build docker image"
exit 1
FIRMWARE_DIR="${PWD}/compiled-firmware"
# Create firmware output directory if it doesn't exist
mkdir -p "$FIRMWARE_DIR"
# Clean previously compiled firmware files
rm -f "$FIRMWARE_DIR"/*
# Build image only if it doesn't already exist
if ! docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
echo "Docker image '$IMAGE_NAME' not found, building..."
if ! docker build --build-arg BUILDPLATFORM=linux/amd64 -t "$IMAGE_NAME" .; then
echo "❌ Failed to build docker image"
exit 1
fi
fi
# ------------------ BUILD VARIANTS ------------------
custom() {
echo "Custom compilation..."
docker run --rm -v "${PWD}/compiled-firmware/:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "rm ./compiled-firmware/*; cd /app && make -s \
echo "🔧 Custom compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
rm -f ./compiled-firmware/* && cd /app && make -s \
EDITION_STRING=Custom \
TARGET=f4hwn.custom \
&& cp f4hwn.custom* compiled-firmware/"
}
standard() {
echo "Standard compilation..."
docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "rm ./compiled-firmware/*; cd /app && make -s \
echo "📦 Standard compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
rm -f ./compiled-firmware/* && cd /app && make -s \
ENABLE_SPECTRUM=0 \
ENABLE_FMRADIO=0 \
ENABLE_AIRCOPY=0 \
@@ -31,11 +43,14 @@ standard() {
}
bandscope() {
echo "Bandscope compilation..."
docker run --rm -v "${PWD}/compiled-firmware/:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "rm ./compiled-firmware/*; cd /app && make -s \
echo "📺 Bandscope compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
rm -f ./compiled-firmware/* && cd /app && make -s \
ENABLE_SPECTRUM=1 \
ENABLE_FMRADIO=0 \
ENABLE_VOX=0 \
ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_GAME=0 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \
@@ -46,32 +61,37 @@ bandscope() {
}
broadcast() {
echo "Broadcast compilation..."
docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "cd /app && make -s \
echo "📻 Broadcast compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
cd /app && make -s \
ENABLE_SPECTRUM=0 \
ENABLE_FMRADIO=1 \
ENABLE_VOX=1 \
ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_GAME=0 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \
EDITION_STRING=Broadcast \
ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \
EDITION_STRING=Broadcast \
TARGET=f4hwn.broadcast \
&& cp f4hwn.broadcast* compiled-firmware/"
}
basic() {
echo "Basic compilation..."
docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "cd /app && make -s \
echo "☘️ Basic compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
cd /app && make -s \
ENABLE_SPECTRUM=1 \
ENABLE_FMRADIO=1 \
ENABLE_VOX=0 \
ENABLE_AIRCOPY=0 \
ENABLE_AUDIO_BAR=0 \
ENABLE_FEAT_F4HWN_GAME=0 \
ENABLE_FEAT_F4HWN_SPECTRUM=0 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \
ENABLE_AUDIO_BAR=0 \
ENABLE_FEAT_F4HWN_RESUME_STATE=0 \
ENABLE_FEAT_F4HWN_CHARGING_C=0 \
ENABLE_FEAT_F4HWN_INV=1 \
@@ -84,11 +104,14 @@ basic() {
}
rescueops() {
echo "RescueOps compilation..."
docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "cd /app && make -s \
echo "🚨 RescueOps compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
cd /app && make -s \
ENABLE_SPECTRUM=0 \
ENABLE_FMRADIO=0 \
ENABLE_VOX=1 \
ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_GAME=0 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=1 \
@@ -98,33 +121,43 @@ rescueops() {
&& cp f4hwn.rescueops* compiled-firmware/"
}
game() {
echo "🎮 Game compilation..."
docker run --rm -v "$FIRMWARE_DIR:/app/compiled-firmware" "$IMAGE_NAME" /bin/bash -c "\
cd /app && make -s \
ENABLE_SPECTRUM=0 \
ENABLE_FMRADIO=1 \
ENABLE_VOX=0 \
ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_GAME=1 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \
ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \
EDITION_STRING=Game \
TARGET=f4hwn.game \
&& cp f4hwn.game* compiled-firmware/"
}
# ------------------ MENU ------------------
case "$1" in
custom)
custom
;;
standard)
standard
;;
bandscope)
bandscope
;;
broadcast)
broadcast
;;
basic)
basic
;;
rescueops)
rescueops
;;
custom) custom ;;
standard) standard ;;
bandscope) bandscope ;;
broadcast) broadcast ;;
basic) basic ;;
rescueops) rescueops ;;
game) game ;;
all)
bandscope
broadcast
rescueops
basic
rescueops
game
;;
*)
echo "Usage: $0 {custom|bandscope|broadcast|basic|standard|all}"
echo "Usage: $0 {custom|standard|bandscope|broadcast|basic|rescueops|game|all} [--rebuild]"
exit 1
;;
esac
esac
+1 -1
View File
@@ -1004,7 +1004,7 @@ State[1] = 0
#ifdef ENABLE_BYP_RAW_DEMODULATORS
| (1 << 2)
#endif
#ifdef ENABLE_BLMIN_TMP_OFF
#ifdef ENABLE_FEAT_F4HWN_GAME
| (1 << 3)
#endif
#ifdef ENABLE_AM_FIX
+2
View File
@@ -1227,6 +1227,8 @@ void UI_DisplayMenu(void)
#if defined(ENABLE_SPECTRUM) && defined(ENABLE_FMRADIO)
UI_PrintStringSmallNormal("Basic", 54, 127, 6);
#elif defined(ENABLE_FEAT_F4HWN_GAME)
UI_PrintStringSmallNormal("Game", 54, 127, 6);
#elif defined(ENABLE_SPECTRUM)
UI_PrintStringSmallNormal("Bandscope", 54, 127, 6);
#elif defined(ENABLE_FMRADIO)