From 74421ed6d7fa0b6956dfa2944b0f64be5bfefb7c Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Mon, 29 Jan 2024 22:43:47 +0100 Subject: [PATCH] Apply changes to v0.22 --- Makefile | 8 +- README.md | 2 + app/action.c | 54 +++++ app/action.h | 7 +- app/app.c | 113 ++++++++++ app/menu.c | 30 +++ compile-with-docker.sh | 7 +- diff | 483 +++++++++++++++++++++++++++++++++++++++++ driver/backlight.c | 22 ++ misc.c | 16 ++ misc.h | 15 ++ radio.c | 77 ++++++- scheduler.c | 4 + settings.c | 19 ++ settings.h | 4 + ui/helper.c | 22 ++ ui/helper.h | 3 + ui/main.c | 242 ++++++++++++++++++++- ui/menu.c | 45 +++- ui/menu.h | 10 + ui/welcome.c | 6 + version.c | 11 +- version.h | 3 + 23 files changed, 1181 insertions(+), 22 deletions(-) create mode 100644 diff diff --git a/Makefile b/Makefile index 9f47bd746..6f550abed 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ ENABLE_KEEP_MEM_NAME ?= 1 ENABLE_WIDE_RX ?= 1 ENABLE_TX_WHEN_AM ?= 0 ENABLE_F_CAL_MENU ?= 0 -ENABLE_CTCSS_TAIL_PHASE_SHIFT ?= 0 +ENABLE_CTCSS_TAIL_PHASE_SHIFT ?= 1 ENABLE_BOOT_BEEPS ?= 0 ENABLE_SHOW_CHARGE_LEVEL ?= 0 ENABLE_REVERSE_BAT_SYMBOL ?= 0 @@ -40,6 +40,7 @@ ENABLE_REDUCE_LOW_MID_TX_POWER?= 0 ENABLE_BYP_RAW_DEMODULATORS ?= 0 ENABLE_BLMIN_TMP_OFF ?= 0 ENABLE_SCAN_RANGES ?= 1 +ENABLE_FEAT_F4HWN ?= 1 # ---- DEBUGGING ---- ENABLE_AM_FIX_SHOW_DATA ?= 0 @@ -377,6 +378,11 @@ endif ifeq ($(ENABLE_CUSTOM_MENU_LAYOUT),1) CFLAGS += -DENABLE_CUSTOM_MENU_LAYOUT endif +ifeq ($(ENABLE_FEAT_F4HWN),1) + CFLAGS += -DENABLE_FEAT_F4HWN + FEAT_STRING ?= "F4HWN v1.5" + CFLAGS += -DFEAT_STRING=\"$(FEAT_STRING)\" -DALERT_TOT=10 +endif LDFLAGS = LDFLAGS += -z noexecstack -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld -Wl,--gc-sections diff --git a/README.md b/README.md index 279479c58..c406bdbd0 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,8 @@ You'll find the options at the top of "Makefile" ('0' = disable, '1' = enable) . | ENABLE_BYP_RAW_DEMODULATORS | additional BYP (bypass?) and RAW demodulation options, proved not to be very useful, but it is there if you want to experiment | | ENABLE_BLMIN_TMP_OFF | additional function for configurable buttons that toggles `BLMin` on and off wihout saving it to the EEPROM | | ENABLE_SCAN_RANGES | scan range mode for frequency scanning, see wiki for instructions (radio operation -> frequency scanning) | +| ENABLE_FEAT_F4HWN | improve by F4HWN | + |🧰 **DEBUGGING** || | ENABLE_AM_FIX_SHOW_DATA| displays settings used by AM-fix when AM transmission is received | | ENABLE_AGC_SHOW_DATA | displays AGC settings | diff --git a/app/action.c b/app/action.c index b99b583f7..bf59f29be 100644 --- a/app/action.c +++ b/app/action.c @@ -100,6 +100,13 @@ void (*action_opt_table[])(void) = { #else [ACTION_OPT_BLMIN_TMP_OFF] = &FUNCTION_NOP, #endif + +#ifdef ENABLE_FEAT_F4HWN + [ACTION_OPT_MAIN] = &ACTION_Main, + [ACTION_OPT_PTT] = &ACTION_Ptt, +#else + [ACTION_OPT_MAIN] = &FUNCTION_NOP, +#endif }; static_assert(ARRAY_SIZE(action_opt_table) == ACTION_OPT_LEN); @@ -441,3 +448,50 @@ void ACTION_BlminTmpOff(void) } } #endif + +#ifdef ENABLE_FEAT_F4HWN +void ACTION_Main(void) +{ + static uint8_t cycle = 0; + static uint8_t a; + static uint8_t b; + + + if(gEeprom.DUAL_WATCH == 0 && gEeprom.CROSS_BAND_RX_TX == 0 && cycle != 1) + { + return; + } + else + { + if(cycle == 0) + { + a = gEeprom.DUAL_WATCH; + b = gEeprom.CROSS_BAND_RX_TX; + + gEeprom.DUAL_WATCH = 0; + gEeprom.CROSS_BAND_RX_TX = 0; + + gFlagReconfigureVfos = true; + gUpdateStatus = true; + + cycle = 1; + } + else + { + gEeprom.DUAL_WATCH = a; + gEeprom.CROSS_BAND_RX_TX = b; + + gFlagReconfigureVfos = true; + gUpdateStatus = true; + + cycle = 0; + } + } +} + +void ACTION_Ptt(void) +{ + gSetting_set_ptt = (gSetting_set_ptt == 0) ? 1: 0; + +} +#endif \ No newline at end of file diff --git a/app/action.h b/app/action.h index 3591ab4c4..b837b0cf8 100644 --- a/app/action.h +++ b/app/action.h @@ -32,7 +32,12 @@ void ACTION_Scan(bool bRestart); void ACTION_SwitchDemodul(void); #ifdef ENABLE_BLMIN_TMP_OFF -void ACTION_BlminTmpOff(void); + void ACTION_BlminTmpOff(void); +#endif + +#ifdef ENABLE_FEAT_F4HWN + void ACTION_Main(void); + void ACTION_Ptt(void); #endif void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); diff --git a/app/app.c b/app/app.c index 9d57f6f0a..e74e6e9c3 100644 --- a/app/app.c +++ b/app/app.c @@ -825,10 +825,48 @@ void APP_Update(void) } #endif +#ifdef ENABLE_FEAT_F4HWN + if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReachedAlert || SerialConfigInProgress())) + { + if (gEeprom.BACKLIGHT_TIME == 0) { + if (gBlinkCounter == 0) + { + GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } + else if(gBlinkCounter == 250) + { + GPIO_FlipBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT); + } + } + else + { + if (gBlinkCounter == 0) + { + BACKLIGHT_TurnOn(); + } + else if(gBlinkCounter == 15000) + { + BACKLIGHT_TurnOff(); + } + } + + gBlinkCounter++; + + if(gBlinkCounter > 30000) + { + gBlinkCounter = 0; + } + } +#endif + if (gCurrentFunction == FUNCTION_TRANSMIT && (gTxTimeoutReached || SerialConfigInProgress())) { // transmitter timed out or must de-key gTxTimeoutReached = false; +#ifdef ENABLE_FEAT_F4HWN + gTxTimeoutReachedAlert = false; +#endif + APP_EndTransmission(); AUDIO_PlayBeep(BEEP_880HZ_60MS_TRIPLE_BEEP); @@ -1012,6 +1050,80 @@ static void CheckKeys(void) #endif // -------------------- PTT ------------------------ +#ifdef ENABLE_FEAT_F4HWN + if (gSetting_set_ptt == 1) + { + if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress() && gPttOnePushCounter == 0) + { // PTT pressed + if (++gPttDebounceCounter >= 3) // 30ms + { // start transmitting + boot_counter_10ms = 0; + gPttDebounceCounter = 0; + gPttIsPressed = true; + gPttOnePushCounter = 1; + ProcessKey(KEY_PTT, true, false); + } + } + else if ((GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) && gPttOnePushCounter == 1) + { + // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + gPttOnePushCounter = 2; + } + } + else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress() && gPttOnePushCounter == 2) + { // PTT pressed again + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + gPttOnePushCounter = 3; + if (gKeyReading1 != KEY_INVALID) + gPttWasReleased = true; + } + } + else if ((GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) && gPttOnePushCounter == 3) + { // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + gPttOnePushCounter = 0; + } + } + else + gPttDebounceCounter = 0; + } + else + { + if (gPttIsPressed) + { + if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) + { // PTT released or serial comms config in progress + if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms + { // stop transmitting + ProcessKey(KEY_PTT, false, false); + gPttIsPressed = false; + if (gKeyReading1 != KEY_INVALID) + gPttWasReleased = true; + } + } + else + gPttDebounceCounter = 0; + } + else if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !SerialConfigInProgress()) + { // PTT pressed + if (++gPttDebounceCounter >= 3) // 30ms + { // start transmitting + boot_counter_10ms = 0; + gPttDebounceCounter = 0; + gPttIsPressed = true; + ProcessKey(KEY_PTT, true, false); + } + } + else + gPttDebounceCounter = 0; + } +#else if (gPttIsPressed) { if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) || SerialConfigInProgress()) @@ -1039,6 +1151,7 @@ static void CheckKeys(void) } else gPttDebounceCounter = 0; +#endif // --------------------- OTHER KEYS ---------------------------- diff --git a/app/menu.c b/app/menu.c index 8dacadafe..a400c2c61 100644 --- a/app/menu.c +++ b/app/menu.c @@ -363,6 +363,17 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) *pMax = gSubMenu_SIDEFUNCTIONS_size-1; break; +#ifdef ENABLE_FEAT_F4HWN + case MENU_SET_LOW: + *pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SET_LOW) - 1; + break; + case MENU_SET_PTT: + *pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_SET_PTT) - 1; + break; +#endif + default: return -1; } @@ -797,6 +808,16 @@ void MENU_AcceptSetting(void) } break; +#ifdef ENABLE_FEAT_F4HWN + case MENU_SET_LOW: + gSetting_set_low = gSubMenuSelection; + gRequestSaveChannel = 1; + break; + case MENU_SET_PTT: + gSetting_set_ptt = gSubMenuSelection; + gRequestSaveChannel = 1; + break; +#endif } gRequestSaveSettings = true; @@ -1159,6 +1180,15 @@ void MENU_ShowCurrentSetting(void) break; } +#ifdef ENABLE_FEAT_F4HWN + case MENU_SET_LOW: + gSubMenuSelection = gSetting_set_low; + break; + case MENU_SET_PTT: + gSubMenuSelection = gSetting_set_ptt; + break; +#endif + default: return; } diff --git a/compile-with-docker.sh b/compile-with-docker.sh index a27d3080f..a51ddf89c 100755 --- a/compile-with-docker.sh +++ b/compile-with-docker.sh @@ -1,3 +1,6 @@ #!/bin/sh -docker build -t uvk5 . -docker run --rm -v ${PWD}/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/" + +IMAGE_NAME="uvk5" + +docker build -t $IMAGE_NAME . +docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/" \ No newline at end of file diff --git a/diff b/diff new file mode 100644 index 000000000..90bdbc451 --- /dev/null +++ b/diff @@ -0,0 +1,483 @@ + +diff --git a/ui/helper.c b/ui/helper.c +index 63bf581..4934ea7 100644 +--- a/ui/helper.c ++++ b/ui/helper.c +@@ -198,6 +198,28 @@ static void sort(int16_t *a, int16_t *b) + } + } + ++#ifdef ENABLE_FEAT_F4HWN ++ void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) ++ { ++ if(x2==x1) { ++ sort(&y1, &y2); ++ for(int16_t i = y1; i <= y2; i+=2) { ++ UI_DrawPixelBuffer(buffer, x1, i, black); ++ } ++ } else { ++ const int multipl = 1000; ++ int a = (y2-y1)*multipl / (x2-x1); ++ int b = y1 - a * x1 / multipl; ++ ++ sort(&x1, &x2); ++ for(int i = x1; i<= x2; i+=2) ++ { ++ UI_DrawPixelBuffer(buffer, i, i*a/multipl +b, black); ++ } ++ } ++ } ++#endif ++ + void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) + { + if(x2==x1) { +diff --git a/ui/helper.h b/ui/helper.h +index 8401a9b..27b339b 100644 +--- a/ui/helper.h ++++ b/ui/helper.h +@@ -32,6 +32,9 @@ void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center); + void UI_DisplayPopup(const char *string); + + void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black); ++#ifdef ENABLE_FEAT_F4HWN ++ void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); ++#endif + void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); + void UI_DrawRectangleBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); + +diff --git a/ui/main.c b/ui/main.c +index eb17b1f..9cde474 100644 +--- a/ui/main.c ++++ b/ui/main.c +@@ -39,6 +39,11 @@ + + center_line_t center_line = CENTER_LINE_NONE; + ++#ifdef ENABLE_FEAT_F4HWN ++ static bool RXCounter; ++ static int8_t RXLine; ++#endif ++ + const int8_t dBmCorrTable[7] = { + -15, // band 1 + -25, // band 2 +@@ -77,17 +82,42 @@ static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level) + + static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) + { ++#ifdef ENABLE_FEAT_F4HWN ++ const char hollowBar[] = { ++ 0b00111110, ++ 0b00100010, ++ 0b00100010, ++ 0b00111110 ++ }; ++ ++ const char simpleBar[] = { ++ 0b00111110, ++ 0b00111110, ++ 0b00111110, ++ 0b00111110 ++ }; ++ ++#else + const char hollowBar[] = { + 0b01111111, + 0b01000001, + 0b01000001, + 0b01111111 + }; ++#endif + + uint8_t *p_line = gFrameBuffer[line]; + level = MIN(level, 13); + + for(uint8_t i = 0; i < level; i++) { ++#ifdef ENABLE_FEAT_F4HWN ++ if(i < 9) { ++ memcpy(p_line + (xpos + i * 5), &simpleBar, ARRAY_SIZE(simpleBar)); ++ } ++ else { ++ memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); ++ } ++#else + if(i < 9) { + for(uint8_t j = 0; j < 4; j++) + p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; +@@ -95,6 +125,7 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) + else { + memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); + } ++#endif + } + } + #endif +@@ -125,7 +156,19 @@ void UI_DisplayAudioBar(void) + if(gLowBattery && !gLowBatteryConfirmed) + return; + +- const unsigned int line = 3; ++#ifdef ENABLE_FEAT_F4HWN ++ unsigned int line; ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ line = 5; ++ } ++ else ++ { ++ line = 3; ++ } ++#else ++ const unsigned int line = 3; ++#endif + + if (gCurrentFunction != FUNCTION_TRANSMIT || + gScreenToDisplay != DISPLAY_MAIN +@@ -159,6 +202,11 @@ void UI_DisplayAudioBar(void) + } + #endif + ++#ifdef ENABLE_FEAT_F4HWN ++ static int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { ++ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; ++ } ++#endif + + void DisplayRSSIBar(const bool now) + { +@@ -167,10 +215,58 @@ void DisplayRSSIBar(const bool now) + const unsigned int txt_width = 7 * 8; // 8 text chars + const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph + +- const unsigned int line = 3; ++#ifdef ENABLE_FEAT_F4HWN ++ ++const char empty[] = { ++ 0b00000000, ++ 0b00000000, ++ 0b00000000, ++ 0b00000000, ++ 0b00000000, ++ 0b00000000, ++ 0b00000000, ++}; ++ unsigned int line; ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ line = 5; ++ } ++ else ++ { ++ line = 3; ++ } ++ ++ char rx[4]; ++ //sprintf(String, "%d", RXCounter); ++ //UI_PrintStringSmallBold(String, 80, 0, RXLine); ++ ++ if(RXLine >= 0 && center_line != CENTER_LINE_IN_USE) ++ { ++ if(RXCounter == true) ++ { ++ sprintf(rx, "%s", "RX"); ++ //UI_PrintStringSmallBold("RX", 14, 0, RXLine); ++ RXCounter = false; ++ } ++ else ++ { ++ sprintf(rx, "%s", " "); ++ memcpy(gFrameBuffer[RXLine] + 14, &empty, ARRAY_SIZE(empty)); ++ memcpy(gFrameBuffer[RXLine] + 21, &empty, ARRAY_SIZE(empty)); ++ ++ //UI_PrintStringSmallBold(" ", 14, 0, RXLine); ++ RXCounter = true; ++ } ++ UI_PrintStringSmallBold(rx, 14, 0, RXLine); ++ ST7565_BlitLine(RXLine); ++ } ++#else ++ const unsigned int line = 3; ++#endif + uint8_t *p_line = gFrameBuffer[line]; + char str[16]; + ++#ifndef ENABLE_FEAT_F4HWN + const char plus[] = { + 0b00011000, + 0b00011000, +@@ -180,6 +276,7 @@ void DisplayRSSIBar(const bool now) + 0b00011000, + 0b00011000, + }; ++#endif + + if ((gEeprom.KEY_LOCK && gKeypadLocked > 0) || center_line != CENTER_LINE_RSSI) + return; // display is in use +@@ -196,6 +293,32 @@ void DisplayRSSIBar(const bool now) + memset(p_line, 0, LCD_WIDTH); + + ++#ifdef ENABLE_FEAT_F4HWN ++ int16_t rssi_dBm = ++ BK4819_GetRSSI_dBm() ++#ifdef ENABLE_AM_FIX ++ + ((gSetting_AM_fix && gRxVfo->Modulation == MODULATION_AM) ? AM_fix_get_gain_diff() : 0) ++#endif ++ + dBmCorrTable[gRxVfo->Band]; ++ ++ rssi_dBm = -rssi_dBm; ++ ++ if(rssi_dBm > 141) rssi_dBm = 141; ++ if(rssi_dBm < 53) rssi_dBm = 53; ++ ++ uint8_t s_level = 0; ++ uint8_t overS9dBm = 0; ++ uint8_t overS9Bars = 0; ++ ++ if(rssi_dBm >= 93) { ++ s_level = map(rssi_dBm, 141, 93, 1, 9); ++ } ++ else { ++ s_level = 9; ++ overS9dBm = map(rssi_dBm, 93, 53, 0, 40); ++ overS9Bars = map(overS9dBm, 0, 40, 0, 4); ++ } ++#else + const int16_t s0_dBm = -gEeprom.S0_LEVEL; // S0 .. base level + const int16_t rssi_dBm = + BK4819_GetRSSI_dBm() +@@ -208,16 +331,32 @@ void DisplayRSSIBar(const bool now) + const uint8_t s_level = MIN(MAX((int32_t)(rssi_dBm - s0_dBm)*100 / (s0_9*100/9), 0), 9); // S0 - S9 + uint8_t overS9dBm = MIN(MAX(rssi_dBm + gEeprom.S9_LEVEL, 0), 99); + uint8_t overS9Bars = MIN(overS9dBm/10, 4); ++#endif + ++#ifdef ENABLE_FEAT_F4HWN ++ if(overS9Bars == 0) { ++ sprintf(str, "% 4d", -rssi_dBm); ++ UI_PrintStringSmallNormal(str, LCD_WIDTH + 8, 0, line - 1); ++ sprintf(str, "S%d", s_level); ++ UI_PrintStringSmallBold(str, LCD_WIDTH + 38, 0, line - 1); ++ } ++ else { ++ sprintf(str, "% 4d", -rssi_dBm); ++ UI_PrintStringSmallNormal(str, LCD_WIDTH + 8, 0, line - 1); ++ sprintf(str, "+%02d", overS9dBm); ++ UI_PrintStringSmallBold(str, LCD_WIDTH + 38, 0, line - 1); ++ } ++#else + if(overS9Bars == 0) { +- sprintf(str, "% 4d S%d", rssi_dBm, s_level); ++ sprintf(str, "% 4d S%d", -rssi_dBm, s_level); + } + else { +- sprintf(str, "% 4d %2d", rssi_dBm, overS9dBm); ++ sprintf(str, "% 4d %2d", -rssi_dBm, overS9dBm); + memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus)); + } + + UI_PrintStringSmallNormal(str, 2, 0, line); ++#endif + DrawLevelBar(bar_x, line, s_level + overS9Bars); + if (now) + ST7565_BlitLine(line); +@@ -329,6 +468,39 @@ void UI_DisplayMain(void) + + for (unsigned int vfo_num = 0; vfo_num < 2; vfo_num++) + { ++ ++#ifdef ENABLE_FEAT_F4HWN ++ const unsigned int line0 = 0; // text screen line ++ const unsigned int line1 = 4; ++ unsigned int line; ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ line = 0; ++ ++ /* ++ UI_DrawLineBuffer(gFrameBuffer, 0, 0, 10, 0, 1); ++ UI_DrawLineBuffer(gFrameBuffer, 117, 0, 127, 0, 1); ++ UI_DrawLineBuffer(gFrameBuffer, 0, 0, 0, 7, 1); ++ UI_DrawLineBuffer(gFrameBuffer, 127, 0, 127, 7, 1); ++ ++ UI_DrawLineBuffer(gFrameBuffer, 0, 46, 10, 46, 1); ++ UI_DrawLineBuffer(gFrameBuffer, 117, 46, 127, 46, 1); ++ UI_DrawLineBuffer(gFrameBuffer, 0, 46, 0, 39, 1); ++ UI_DrawLineBuffer(gFrameBuffer, 127, 46, 127, 39, 1); ++ */ ++ ++ //UI_DrawLineBuffer(gFrameBuffer, 0, 4, 127, 4, 1); ++ //UI_DrawLineBuffer(gFrameBuffer, 0, 42, 127, 42, 1); ++ } ++ else ++ { ++ line = (vfo_num == 0) ? line0 : line1; ++ } ++ const bool isMainVFO = (vfo_num == gEeprom.TX_VFO); ++ uint8_t *p_line0 = gFrameBuffer[line + 0]; ++ uint8_t *p_line1 = gFrameBuffer[line + 1]; ++ enum Vfo_txtr_mode mode = VFO_MODE_NONE; ++#else + const unsigned int line0 = 0; // text screen line + const unsigned int line1 = 4; + const unsigned int line = (vfo_num == 0) ? line0 : line1; +@@ -336,6 +508,17 @@ void UI_DisplayMain(void) + uint8_t *p_line0 = gFrameBuffer[line + 0]; + uint8_t *p_line1 = gFrameBuffer[line + 1]; + enum Vfo_txtr_mode mode = VFO_MODE_NONE; ++#endif ++ ++#ifdef ENABLE_FEAT_F4HWN ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ if (activeTxVFO != vfo_num) ++ { ++ continue; ++ } ++ } ++#endif + + if (activeTxVFO != vfo_num) // this is not active TX VFO + { +@@ -428,7 +611,20 @@ void UI_DisplayMain(void) + { // receiving .. show the RX symbol + mode = VFO_MODE_RX; + if (FUNCTION_IsRx() && gEeprom.RX_VFO == vfo_num) { +- UI_PrintStringSmallBold("RX", 14, 0, line); ++ ++#ifdef ENABLE_FEAT_F4HWN ++ if(!isMainVFO) ++ { ++ RXLine = line; ++ } ++ else ++ { ++ RXLine = -1; ++ UI_PrintStringSmallBold("RX", 14, 0, line); ++ } ++#else ++ UI_PrintStringSmallBold("RX", 14, 0, line); ++#endif + } + } + +@@ -570,10 +766,51 @@ void UI_DisplayMain(void) + UI_PrintString(String, 32, 0, line, 8); + } + else { +- UI_PrintStringSmallBold(String, 32 + 4, 0, line); +- // show the channel frequency below the channel number/name +- sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); +- UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); ++#ifdef ENABLE_FEAT_F4HWN ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ UI_PrintString(String, 32, 0, line, 8); ++ } ++ else ++ { ++ if(activeTxVFO == vfo_num) { ++ UI_PrintStringSmallBold(String, 32 + 4, 0, line); ++ } ++ else ++ { ++ UI_PrintStringSmallNormal(String, 32 + 4, 0, line); ++ } ++ } ++#else ++ UI_PrintStringSmallBold(String, 32 + 4, 0, line); ++#endif ++ ++#ifdef ENABLE_FEAT_F4HWN ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); ++ if(frequency < _1GHz_in_KHz) { ++ // show the remaining 2 small frequency digits ++ UI_PrintStringSmallNormal(String + 7, 113, 0, line + 4); ++ String[7] = 0; ++ // show the main large frequency digits ++ UI_DisplayFrequency(String, 32, line + 3, false); ++ } ++ else ++ { ++ // show the frequency in the main font ++ UI_PrintString(String, 32, 0, line + 3, 8); ++ } ++ } ++ else ++ { ++ sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); ++ UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); ++ } ++#else // show the channel frequency below the channel number/name ++ sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); ++ UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); ++#endif + } + + break; +@@ -641,6 +878,24 @@ void UI_DisplayMain(void) + String[0] = '\0'; + const VFO_Info_t *vfoInfo = &gEeprom.VfoInfo[vfo_num]; + ++/* ++#ifdef ENABLE_FEAT_F4HWN ++ // show the TX power in watts ++ const char low_pwr_list[][7] = {"125mW","250mW", "500mW", "1W", "< 20mW"}; ++ switch (vfoInfo->OUTPUT_POWER) ++ { ++ case 0: ++ UI_PrintStringSmallNormal(low_pwr_list[gSetting_set_low], 0, 0, line + 2); ++ break; ++ case 1: ++ UI_PrintStringSmallNormal("2W", 0, 0, line + 2); ++ break; ++ case 2: ++ UI_PrintStringSmallNormal("5W", 0, 0, line + 2); ++ break; ++ } ++#endif ++*/ + // show the modulation symbol + const char * s = ""; + const ModulationMode_t mod = vfoInfo->Modulation; +@@ -689,6 +944,7 @@ void UI_DisplayMain(void) + // show the audio scramble symbol + if (vfoInfo->SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable) + UI_PrintStringSmallNormal("SCR", LCD_WIDTH + 106, 0, line + 1); ++ + } + + #ifdef ENABLE_AGC_SHOW_DATA +@@ -751,7 +1007,20 @@ void UI_DisplayMain(void) + center_line = CENTER_LINE_DTMF_DEC; + + sprintf(String, "DTMF %s", gDTMF_RX_live + idx); +- UI_PrintStringSmallNormal(String, 2, 0, 3); ++ ++#ifdef ENABLE_FEAT_F4HWN ++ if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) ++ { ++ UI_PrintStringSmallNormal(String, 2, 0, 5); ++ } ++ else ++ { ++ UI_PrintStringSmallNormal(String, 2, 0, 3); ++ } ++#else ++ UI_PrintStringSmallNormal(String, 2, 0, 3); ++ ++#endif + } + #else + if (gSetting_live_DTMF_decoder && gDTMF_RX_index > 0) +@@ -790,7 +1059,6 @@ void UI_DisplayMain(void) + #endif + } + } +- + ST7565_BlitFullScreen(); + } + \ No newline at end of file diff --git a/driver/backlight.c b/driver/backlight.c index 0d00c99ba..d3c596fce 100644 --- a/driver/backlight.c +++ b/driver/backlight.c @@ -21,6 +21,10 @@ #include "driver/gpio.h" #include "settings.h" +#ifdef ENABLE_FEAT_F4HWN + #include "driver/system.h" +#endif + // this is decremented once every 500ms uint16_t gBacklightCountdown_500ms = 0; bool backlightOn; @@ -60,7 +64,25 @@ void BACKLIGHT_TurnOn(void) } backlightOn = true; + +#ifdef ENABLE_FEAT_F4HWN + static bool k5Startup = true; + + if(k5Startup == true) { + for(uint8_t i = 0; i <= gEeprom.BACKLIGHT_MAX; i++) + { + BACKLIGHT_SetBrightness(i); + SYSTEM_DelayMs(50); + } + k5Startup = false; + } + else + { + BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); + } +#else BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX); +#endif switch (gEeprom.BACKLIGHT_TIME) { default: diff --git a/misc.c b/misc.c index e322e3f61..e6f04dc36 100644 --- a/misc.c +++ b/misc.c @@ -95,6 +95,11 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; bool gSetting_AM_fix; #endif +#ifdef ENABLE_FEAT_F4HWN + uint8_t gSetting_set_low; + bool gSetting_set_ptt; +#endif + #ifdef ENABLE_AUDIO_BAR bool gSetting_mic_bar; #endif @@ -132,6 +137,11 @@ volatile bool gNextTimeslice_500ms; volatile uint16_t gTxTimerCountdown_500ms; volatile bool gTxTimeoutReached; +#ifdef ENABLE_FEAT_F4HWN + volatile uint16_t gTxTimerCountdownAlert_500ms; + volatile bool gTxTimeoutReachedAlert; +#endif + volatile uint16_t gTailNoteEliminationCountdown_10ms; volatile uint8_t gVFOStateResumeCountdown_500ms; @@ -247,6 +257,12 @@ volatile uint8_t boot_counter_10ms; uint8_t gIsLocked = 0xFF; +#ifdef ENABLE_FEAT_F4HWN + bool gPttOnePush = true; + uint8_t gPttOnePushCounter = 0; + uint32_t gBlinkCounter = 0; +#endif + inline void FUNCTION_NOP() { ; } diff --git a/misc.h b/misc.h index ed81573e2..8da173191 100644 --- a/misc.h +++ b/misc.h @@ -156,6 +156,11 @@ extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; extern bool gSetting_AM_fix; #endif +#ifdef ENABLE_FEAT_F4HWN + extern uint8_t gSetting_set_low; + extern bool gSetting_set_ptt; +#endif + #ifdef ENABLE_AUDIO_BAR extern bool gSetting_mic_bar; #endif @@ -205,6 +210,11 @@ extern volatile bool gNextTimeslice_500ms; extern volatile uint16_t gTxTimerCountdown_500ms; extern volatile bool gTxTimeoutReached; +#ifdef ENABLE_FEAT_F4HWN + extern volatile uint16_t gTxTimerCountdownAlert_500ms; + extern volatile bool gTxTimeoutReachedAlert; +#endif + extern volatile uint16_t gTailNoteEliminationCountdown_10ms; #ifdef ENABLE_NOAA @@ -323,6 +333,11 @@ extern volatile uint8_t gVFOStateResumeCountdown_500ms; extern uint8_t gIsLocked; extern volatile uint8_t boot_counter_10ms; +#ifdef ENABLE_FEAT_F4HWN + extern uint8_t gPttOnePushCounter; + extern uint32_t gBlinkCounter; +#endif + int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit); unsigned long StrToUL(const char * str); diff --git a/radio.c b/radio.c index 93a6e500c..27cf03b7e 100644 --- a/radio.c +++ b/radio.c @@ -455,21 +455,75 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo) Band = FREQUENCY_GetBand(pInfo->pTX->Frequency); + // my eeprom calibration data + // + // 1ED0 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 50 MHz + // 1EE0 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 108 MHz + // 1EF0 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 137 MHz + // 1F00 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 174 MHz + // 1F10 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 350 MHz + // 1F20 5f 5f 5f 69 69 69 87 87 87 ff ff ff ff ff ff ff 400 MHz + // 1F30 32 32 32 64 64 64 8c 8c 8c ff ff ff ff ff ff ff 470 MHz + uint8_t Txp[3]; EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (pInfo->OUTPUT_POWER * 3), Txp, 3); -#ifdef ENABLE_REDUCE_LOW_MID_TX_POWER +#ifdef ENABLE_FEAT_F4HWN // make low and mid even lower if (pInfo->OUTPUT_POWER == OUTPUT_POWER_LOW) { - Txp[0] /= 5; - Txp[1] /= 5; - Txp[2] /= 5; + switch (gSetting_set_low) { + case 0: + Txp[0] = (Txp[0] * 4) / 19; + Txp[1] = (Txp[1] * 4) / 19; + Txp[2] = (Txp[2] * 4) / 19; + break; + case 1: + Txp[0] = (Txp[0] * 4) / 13; + Txp[1] = (Txp[1] * 4) / 13; + Txp[2] = (Txp[2] * 4) / 13; + break; + case 2: + Txp[0] = (Txp[0] * 4) / 10; + Txp[1] = (Txp[1] * 4) / 10; + Txp[2] = (Txp[2] * 4) / 10; + break; + case 3: + Txp[0] = (Txp[0] * 4) / 7; + Txp[1] = (Txp[1] * 4) / 7; + Txp[2] = (Txp[2] * 4) / 7; + break; + case 4: + Txp[0] = (Txp[0] * 4) / 25; + Txp[1] = (Txp[1] * 4) / 25; + Txp[2] = (Txp[2] * 4) / 25; + break; + } } else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_MID){ - Txp[0] /= 3; - Txp[1] /= 3; - Txp[2] /= 3; + Txp[0] = (Txp[0] * 3) / 4; + Txp[1] = (Txp[1] * 3) / 4; + Txp[2] = (Txp[2] * 3) / 4; + } + // increase high + else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_HIGH){ + Txp[0] = Txp[0] + 30; + Txp[1] = Txp[1] + 30; + Txp[2] = Txp[2] + 30; } +#else + #ifdef ENABLE_REDUCE_LOW_MID_TX_POWER + // make low and mid even lower + if (pInfo->OUTPUT_POWER == OUTPUT_POWER_LOW) { + Txp[0] /= 5; + Txp[1] /= 5; + Txp[2] /= 5; + } + else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_MID){ + Txp[0] /= 3; + Txp[1] /= 3; + Txp[2] /= 3; + } + #endif #endif pInfo->TXP_CalculatedSetting = FREQUENCY_CalculateOutputPower( @@ -993,9 +1047,18 @@ void RADIO_PrepareTX(void) gTxTimerCountdown_500ms = 120 * gEeprom.TX_TIMEOUT_TIMER; // minutes else gTxTimerCountdown_500ms = 120 * 15; // 15 minutes + +#ifdef ENABLE_FEAT_F4HWN + gTxTimerCountdownAlert_500ms = gTxTimerCountdown_500ms; +#endif } gTxTimeoutReached = false; + +#ifdef ENABLE_FEAT_F4HWN + gTxTimeoutReachedAlert = false; +#endif + gFlagEndTransmission = false; gRTTECountdown_10ms = 0; diff --git a/scheduler.c b/scheduler.c index f76b4a600..8ed2b891a 100644 --- a/scheduler.c +++ b/scheduler.c @@ -55,6 +55,10 @@ void SystickHandler(void) if ((gGlobalSysTickCounter % 50) == 0) { gNextTimeslice_500ms = true; + +#ifdef ENABLE_FEAT_F4HWN + DECREMENT_AND_TRIGGER(gTxTimerCountdownAlert_500ms - ALERT_TOT * 2, gTxTimeoutReachedAlert); +#endif DECREMENT_AND_TRIGGER(gTxTimerCountdown_500ms, gTxTimeoutReached); DECREMENT(gSerialConfigCountDown_500ms); diff --git a/settings.c b/settings.c index 68a1926ad..3b81e40c6 100644 --- a/settings.c +++ b/settings.c @@ -277,6 +277,13 @@ void SETTINGS_InitEEPROM(void) return; } } + + #ifdef ENABLE_FEAT_F4HWN + // 1FF0..0x1FF7 + EEPROM_ReadBuffer(0x1FF0, Data, 8); + gSetting_set_low = (Data[7] < 5) ? Data[7] : 0; + gSetting_set_ptt = (Data[6] < 2) ? Data[6] : 0; + #endif } void SETTINGS_LoadCalibration(void) @@ -592,6 +599,13 @@ void SETTINGS_SaveSettings(void) State[7] = (State[7] & ~(3u << 6)) | ((gSetting_backlight_on_tx_rx & 3u) << 6); EEPROM_WriteBuffer(0x0F40, State); + +#ifdef ENABLE_FEAT_F4HWN + memset(State, 0xFF, sizeof(State)); + State[6] = gSetting_set_ptt; + State[7] = gSetting_set_low; + EEPROM_WriteBuffer(0x1FF0, State); +#endif } void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO, uint8_t Mode) @@ -714,6 +728,11 @@ void SETTINGS_UpdateChannel(uint8_t channel, const VFO_Info_t *pVFO, bool keep) void SETTINGS_WriteBuildOptions(void) { uint8_t buf[8] = {0}; + +#ifdef ENABLE_FEAT_F4HWN + EEPROM_ReadBuffer(0x1FF0, buf, 8); +#endif + buf[0] = 0 #ifdef ENABLE_FMRADIO | (1 << 0) diff --git a/settings.h b/settings.h index eadf2fe2f..2b587ca4c 100644 --- a/settings.h +++ b/settings.h @@ -90,6 +90,10 @@ enum ACTION_OPT_t { ACTION_OPT_VFO_MR, ACTION_OPT_SWITCH_DEMODUL, ACTION_OPT_BLMIN_TMP_OFF, //BackLight Minimum Temporay OFF +#ifdef ENABLE_FEAT_F4HWN + ACTION_OPT_MAIN, + ACTION_OPT_PTT, +#endif ACTION_OPT_LEN }; diff --git a/ui/helper.c b/ui/helper.c index 63bf58199..0ed875869 100644 --- a/ui/helper.c +++ b/ui/helper.c @@ -198,6 +198,28 @@ static void sort(int16_t *a, int16_t *b) } } +#ifdef ENABLE_FEAT_F4HWN + void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) + { + if(x2==x1) { + sort(&y1, &y2); + for(int16_t i = y1; i <= y2; i+=2) { + UI_DrawPixelBuffer(buffer, x1, i, black); + } + } else { + const int multipl = 1000; + int a = (y2-y1)*multipl / (x2-x1); + int b = y1 - a * x1 / multipl; + + sort(&x1, &x2); + for(int i = x1; i<= x2; i+=2) + { + UI_DrawPixelBuffer(buffer, i, i*a/multipl +b, black); + } + } + } +#endif + void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black) { if(x2==x1) { diff --git a/ui/helper.h b/ui/helper.h index 8401a9b3e..27b339bfc 100644 --- a/ui/helper.h +++ b/ui/helper.h @@ -32,6 +32,9 @@ void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center); void UI_DisplayPopup(const char *string); void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black); +#ifdef ENABLE_FEAT_F4HWN + void UI_DrawLineDottedBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); +#endif void UI_DrawLineBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); void UI_DrawRectangleBuffer(uint8_t (*buffer)[128], int16_t x1, int16_t y1, int16_t x2, int16_t y2, bool black); diff --git a/ui/main.c b/ui/main.c index eb17b1f86..0c14654bf 100644 --- a/ui/main.c +++ b/ui/main.c @@ -39,6 +39,11 @@ center_line_t center_line = CENTER_LINE_NONE; +#ifdef ENABLE_FEAT_F4HWN + static bool RXCounter; + static int8_t RXLine; +#endif + const int8_t dBmCorrTable[7] = { -15, // band 1 -25, // band 2 @@ -77,17 +82,42 @@ static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level) static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) { +#ifdef ENABLE_FEAT_F4HWN + const char hollowBar[] = { + 0b00111110, + 0b00100010, + 0b00100010, + 0b00111110 + }; + + const char simpleBar[] = { + 0b00111110, + 0b00111110, + 0b00111110, + 0b00111110 + }; + +#else const char hollowBar[] = { 0b01111111, 0b01000001, 0b01000001, 0b01111111 }; - +#endif + uint8_t *p_line = gFrameBuffer[line]; level = MIN(level, 13); for(uint8_t i = 0; i < level; i++) { +#ifdef ENABLE_FEAT_F4HWN + if(i < 9) { + memcpy(p_line + (xpos + i * 5), &simpleBar, ARRAY_SIZE(simpleBar)); + } + else { + memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); + } +#else if(i < 9) { for(uint8_t j = 0; j < 4; j++) p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F; @@ -95,6 +125,7 @@ static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level) else { memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar)); } +#endif } } #endif @@ -125,7 +156,19 @@ void UI_DisplayAudioBar(void) if(gLowBattery && !gLowBatteryConfirmed) return; - const unsigned int line = 3; +#ifdef ENABLE_FEAT_F4HWN + unsigned int line; + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + line = 5; + } + else + { + line = 3; + } +#else + const unsigned int line = 3; +#endif if (gCurrentFunction != FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN @@ -159,6 +202,11 @@ void UI_DisplayAudioBar(void) } #endif +#ifdef ENABLE_FEAT_F4HWN + static int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; + } +#endif void DisplayRSSIBar(const bool now) { @@ -167,10 +215,58 @@ void DisplayRSSIBar(const bool now) const unsigned int txt_width = 7 * 8; // 8 text chars const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph - const unsigned int line = 3; +#ifdef ENABLE_FEAT_F4HWN + const char empty[] = { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }; + + unsigned int line; + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + line = 5; + } + else + { + line = 3; + } + + char rx[4]; + //sprintf(String, "%d", RXCounter); + //UI_PrintStringSmallBold(String, 80, 0, RXLine); + + if(RXLine >= 0 && center_line != CENTER_LINE_IN_USE) + { + if(RXCounter == true) + { + sprintf(rx, "%s", "RX"); + //UI_PrintStringSmallBold("RX", 14, 0, RXLine); + RXCounter = false; + } + else + { + sprintf(rx, "%s", " "); + memcpy(gFrameBuffer[RXLine] + 14, &empty, ARRAY_SIZE(empty)); + memcpy(gFrameBuffer[RXLine] + 21, &empty, ARRAY_SIZE(empty)); + + //UI_PrintStringSmallBold(" ", 14, 0, RXLine); + RXCounter = true; + } + UI_PrintStringSmallBold(rx, 14, 0, RXLine); + ST7565_BlitLine(RXLine); + } +#else + const unsigned int line = 3; +#endif uint8_t *p_line = gFrameBuffer[line]; char str[16]; +#ifndef ENABLE_FEAT_F4HWN const char plus[] = { 0b00011000, 0b00011000, @@ -180,6 +276,7 @@ void DisplayRSSIBar(const bool now) 0b00011000, 0b00011000, }; +#endif if ((gEeprom.KEY_LOCK && gKeypadLocked > 0) || center_line != CENTER_LINE_RSSI) return; // display is in use @@ -195,7 +292,32 @@ void DisplayRSSIBar(const bool now) if (now) memset(p_line, 0, LCD_WIDTH); +#ifdef ENABLE_FEAT_F4HWN + int16_t rssi_dBm = + BK4819_GetRSSI_dBm() +#ifdef ENABLE_AM_FIX + + ((gSetting_AM_fix && gRxVfo->Modulation == MODULATION_AM) ? AM_fix_get_gain_diff() : 0) +#endif + + dBmCorrTable[gRxVfo->Band]; + + rssi_dBm = -rssi_dBm; + + if(rssi_dBm > 141) rssi_dBm = 141; + if(rssi_dBm < 53) rssi_dBm = 53; + + uint8_t s_level = 0; + uint8_t overS9dBm = 0; + uint8_t overS9Bars = 0; + if(rssi_dBm >= 93) { + s_level = map(rssi_dBm, 141, 93, 1, 9); + } + else { + s_level = 9; + overS9dBm = map(rssi_dBm, 93, 53, 0, 40); + overS9Bars = map(overS9dBm, 0, 40, 0, 4); + } +#else const int16_t s0_dBm = -gEeprom.S0_LEVEL; // S0 .. base level const int16_t rssi_dBm = BK4819_GetRSSI_dBm() @@ -208,16 +330,32 @@ void DisplayRSSIBar(const bool now) const uint8_t s_level = MIN(MAX((int32_t)(rssi_dBm - s0_dBm)*100 / (s0_9*100/9), 0), 9); // S0 - S9 uint8_t overS9dBm = MIN(MAX(rssi_dBm + gEeprom.S9_LEVEL, 0), 99); uint8_t overS9Bars = MIN(overS9dBm/10, 4); +#endif +#ifdef ENABLE_FEAT_F4HWN if(overS9Bars == 0) { - sprintf(str, "% 4d S%d", rssi_dBm, s_level); + sprintf(str, "% 4d", -rssi_dBm); + UI_PrintStringSmallNormal(str, LCD_WIDTH + 8, 0, line - 1); + sprintf(str, "S%d", s_level); + UI_PrintStringSmallBold(str, LCD_WIDTH + 38, 0, line - 1); } else { - sprintf(str, "% 4d %2d", rssi_dBm, overS9dBm); + sprintf(str, "% 4d", -rssi_dBm); + UI_PrintStringSmallNormal(str, LCD_WIDTH + 8, 0, line - 1); + sprintf(str, "+%02d", overS9dBm); + UI_PrintStringSmallBold(str, LCD_WIDTH + 38, 0, line - 1); + } +#else + if(overS9Bars == 0) { + sprintf(str, "% 4d S%d", -rssi_dBm, s_level); + } + else { + sprintf(str, "% 4d %2d", -rssi_dBm, overS9dBm); memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus)); } UI_PrintStringSmallNormal(str, 2, 0, line); +#endif DrawLevelBar(bar_x, line, s_level + overS9Bars); if (now) ST7565_BlitLine(line); @@ -329,6 +467,23 @@ void UI_DisplayMain(void) for (unsigned int vfo_num = 0; vfo_num < 2; vfo_num++) { +#ifdef ENABLE_FEAT_F4HWN + const unsigned int line0 = 0; // text screen line + const unsigned int line1 = 4; + unsigned int line; + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + line = 0; + } + else + { + line = (vfo_num == 0) ? line0 : line1; + } + const bool isMainVFO = (vfo_num == gEeprom.TX_VFO); + uint8_t *p_line0 = gFrameBuffer[line + 0]; + uint8_t *p_line1 = gFrameBuffer[line + 1]; + enum Vfo_txtr_mode mode = VFO_MODE_NONE; +#else const unsigned int line0 = 0; // text screen line const unsigned int line1 = 4; const unsigned int line = (vfo_num == 0) ? line0 : line1; @@ -336,7 +491,17 @@ void UI_DisplayMain(void) uint8_t *p_line0 = gFrameBuffer[line + 0]; uint8_t *p_line1 = gFrameBuffer[line + 1]; enum Vfo_txtr_mode mode = VFO_MODE_NONE; +#endif +#ifdef ENABLE_FEAT_F4HWN + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + if (activeTxVFO != vfo_num) + { + continue; + } + } +#endif if (activeTxVFO != vfo_num) // this is not active TX VFO { #ifdef ENABLE_SCAN_RANGES @@ -428,7 +593,19 @@ void UI_DisplayMain(void) { // receiving .. show the RX symbol mode = VFO_MODE_RX; if (FUNCTION_IsRx() && gEeprom.RX_VFO == vfo_num) { +#ifdef ENABLE_FEAT_F4HWN + if(!isMainVFO) + { + RXLine = line; + } + else + { + RXLine = -1; + UI_PrintStringSmallBold("RX", 14, 0, line); + } +#else UI_PrintStringSmallBold("RX", 14, 0, line); +#endif } } @@ -570,10 +747,51 @@ void UI_DisplayMain(void) UI_PrintString(String, 32, 0, line, 8); } else { +#ifdef ENABLE_FEAT_F4HWN + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + UI_PrintString(String, 32, 0, line, 8); + } + else + { + if(activeTxVFO == vfo_num) { + UI_PrintStringSmallBold(String, 32 + 4, 0, line); + } + else + { + UI_PrintStringSmallNormal(String, 32 + 4, 0, line); + } + } +#else UI_PrintStringSmallBold(String, 32 + 4, 0, line); - // show the channel frequency below the channel number/name +#endif + +#ifdef ENABLE_FEAT_F4HWN + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000); + if(frequency < _1GHz_in_KHz) { + // show the remaining 2 small frequency digits + UI_PrintStringSmallNormal(String + 7, 113, 0, line + 4); + String[7] = 0; + // show the main large frequency digits + UI_DisplayFrequency(String, 32, line + 3, false); + } + else + { + // show the frequency in the main font + UI_PrintString(String, 32, 0, line + 3, 8); + } + } + else + { + sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); + UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); + } +#else // show the channel frequency below the channel number/name sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000); UI_PrintStringSmallNormal(String, 32 + 4, 0, line + 1); +#endif } break; @@ -751,7 +969,19 @@ void UI_DisplayMain(void) center_line = CENTER_LINE_DTMF_DEC; sprintf(String, "DTMF %s", gDTMF_RX_live + idx); +#ifdef ENABLE_FEAT_F4HWN + if ((gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2 == 0) + { + UI_PrintStringSmallNormal(String, 2, 0, 5); + } + else + { + UI_PrintStringSmallNormal(String, 2, 0, 3); + } +#else UI_PrintStringSmallNormal(String, 2, 0, 3); + +#endif } #else if (gSetting_live_DTMF_decoder && gDTMF_RX_index > 0) diff --git a/ui/menu.c b/ui/menu.c index 62f5b7192..ed53967b4 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -123,7 +123,10 @@ const t_menu_item MenuList[] = {"BatVol", VOICE_ID_INVALID, MENU_VOL }, // was "VOL" {"RxMode", VOICE_ID_DUAL_STANDBY, MENU_TDR }, {"Sql", VOICE_ID_SQUELCH, MENU_SQL }, - +#ifdef ENABLE_FEAT_F4HWN + {"SetLow", VOICE_ID_INVALID, MENU_SET_LOW }, + {"SetPtt", VOICE_ID_INVALID, MENU_SET_PTT }, +#endif // hidden menu items from here on // enabled if pressing both the PTT and upper side button at power-on {"F Lock", VOICE_ID_INVALID, MENU_F_LOCK }, @@ -334,6 +337,23 @@ const char gSubMenu_SCRAMBLER[][7] = "3500Hz" }; +#ifdef ENABLE_FEAT_F4HWN + const char gSubMenu_SET_LOW[][7] = + { + "125mW", + "250mW", + "500mW", + "1W", + "< 20mW" + }; + + const char gSubMenu_SET_PTT[][8] = + { + "Classic", + "OnePush" + }; +#endif + const t_sidefunction gSubMenu_SIDEFUNCTIONS[] = { {"NONE", ACTION_OPT_NONE}, @@ -362,6 +382,10 @@ const t_sidefunction gSubMenu_SIDEFUNCTIONS[] = #ifdef ENABLE_BLMIN_TMP_OFF {"BLMIN\nTMP OFF", ACTION_OPT_BLMIN_TMP_OFF}, //BackLight Minimum Temporay OFF #endif +#ifdef ENABLE_FEAT_F4HWN + {"SWITCH\nMAIN ONLY", ACTION_OPT_MAIN}, + {"SWITCH\nPTT", ACTION_OPT_PTT}, +#endif }; const uint8_t gSubMenu_SIDEFUNCTIONS_size = ARRAY_SIZE(gSubMenu_SIDEFUNCTIONS); @@ -404,6 +428,11 @@ void UI_DisplayMenu(void) UI_DisplayClear(); +#ifdef ENABLE_FEAT_F4HWN + UI_DrawLineBuffer(gFrameBuffer, 50, 0, 50, 63, 1); // Be ware, limit is 63 pixels (not 64) + UI_DrawLineDottedBuffer(gFrameBuffer, 0, 46, 50, 46, 1); +#endif + #ifndef ENABLE_CUSTOM_MENU_LAYOUT // original menu layout for (i = 0; i < 3; i++) @@ -427,8 +456,11 @@ void UI_DisplayMenu(void) memcpy(gFrameBuffer[0] + (8 * menu_list_width) + 1, BITMAP_CurrentIndicator, sizeof(BITMAP_CurrentIndicator)); // draw the menu index number/count +#ifdef ENABLE_FEAT_F4HWN + sprintf(String, "%02u/%u", 1 + gMenuCursor, gMenuListCount); +#else sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount); - +#endif UI_PrintStringSmallNormal(String, 2, 0, 6); #else @@ -839,6 +871,15 @@ void UI_DisplayMenu(void) strcpy(String, gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].name); break; +#ifdef ENABLE_FEAT_F4HWN + case MENU_SET_LOW: + strcpy(String, gSubMenu_SET_LOW[gSubMenuSelection]); + break; + + case MENU_SET_PTT: + strcpy(String, gSubMenu_SET_PTT[gSubMenuSelection]); + break; +#endif } if (!already_printed) diff --git a/ui/menu.h b/ui/menu.h index 16f5c1cd0..93e052c49 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -116,6 +116,10 @@ enum MENU_SCREN, #ifdef ENABLE_F_CAL_MENU MENU_F_CALI, // reference xtal calibration +#endif +#ifdef ENABLE_FEAT_F4HWN + MENU_SET_LOW, + MENU_SET_PTT, #endif MENU_BATCAL, // battery voltage calibration MENU_F1SHRT, @@ -148,6 +152,12 @@ extern const char* const gSubMenu_MDF[4]; #ifdef ENABLE_DTMF_CALLING extern const char gSubMenu_D_RSP[4][11]; #endif + +#ifdef ENABLE_FEAT_F4HWN + extern const char gSubMenu_SET_LOW[5][7]; + extern const char gSubMenu_SET_PTT[2][8]; +#endif + extern const char* const gSubMenu_PTT_ID[5]; extern const char gSubMenu_PONMSG[4][8]; extern const char gSubMenu_ROGER[3][6]; diff --git a/ui/welcome.c b/ui/welcome.c index 71b309fbd..08d95bfb5 100644 --- a/ui/welcome.c +++ b/ui/welcome.c @@ -69,7 +69,13 @@ void UI_DisplayWelcome(void) UI_PrintString(WelcomeString0, 0, 127, 0, 10); UI_PrintString(WelcomeString1, 0, 127, 2, 10); + +#ifdef ENABLE_FEAT_F4HWN + UI_PrintStringSmallNormal(Version, 0, 128, 5); + UI_PrintStringSmallNormal(Feat, 0, 128, 6); +#else UI_PrintStringSmallNormal(Version, 0, 128, 6); +#endif ST7565_BlitStatusLine(); // blank status line ST7565_BlitFullScreen(); diff --git a/version.c b/version.c index 779868184..ca54ca7ef 100644 --- a/version.c +++ b/version.c @@ -5,7 +5,12 @@ #define VER "" #endif - -const char Version[] = AUTHOR_STRING VER; -const char UART_Version[] = "UV-K5 Firmware, Open Edition, " AUTHOR_STRING VER "\r\n"; +#ifdef ENABLE_FEAT_F4HWN + const char Version[] = AUTHOR_STRING " v0.22"; + const char UART_Version[] = "UV-K5 Firmware, Open Edition, " AUTHOR_STRING "\r\n"; + const char Feat[] = "Feat " FEAT_STRING; +#else + const char Version[] = AUTHOR_STRING VER; + const char UART_Version[] = "UV-K5 Firmware, Open Edition, " AUTHOR_STRING VER "\r\n"; +#endif diff --git a/version.h b/version.h index 7d2b848c8..e24718974 100644 --- a/version.h +++ b/version.h @@ -22,3 +22,6 @@ extern const char UART_Version[]; #endif +#ifdef ENABLE_FEAT_F4HWN + extern const char Feat[]; +#endif