diff --git a/openrtx/include/core/utils.h b/openrtx/include/core/utils.h
index de6f4965..6c438dc4 100644
--- a/openrtx/include/core/utils.h
+++ b/openrtx/include/core/utils.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, *
+ * Copyright (C) 2020 - 2025 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Silvano Seva IU2KWO *
* *
@@ -17,8 +17,8 @@
* along with this program; if not, see *
***************************************************************************/
-#ifndef CALIB_UTILS_H
-#define CALIB_UTILS_H
+#ifndef UTILS_H
+#define UTILS_H
#include
#include
@@ -49,8 +49,10 @@ uint8_t interpCalParameter(const freq_t freq, const freq_t *calPoints,
const uint8_t *param, const uint8_t elems);
/**
- * \internal Utility function to convert 4 byte BCD values into a 32-bit
- * unsigned integer ones.
+ * Convert a 4 byte BCD number to a 32-bit unsigned integer one.
+ *
+ * @param bcd: BCD number
+ * @return unsigned integer representation of the BCD input.
*/
uint32_t bcdToBin(uint32_t bcd);
@@ -64,6 +66,14 @@ uint32_t bcdToBin(uint32_t bcd);
*/
void stripTrailingZeroes(char *str);
+/**
+ * Get the S-level corresponding to a given RSSI value in dBm.
+ *
+ * @param rssi: RSSI in dBm
+ * @return S level, from S0 to S11
+ */
+uint8_t rssiToSlevel(const rssi_t rssi);
+
#ifdef __cplusplus
}
#endif
diff --git a/openrtx/src/core/graphics.c b/openrtx/src/core/graphics.c
index 1651f9ae..e51dd077 100644
--- a/openrtx/src/core/graphics.c
+++ b/openrtx/src/core/graphics.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
#include
@@ -775,9 +776,7 @@ void gfx_drawSmeter(point_t start, uint16_t width, uint16_t height, rssi_t rssi,
// RSSI bar
uint16_t rssi_height = bar_height * 4 / bar_height_divider;
- int16_t s_level = (127 + rssi) / 6;
- uint16_t rssi_width = (s_level < 0) ? 0 : (s_level * (width - 1) / 11);
- rssi_width = (s_level > 10) ? width : rssi_width;
+ uint16_t rssi_width = (rssiToSlevel(rssi) * (width - 1) / 11);
point_t rssi_pos = { start.x, (uint8_t) (start.y + 2 + squelch_height + volume_height)};
gfx_drawRect(rssi_pos, rssi_width, rssi_height, white, true);
}
@@ -843,11 +842,10 @@ void gfx_drawSmeterLevel(point_t start, uint16_t width, uint16_t height, rssi_t
uint16_t level_width = (width * level) / 255;
point_t level_pos = { start.x, (uint8_t) (start.y + 2 + volume_height)};
gfx_drawRect(level_pos, level_width, level_height, green, true);
+
// RSSI bar
- int16_t s_level = (127 + rssi) / 6;
uint16_t rssi_height = bar_height * 3 / bar_height_divider;
- uint16_t rssi_width = (s_level < 0) ? 0 : (s_level * (width - 1) / 11);
- rssi_width = (s_level > 10) ? width : rssi_width;
+ uint16_t rssi_width = (rssiToSlevel(rssi) * (width - 1) / 11);
point_t rssi_pos = {start.x, (uint8_t) (start.y + 5 + level_height + volume_height)};
gfx_drawRect(rssi_pos, rssi_width, rssi_height, white, true);
// S-level marks and numbers
diff --git a/openrtx/src/core/utils.c b/openrtx/src/core/utils.c
index a3eb14d2..decdf10c 100644
--- a/openrtx/src/core/utils.c
+++ b/openrtx/src/core/utils.c
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, *
+ * Copyright (C) 2020 - 2025 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN, *
* Silvano Seva IU2KWO *
* *
@@ -76,3 +76,21 @@ void stripTrailingZeroes(char *str)
}
}
}
+
+uint8_t rssiToSlevel(const rssi_t rssi)
+{
+ // RSSI >= -53dB is S11 (S9 + 20 dB)
+ if(rssi >= -53)
+ return 11;
+
+ // RSSI lower than -121dB is always S0
+ if(rssi < -121)
+ return 0;
+
+ // For S level > 9 use 10dB steps instead of 6dB
+ if (rssi >= -73)
+ return (uint8_t)((163 + rssi) / 10);
+
+ // For S1 - S9 use 6dB increase per S-Point
+ return (uint8_t)(127 + rssi) / 6;
+}