Files
uv-k5-ua1zbe-firmware/app/display_rssi.c
ua1zbe a1206d6fd4 UA1ZBE Custom Firmware v1.0
Features:
- VFO mode with direct frequency input
- POCSAG decoder (512/1200 baud) with BCH(31,21) correction
- Full-screen Spectrum analyzer
- FM Radio receiver
- RSSI signal indicator overlay
- Custom boot splash (UA1ZBE / POCSAG pager / build date)

Architecture:
- app/mode.c — mode dispatcher (VFO/POCSAG/Spectrum/FM)
- app/boot_splash.c — 2-second boot splash
- app/pocsag/ — POCSAG decoder + BCH correction
- app/display_rssi.c — RSSI indicator
- main.c — entry point with custom init
- syscalls.c — bare-metal _sbrk stub

Build: arm-none-eabi-gcc -Os -flto -Wall -Werror -Wextra
Size: 57.9KB Flash / 3.6KB RAM

Controls:
- 0-9: Direct frequency input (VFO)
- SK2: POCSAG mode
- SK1: Spectrum analyzer
- 0: FM Radio
- EXIT: Return to VFO
- F/*: Toggle 512/1200 baud (in POCSAG)
2026-04-12 00:44:05 +03:00

129 lines
3.5 KiB
C

/* UA1ZBE Custom Firmware - RSSI Display Implementation
*
* Reads RSSI from BK4819 REG_67 (9-bit value).
* Conversion: dBm = (raw / 2) - 160 + band_correction
*
* Displays as "S:XX" format with optional mini bar.
* Updates every ~150ms via internal counter.
*/
#include "display_rssi.h"
#include "driver/bk4819.h"
#include "driver/st7565.h"
#include "ui/helper.h"
#include "ui/main.h"
#include "misc.h"
#include "radio.h"
#include <string.h>
#include <stdio.h>
/* dBm correction table — defined in ui/main.c */
extern const int8_t dBmCorrTable[7];
/* === Internal state === */
static int16_t s_rssi_dbm;
static uint16_t s_rssi_raw;
static uint8_t s_s_level;
static uint16_t s_update_counter;
/* Update interval: ~15 (150ms at 10ms tick) */
#define RSSI_UPDATE_INTERVAL 15
/* S-meter thresholds (dBm) — simplified from U8RssiMap */
static const int8_t s_thresholds[] = {
-121, -115, -109, -103, -97, -91, -85, -79, -73, -63
};
void RSSI_Init(void)
{
s_rssi_dbm = -160;
s_rssi_raw = 0;
s_s_level = 0;
s_update_counter = 0;
}
void RSSI_Update(void)
{
s_update_counter++;
if (s_update_counter < RSSI_UPDATE_INTERVAL)
return;
s_update_counter = 0;
/* Read raw RSSI from BK4819 */
s_rssi_raw = BK4819_GetRSSI();
/* Convert to dBm: (raw / 2) - 160 + band_correction
* Avoid division: raw >> 1 */
int8_t band_corr = dBmCorrTable[gRxVfo->Band];
s_rssi_dbm = (int16_t)(s_rssi_raw >> 1) - 160 + band_corr;
/* Calculate S-level */
s_s_level = 0;
for (uint8_t i = 0; i < ARRAY_SIZE(s_thresholds); i++) {
if (s_rssi_dbm >= s_thresholds[i]) {
s_s_level = i + 1;
}
}
if (s_s_level > 9)
s_s_level = 9;
}
int16_t RSSI_GetdBm(void)
{
return s_rssi_dbm;
}
uint16_t RSSI_GetRaw(void)
{
return s_rssi_raw;
}
uint8_t RSSI_GetSLevel(void)
{
return s_s_level;
}
/*
* Draw RSSI indicator.
* Format: "S:42" or raw dBm with mini bar.
* Uses small font to fit in upper-right corner.
*/
void RSSI_Draw(int x, int y, bool with_bar)
{
static char buf[16];
/* Draw dBm value: "-87dBm" */
sprintf(buf, "%ddBm", s_rssi_dbm);
UI_PrintStringSmallNormal(buf, x, LCD_WIDTH, y);
if (with_bar) {
/* Draw mini signal bar below the text
* 5 bars, each 2px wide, 1px gap */
int bar_x = x;
int bar_y = y + 8;
uint8_t bars = (s_s_level + 1) / 2; /* 0-5 bars from S0-S9 */
if (bars > 5) bars = 5;
for (uint8_t i = 0; i < 5; i++) {
uint8_t h = 2 + i * 2; /* Bar heights: 2,4,6,8,10 */
if (i < bars) {
/* Draw filled bar */
for (uint8_t py = 0; py < h; py++) {
for (uint8_t px = 0; px < 2; px++) {
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + px, bar_y + (10 - h) + py, true);
}
}
} else {
/* Draw outline only */
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3, bar_y + (10 - h), false);
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + (10 - h), false);
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3, bar_y + 9, false);
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + 9, false);
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3, bar_y + (10 - h) + 1, false);
UI_DrawPixelBuffer(gFrameBuffer, bar_x + i * 3 + 1, bar_y + (10 - h) + 1, false);
}
}
}
}