Major code refactoring

This commit is contained in:
mrkusypl committed 2026-03-19 23:09:39 +01:00
1 parent a1f2f0cdb9
commit e28177cb9b
16 files changed
+169 -252

No files matched your search

+12 -43
View File
@@ -554,55 +554,24 @@ void ACTION_Wn(void)
BK4819_SetFilterBandwidth(BK4819_FILTER_BW_AM, true);
return;
}
const bool isRx = FUNCTION_IsRx();
VFO_Info_t *pVfo = isRx ? gRxVfo : gTxVfo;
pVfo->CHANNEL_BANDWIDTH = !pVfo->CHANNEL_BANDWIDTH;
uint8_t bw = pVfo->CHANNEL_BANDWIDTH;
#ifdef ENABLE_FEAT_F4HWN_NARROWER
bool narrower = 0;
if (FUNCTION_IsRx())
if (isRx && bw == BANDWIDTH_NARROW && gSetting_set_nfm == 1)
{
gRxVfo->CHANNEL_BANDWIDTH = (gRxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0;
if(gRxVfo->CHANNEL_BANDWIDTH == BANDWIDTH_NARROW && gSetting_set_nfm == 1)
{
narrower = 1;
bw++;
}
#endif
#ifdef ENABLE_AM_FIX
BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH + narrower, true);
BK4819_SetFilterBandwidth(bw, true);
#else
BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH + narrower, false);
#endif
}
else
{
gTxVfo->CHANNEL_BANDWIDTH = (gTxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0;
if(gTxVfo->CHANNEL_BANDWIDTH == BANDWIDTH_NARROW && gSetting_set_nfm == 1)
{
narrower = 1;
}
#ifdef ENABLE_AM_FIX
BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, true);
#else
BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, false);
#endif
}
#else
if (FUNCTION_IsRx())
{
gRxVfo->CHANNEL_BANDWIDTH = (gRxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0;
#ifdef ENABLE_AM_FIX
BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH, true);
#else
BK4819_SetFilterBandwidth(gRxVfo->CHANNEL_BANDWIDTH, false);
#endif
}
else
{
gTxVfo->CHANNEL_BANDWIDTH = (gTxVfo->CHANNEL_BANDWIDTH == 0) ? 1: 0;
#ifdef ENABLE_AM_FIX
BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, true);
#else
BK4819_SetFilterBandwidth(gTxVfo->CHANNEL_BANDWIDTH, false);
#endif
}
BK4819_SetFilterBandwidth(bw, false);
#endif
}
+9 -6
View File
@@ -172,6 +172,13 @@ static inline void AIRCOPY_CheckComplete(void)
}
}
static inline void AIRCOPY_Obfuscation(void)
{
for (unsigned int i = 0; i < 34; i++) {
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
}
}
// ============================================================================
// Send/Receive Functions
// ============================================================================
@@ -223,9 +230,7 @@ bool AIRCOPY_SendMessage(void)
g_FSK_Buffer[34] = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
for (unsigned int i = 0; i < 34; i++) {
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
}
AIRCOPY_Obfuscation();
RADIO_SetTxParameters();
@@ -261,9 +266,7 @@ void AIRCOPY_StorePacket(void)
return;
}
for (unsigned int i = 0; i < 34; i++) {
g_FSK_Buffer[i + 1] ^= Obfuscation[i % 8];
}
AIRCOPY_Obfuscation();
uint16_t Crc = CRC_Calculate(&g_FSK_Buffer[1], 2 + 64);
if (g_FSK_Buffer[34] != Crc) {
+42 -70
View File
@@ -1165,8 +1165,21 @@ void APP_Update(void)
}
}
void StopTransmitting(void) {
ProcessKey(KEY_PTT, false, false);
gPttIsPressed = false;
if (gKeyReading1 != KEY_INVALID)
gPttWasReleased = true;
#ifdef ENABLE_FEAT_F4HWN
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv();
#endif
#endif
}
// called every 10ms
static void CheckKeys(void)
void CheckKeys(void)
{
#ifdef ENABLE_DTMF_CALLING
if(gSetting_KILLED){
@@ -1181,47 +1194,39 @@ static void CheckKeys(void)
#endif
// -------------------- PTT ------------------------
const bool serialConfigInProgress = SerialConfigInProgress();
#ifdef ENABLE_FEAT_F4HWN
const bool isPressed = GPIO_IsPttPressed() && !serialConfigInProgress;
#else
const bool isPressed = !GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && !serialConfigInProgress;
#endif
#ifdef ENABLE_FEAT_F4HWN
if (gSetting_set_ptt_session)
{
if (GPIO_IsPttPressed() && !SerialConfigInProgress() && gPttOnePushCounter == 0)
{ // PTT pressed
if (++gPttDebounceCounter >= 3) // 30ms
if ((isPressed && (gPttOnePushCounter == 0 || gPttOnePushCounter == 2)) ||
(!isPressed && (gPttOnePushCounter == 1 || gPttOnePushCounter == 3)) ||
serialConfigInProgress)
{
if (++gPttDebounceCounter >= 3 || (serialConfigInProgress && gPttOnePushCounter > 0))
{
gPttDebounceCounter = 0;
if (gPttOnePushCounter == 0)
{ // start transmitting
boot_counter_10ms = 0;
gPttDebounceCounter = 0;
gPttIsPressed = true;
gPttOnePushCounter = 1;
ProcessKey(KEY_PTT, true, false);
}
}
else if ((!GPIO_IsPttPressed() || SerialConfigInProgress()) && gPttOnePushCounter == 1)
{
// PTT released or serial comms config in progress
if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms
else if (gPttOnePushCounter == 3 || serialConfigInProgress)
{ // stop transmitting
gPttOnePushCounter = 2;
}
}
else if (GPIO_IsPttPressed() && !SerialConfigInProgress() && gPttOnePushCounter == 2)
{ // PTT pressed again
if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms
{ // stop transmitting
gPttOnePushCounter = 3;
}
}
else if ((!GPIO_IsPttPressed() || SerialConfigInProgress()) && gPttOnePushCounter == 3)
{ // 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;
StopTransmitting();
gPttOnePushCounter = 0;
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv();
#endif
}
else
gPttOnePushCounter++;
}
}
else
@@ -1230,26 +1235,22 @@ static void CheckKeys(void)
//gDebug = gPttOnePushCounter;
}
else
#endif
{
if (gPttIsPressed)
{
if (!GPIO_IsPttPressed() || SerialConfigInProgress())
if (!isPressed)
{ // PTT released or serial comms config in progress
if (++gPttDebounceCounter >= 3 || SerialConfigInProgress()) // 30ms
if (++gPttDebounceCounter >= 3 || serialConfigInProgress) // 30ms
{ // stop transmitting
ProcessKey(KEY_PTT, false, false);
gPttIsPressed = false;
if (gKeyReading1 != KEY_INVALID)
gPttWasReleased = true;
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv();
#endif
gPttDebounceCounter = 0;
StopTransmitting();
}
}
else
gPttDebounceCounter = 0;
}
else if (GPIO_IsPttPressed() && !SerialConfigInProgress())
else if (isPressed)
{ // PTT pressed
if (++gPttDebounceCounter >= 3) // 30ms
{ // start transmitting
@@ -1262,35 +1263,6 @@ static void CheckKeys(void)
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;
#endif
// --------------------- OTHER KEYS ----------------------------
+1 -13
View File
@@ -401,18 +401,6 @@ static void OnKeyDown(uint8_t key)
}
}
// Key
static KEY_Code_t GetKey()
{
KEY_Code_t btn = KEYBOARD_Poll();
if (btn == KEY_INVALID && GPIO_IsPttPressed())
{
btn = KEY_PTT;
}
return btn;
}
// HandleUserInput
static bool HandleUserInput()
{
@@ -423,7 +411,7 @@ static bool HandleUserInput()
#endif
kbd.prev = kbd.current;
kbd.current = GetKey();
kbd.current = KEYBOARD_GetKey();
if (kbd.current == KEY_INVALID)
return true;
+9
View File
@@ -37,6 +37,15 @@ uint8_t initialCROSS_BAND_RX_TX;
static void NextFreqChannel(void);
static void NextMemChannel(void);
#if defined(ENABLE_FEAT_F4HWN_RESUME_STATE) || defined(ENABLE_SCAN_RANGES)
void CHFRSCANNER_ScanRange(void) {
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
if(gScanRangeStart > gScanRangeStop)
SWAP(gScanRangeStart, gScanRangeStop);
}
#endif
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction)
{
if (storeBackupSettings) {
+4
View File
@@ -20,6 +20,10 @@ void CHFRSCANNER_Stop(void);
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction);
void CHFRSCANNER_ContinueScanning(void);
#if defined(ENABLE_FEAT_F4HWN_RESUME_STATE) || defined(ENABLE_SCAN_RANGES)
void CHFRSCANNER_ScanRange(void);
#endif
#ifdef ENABLE_FEAT_F4HWN
extern uint32_t lastFoundFrqOrChan;
extern uint32_t lastFoundFrqOrChanOld;
+17 -11
View File
@@ -51,20 +51,26 @@ static inline void Flashlight_Toggle(){ GPIO_TogglePin(GPIO_PIN_FLASHLIGHT); }
void ACTION_FlashLight(void)
{
switch (gFlashLightState) {
case FLASHLIGHT_OFF:
gFlashLightState++;
// switch (gFlashLightState) {
// case FLASHLIGHT_OFF:
// Flashlight_TurnOn();
// break;
// case FLASHLIGHT_ON:
// case FLASHLIGHT_BLINK:
// break;
// case FLASHLIGHT_SOS:
// default:
// Flashlight_TurnOff();
// }
if(gFlashLightState == FLASHLIGHT_OFF) {
Flashlight_TurnOn();
break;
case FLASHLIGHT_ON:
case FLASHLIGHT_BLINK:
gFlashLightState++;
break;
case FLASHLIGHT_SOS:
default:
gFlashLightState = 0;
}
else if (gFlashLightState == FLASHLIGHT_SOS) {
Flashlight_TurnOff();
}
gFlashLightState = (gFlashLightState + 1) % 4;
}
#else
void ACTION_FlashLight(void)
+14 -8
View File
@@ -129,6 +129,18 @@ void FM_EraseChannels(void)
memset(gFM_Channels, 0xFF, sizeof(gFM_Channels));
}
uint16_t FM_WrapFrequency(uint16_t Frequency) {
const uint16_t freqLoLimit = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
const uint16_t freqHiLimit = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
if (Frequency < freqLoLimit)
return freqHiLimit;
else if (Frequency > freqHiLimit)
return freqLoLimit;
return Frequency;
}
void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag)
{
AUDIO_AudioPathOff();
@@ -145,10 +157,7 @@ void FM_Tune(uint16_t Frequency, int8_t Step, bool bFlag)
if (!bFlag) {
Frequency += Step;
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band))
Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band))
Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
Frequency = FM_WrapFrequency(Frequency);
gEeprom.FM_FrequencyPlaying = Frequency;
}
@@ -513,10 +522,7 @@ static void Key_UP_DOWN(uint8_t state, int8_t Step)
else {
uint16_t Frequency = gEeprom.FM_SelectedFrequency + Step;
if (Frequency < BK1080_GetFreqLoLimit(gEeprom.FM_Band))
Frequency = BK1080_GetFreqHiLimit(gEeprom.FM_Band);
else if (Frequency > BK1080_GetFreqHiLimit(gEeprom.FM_Band))
Frequency = BK1080_GetFreqLoLimit(gEeprom.FM_Band);
Frequency = FM_WrapFrequency(Frequency);
gEeprom.FM_FrequencyPlaying = Frequency;
gEeprom.FM_SelectedFrequency = gEeprom.FM_FrequencyPlaying;
+1 -4
View File
@@ -61,10 +61,7 @@ static void toggle_chan_scanlist(void)
if(!IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
#ifdef ENABLE_SCAN_RANGES
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
if(gScanRangeStart > gScanRangeStop)
SWAP(gScanRangeStart, gScanRangeStop);
CHFRSCANNER_ScanRange();
#endif
return;
}
+1 -11
View File
@@ -270,16 +270,6 @@ static void GUI_DisplaySmallest(const char *pString, uint8_t x, uint8_t y,
// Utility functions
static KEY_Code_t GetKey()
{
KEY_Code_t btn = KEYBOARD_Poll();
if (btn == KEY_INVALID && GPIO_IsPttPressed())
{
btn = KEY_PTT;
}
return btn;
}
static int clamp(int v, int min, int max)
{
return v <= min ? min : (v >= max ? max : v);
@@ -1517,7 +1507,7 @@ static void Render()
static bool HandleUserInput()
{
kbd.prev = kbd.current;
kbd.current = GetKey();
kbd.current = KEYBOARD_GetKey();
if (kbd.current != KEY_INVALID && kbd.current == kbd.prev)
{
+11 -1
View File
@@ -46,7 +46,7 @@ static uint8_t gSerialKeyLong = 0; // 0 = short press, 1 = long press
// Inject a short or long press from serial (UART or VCP).
// KEY_PTT is explicitly blocked — PTT release cannot be guaranteed over serial.
void KEYBOARD_InjectKey(uint8_t keyCode, bool keyLong)
static inline void KEYBOARD_InjectKey(uint8_t keyCode, bool keyLong)
{
if (keyCode < KEY_INVALID && keyCode != KEY_PTT) {
gKeyFromSerial = (KEY_Code_t)keyCode;
@@ -251,3 +251,13 @@ KEY_Code_t KEYBOARD_Poll(void)
return Key;
}
KEY_Code_t KEYBOARD_GetKey(void)
{
KEY_Code_t btn = KEYBOARD_Poll();
if (btn == KEY_INVALID && GPIO_IsPttPressed())
{
btn = KEY_PTT;
}
return btn;
}
+1 -2
View File
@@ -65,11 +65,10 @@ extern bool gWasFKeyPressed;
// Serial-injected key (written by UART/VCP parser, consumed by KEYBOARD_Poll).
extern volatile KEY_Code_t gKeyFromSerial;
// Inject a short or long press received from serial (UART or VCP).
void KEYBOARD_InjectKey(uint8_t keyCode, bool keyLong);
bool KEYBOARD_ProcessProtocolByte(ParseState_t *state, uint8_t b);
#endif
KEY_Code_t KEYBOARD_Poll(void);
KEY_Code_t KEYBOARD_GetKey(void);
#endif
+2 -41
View File
@@ -277,17 +277,10 @@ void Main(void)
#endif
}
/*
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
if (gEeprom.CURRENT_STATE == 2 || gEeprom.CURRENT_STATE == 5)
{
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
if(gScanRangeStart > gScanRangeStop)
{
SWAP(gScanRangeStart, gScanRangeStop);
}
}
CHFRSCANNER_ScanRange();
switch (gEeprom.CURRENT_STATE) {
case 1:
gEeprom.SCAN_LIST_DEFAULT = gEeprom.CURRENT_LIST;
@@ -307,8 +300,6 @@ void Main(void)
#ifdef ENABLE_SPECTRUM
case 4:
APP_RunSpectrum();
break;
case 5:
APP_RunSpectrum();
break;
@@ -319,36 +310,6 @@ void Main(void)
break;
}
#endif
*/
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
if (gEeprom.CURRENT_STATE == 2 || gEeprom.CURRENT_STATE == 5) {
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
if (gScanRangeStart > gScanRangeStop) {
SWAP(gScanRangeStart, gScanRangeStop);
}
}
if (gEeprom.CURRENT_STATE == 1) {
gEeprom.SCAN_LIST_DEFAULT = gEeprom.CURRENT_LIST;
}
if (gEeprom.CURRENT_STATE == 1 || gEeprom.CURRENT_STATE == 2) {
CHFRSCANNER_Start(true, SCAN_FWD);
}
#ifdef ENABLE_FMRADIO
else if (gEeprom.CURRENT_STATE == 3) {
ACTION_FM();
GUI_SelectNextDisplay(gRequestDisplayScreen);
}
#endif
#ifdef ENABLE_SPECTRUM
else if (gEeprom.CURRENT_STATE == 4 || gEeprom.CURRENT_STATE == 5) {
APP_RunSpectrum();
}
#endif
#endif
while (true) {
APP_Update();
+14 -22
View File
@@ -52,6 +52,18 @@ static void SCREENSHOT_Send(const uint8_t *buf, uint16_t len)
}
}
void SCREENSHOT_Line(uint8_t *src, uint8_t *dest, uint16_t *idx, bool inv) {
for (uint8_t b = 0; b < 8; b++) {
for (uint8_t i = 0; i < 128; i += 8) {
uint8_t acc = 0;
for (uint8_t k = 0; k < 8; k++) {
if (src[i + k] & (1 << b)) acc |= (1 << k);
}
dest[(*idx)++] = inv ? ~acc : acc;
}
}
}
void SCREENSHOT_Update(bool force)
{
// Build frame in a temporary stack buffer
@@ -83,31 +95,11 @@ void SCREENSHOT_Update(bool force)
// ==== BUILD FRAME ONCE ====
// Status line: 8 bit layers × 128 columns
for (uint8_t b = 0; b < 8; b++) {
for (uint8_t i = 0; i < 128; i++) {
uint8_t bit = (gStatusLine[i] >> b) & 0x01;
acc |= (bit << bitCount++);
if (bitCount == 8) {
frameBuffer[index++] = gSetting_set_inv ? ~acc : acc;
acc = 0;
bitCount = 0;
}
}
}
SCREENSHOT_Line(gStatusLine, frameBuffer, &index, gSetting_set_inv);
// Frame buffer: 7 lines × 8 bit layers × 128 columns
for (uint8_t l = 0; l < 7; l++) {
for (uint8_t b = 0; b < 8; b++) {
for (uint8_t i = 0; i < 128; i++) {
uint8_t bit = (gFrameBuffer[l][i] >> b) & 0x01;
acc |= (bit << bitCount++);
if (bitCount == 8) {
frameBuffer[index++] = gSetting_set_inv ? ~acc : acc;
acc = 0;
bitCount = 0;
}
}
}
SCREENSHOT_Line(gFrameBuffer[l], frameBuffer, &index, gSetting_set_inv);
}
if (bitCount > 0)
+14 -10
View File
@@ -617,16 +617,20 @@ void SETTINGS_FetchChannelName(char *s, const uint16_t channel)
void SETTINGS_FactoryReset(bool bIsAll)
{
PY25Q16_SectorErase(0x000000);
PY25Q16_SectorErase(0x001000);
PY25Q16_SectorErase(0x002000);
PY25Q16_SectorErase(0x003000);
PY25Q16_SectorErase(0x004000);
PY25Q16_SectorErase(0x005000);
PY25Q16_SectorErase(0x006000);
PY25Q16_SectorErase(0x007000);
PY25Q16_SectorErase(0x008000);
PY25Q16_SectorErase(0x009000);
// PY25Q16_SectorErase(0x000000);
// PY25Q16_SectorErase(0x001000);
// PY25Q16_SectorErase(0x002000);
// PY25Q16_SectorErase(0x003000);
// PY25Q16_SectorErase(0x004000);
// PY25Q16_SectorErase(0x005000);
// PY25Q16_SectorErase(0x006000);
// PY25Q16_SectorErase(0x007000);
// PY25Q16_SectorErase(0x008000);
// PY25Q16_SectorErase(0x009000);
for (uint32_t addr = 0x000000; addr <= 0x009000; addr += 0x1000) {
PY25Q16_SectorErase(addr);
}
// 0d60 - 0e30
if (bIsAll)
+17 -10
View File
@@ -334,16 +334,23 @@ void DisplayRSSIBar(const bool now)
uint8_t overS9dBm = 0;
uint8_t overS9Bars = 0;
if (rssi_dBm >= -93) s_level = 9; // S9 = -93 dBm
else if (rssi_dBm >= -99) s_level = 8; // S8 = -99 dBm
else if (rssi_dBm >= -105) s_level = 7; // S7 = -105 dBm
else if (rssi_dBm >= -111) s_level = 6; // S6 = -111 dBm
else if (rssi_dBm >= -117) s_level = 5; // S5 = -117 dBm
else if (rssi_dBm >= -123) s_level = 4; // S4 = -123 dBm
else if (rssi_dBm >= -129) s_level = 3; // S3 = -129 dBm
else if (rssi_dBm >= -135) s_level = 2; // S2 = -135 dBm
else if (rssi_dBm >= -141) s_level = 1; // S1 = -141 dBm
else s_level = 0; // S0 (below -141 dBm)
// if (rssi_dBm >= -93) s_level = 9; // S9 = -93 dBm
// else if (rssi_dBm >= -99) s_level = 8; // S8 = -99 dBm
// else if (rssi_dBm >= -105) s_level = 7; // S7 = -105 dBm
// else if (rssi_dBm >= -111) s_level = 6; // S6 = -111 dBm
// else if (rssi_dBm >= -117) s_level = 5; // S5 = -117 dBm
// else if (rssi_dBm >= -123) s_level = 4; // S4 = -123 dBm
// else if (rssi_dBm >= -129) s_level = 3; // S3 = -129 dBm
// else if (rssi_dBm >= -135) s_level = 2; // S2 = -135 dBm
// else if (rssi_dBm >= -141) s_level = 1; // S1 = -141 dBm
// else s_level = 0; // S0 (below -141 dBm)
s_level = (rssi_dBm + 147) / 6;
if (s_level > 9)
s_level = 9;
else if (s_level < 0)
s_level = 0;
if (s_level == 9) {
// Compute over-S9 dB directly