/* 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 #include /* 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); } } } }