Signal strength meter for FM radio - FS#8151 by Przemysław Hołubowski


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28559 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c
index 665e73a..efe67a1 100644
--- a/apps/gui/skin_engine/skin_tokens.c
+++ b/apps/gui/skin_engine/skin_tokens.c
@@ -475,6 +475,17 @@
         case SKIN_TOKEN_TUNER_CURFREQ:
             return format_freq_MHz(radio_current_frequency(),
                             region_data->freq_step, buf, buf_size);
+#ifdef HAVE_RADIO_RSSI
+        case SKIN_TOKEN_TUNER_RSSI:
+            snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI));
+            return buf;
+        case SKIN_TOKEN_TUNER_RSSI_MIN:
+            snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI_MIN));
+            return buf;
+        case SKIN_TOKEN_TUNER_RSSI_MAX:
+            snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI_MAX));
+            return buf;
+#endif
         case SKIN_TOKEN_PRESET_NAME:
         case SKIN_TOKEN_PRESET_FREQ:
         case SKIN_TOKEN_PRESET_ID:
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 9034130..0817134 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12647,3 +12647,20 @@
     *: "Start File Browser at root"
   </voice>
 </phrase>
+<phrase>
+  id: LANG_FM_RSSI
+  desc: Signal strength of a received FM station
+  user: core
+  <source>
+    *: none
+    radio: "Signal strength:"
+  </source>
+  <dest>
+    *: none
+    radio: "Signal strength:"
+  </dest>
+  <voice>
+    *: none
+    radio: "Signal strength:"
+  </voice>
+</phrase>
diff --git a/apps/lang/polski.lang b/apps/lang/polski.lang
index 8661a2d..bc54d11 100644
--- a/apps/lang/polski.lang
+++ b/apps/lang/polski.lang
@@ -12580,3 +12580,20 @@
     *: "Rozpocznij Przeglądanie Plików Tutaj"
   </voice>
   </phrase>
+<phrase>
+  id: LANG_FM_RSSI
+  desc: Signal strength of a received FM station
+  user: core
+  <source>
+    *: none
+    radio: "Signal strength:"
+  </source>
+  <dest>
+    *: none
+    radio: "Poziom sygnału:"
+  </dest>
+  <voice>
+    *: none
+    radio: "Poziom sygnału:"
+  </voice>
+</phrase>
diff --git a/apps/radio/radio_skin.c b/apps/radio/radio_skin.c
index 3079693..68314d6 100644
--- a/apps/radio/radio_skin.c
+++ b/apps/radio/radio_skin.c
@@ -27,6 +27,7 @@
 #include "skin_engine/skin_engine.h"
 #include "settings.h"
 #include "radio.h"
+#include "tuner.h"
 #include "action.h"
 #include "appevents.h"
 #include "statusbar-skinned.h"
@@ -41,6 +42,9 @@
         "%Sx(Station:) %tf MHz\n"
         "%?St(force fm mono)<%Sx(Force Mono)|%?ts<%Sx(Stereo)|%Sx(Mono)>>\n"
         "%Sx(Mode:) %?tm<%Sx(Scan)|%Sx(Preset)>\n"
+#ifdef HAVE_RADIO_RSSI
+        "%Sx(Signal strength:) %tr dBuV\n"
+#endif
 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
         "%?Rr<%Sx(Time:) %Rh:%Rn:%Rs|%?St(prerecording time)<%pm|%Sx(Prerecord Time) %Rs>>\n"
 #endif
diff --git a/firmware/drivers/tuner/lv24020lp.c b/firmware/drivers/tuner/lv24020lp.c
index 0228888..590ca96 100644
--- a/firmware/drivers/tuner/lv24020lp.c
+++ b/firmware/drivers/tuner/lv24020lp.c
@@ -35,6 +35,10 @@
 
 static struct mutex tuner_mtx;
 
+/* define RSSI range */
+#define RSSI_MIN 5
+#define RSSI_MAX 75
+
 /* define to enable tuner logging */
 #undef SANYO_TUNER_LOG_FILE
 #undef SANYO_TUNER_LOGF
@@ -966,6 +970,8 @@
 int lv24020lp_get(int setting)
 {
     int val = -1;
+    const unsigned char fst[7] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f};
+    unsigned char fst_ndx, fs;
 
     mutex_lock(&tuner_mtx);
 
@@ -994,6 +1000,22 @@
         break;
         }
 
+    case RADIO_RSSI:
+        fs = RSS_FS(lv24020lp_read(RADIO_STAT));
+        for(fst_ndx=0; fst_ndx<7; fst_ndx++)
+            if(fs == fst[fst_ndx])
+                break;
+        val = 75 - 10*fst_ndx;
+        break;
+
+    case RADIO_RSSI_MIN:
+        val = RSSI_MIN;
+        break;
+
+    case RADIO_RSSI_MAX:
+        val = RSSI_MAX;
+        break;
+
     default:
         val = lv24020lp_debug_info(setting);
     }
diff --git a/firmware/drivers/tuner/rda5802.c b/firmware/drivers/tuner/rda5802.c
index 43dffe2..82dc0bb 100644
--- a/firmware/drivers/tuner/rda5802.c
+++ b/firmware/drivers/tuner/rda5802.c
@@ -34,6 +34,10 @@
 
 #define I2C_ADR 0x20
 
+/* define RSSI range */
+#define RSSI_MIN 0
+#define RSSI_MAX 70
+
 /** Registers and bits **/
 #define POWERCFG    0x2
 #define CHANNEL     0x3
@@ -263,6 +267,12 @@
     return (rda5802_read_reg(READCHAN) & READCHAN_ST);
 }
 
+static int rda5802_rssi(void)
+{
+    uint16_t status = rda5802_read_reg(STATUSRSSI);
+    return STATUSRSSI_RSSIr(status);
+}
+
 /* tuner abstraction layer: set something to the tuner */
 int rda5802_set(int setting, int value)
 {
@@ -323,6 +333,18 @@
     case RADIO_STEREO:
         val = rda5802_st();
         break;
+
+    case RADIO_RSSI:
+        val = rda5802_rssi();
+        break;
+
+    case RADIO_RSSI_MIN:
+        val = RSSI_MIN;
+        break;
+
+    case RADIO_RSSI_MAX:
+        val = RSSI_MAX;
+        break;
     }
 
     return val;
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c
index dfc0e46..4747357 100644
--- a/firmware/drivers/tuner/si4700.c
+++ b/firmware/drivers/tuner/si4700.c
@@ -50,6 +50,10 @@
 
 #define I2C_ADR 0x20
 
+/* define RSSI range */
+#define RSSI_MIN 0
+#define RSSI_MAX 70
+
 /** Registers and bits - "x" denotes Si4702/03 only (so they say) **/
 #define DEVICEID    0x0
 #define CHIPID      0x1
@@ -197,7 +201,7 @@
 #define STATUSRSSI_BLERA    (0x3 <<  9) /* x */
 #define STATUSRSSI_ST       (0x1 <<  8)
 #define STATUSRSSI_RSSI     (0xff << 0)
-    #define STATUSRSSI_RSSIr(x) ((x) & 0xff)
+#define STATUSRSSI_RSSIr(x) ((x) & 0xff)
 
 /* READCHAN (0xB) */
 #define READCHAN_BLERB      (0x3 << 14) /* x */
@@ -481,6 +485,18 @@
         case RADIO_STEREO:
             val = si4700_st();
             break;
+    
+        case RADIO_RSSI:
+            val = STATUSRSSI_RSSIr(si4700_read_reg(STATUSRSSI));
+            break;
+
+        case RADIO_RSSI_MIN:
+            val = RSSI_MIN;
+            break;
+
+        case RADIO_RSSI_MAX:
+            val = RSSI_MAX;
+            break;
     }
 
     return val;
diff --git a/firmware/drivers/tuner/tea5760uk.c b/firmware/drivers/tuner/tea5760uk.c
index 20234e2..c1dff59 100644
--- a/firmware/drivers/tuner/tea5760uk.c
+++ b/firmware/drivers/tuner/tea5760uk.c
@@ -30,6 +30,10 @@
 
 #define I2C_ADR 0x22
 
+/* define RSSI range */
+#define RSSI_MIN 4
+#define RSSI_MAX 46
+
 static bool tuner_present = false;
 static unsigned char write_bytes[7] = {
     0x00,   /* INTREG LSB */
@@ -138,6 +142,19 @@
         case RADIO_STEREO:
             val = read_bytes[9] >> 2;
             break;
+            
+        case RADIO_RSSI:
+            val = (read_bytes[9] >> 4) & 0x0F;
+            val = 4 + (28 * val + 5) / 10;
+            break;
+
+        case RADIO_RSSI_MIN:
+            val = RSSI_MIN;
+            break;
+
+        case RADIO_RSSI_MAX:
+            val = RSSI_MAX;
+            break;
     }
 
     return val;
diff --git a/firmware/drivers/tuner/tea5767.c b/firmware/drivers/tuner/tea5767.c
index 67aa808..3f3af68 100644
--- a/firmware/drivers/tuner/tea5767.c
+++ b/firmware/drivers/tuner/tea5767.c
@@ -34,6 +34,10 @@
 #define I2C_ADR 0xC0
 #endif
 
+/* define RSSI range */
+#define RSSI_MIN 10
+#define RSSI_MAX 55
+
 static bool tuner_present = true;
 static unsigned char write_bytes[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
 
@@ -132,6 +136,18 @@
         case RADIO_STEREO:
             val = read_bytes[2] >> 7;
             break;
+        
+        case RADIO_RSSI:
+            val = 10 + 3*(read_bytes[3] >> 4);
+            break;
+
+        case RADIO_RSSI_MIN:
+            val = RSSI_MIN;
+            break;
+
+        case RADIO_RSSI_MAX:
+            val = RSSI_MAX;
+            break;
     }
 
     return val;
diff --git a/firmware/export/lv24020lp.h b/firmware/export/lv24020lp.h
index 753949f..f2e123b 100644
--- a/firmware/export/lv24020lp.h
+++ b/firmware/export/lv24020lp.h
@@ -25,6 +25,7 @@
 
 /* Define additional tuner messages here */
 #define HAVE_RADIO_REGION
+#define HAVE_RADIO_RSSI
 
 #define LV24020LP_CTRL_STAT (RADIO_GET_CHIP_FIRST+0)
 #define LV24020LP_REG_STAT  (RADIO_GET_CHIP_FIRST+1)
diff --git a/firmware/export/rda5802.h b/firmware/export/rda5802.h
index 8770796..0dae3ab 100644
--- a/firmware/export/rda5802.h
+++ b/firmware/export/rda5802.h
@@ -26,6 +26,7 @@
 #define _RDA5802_H_
 
 #define HAVE_RADIO_REGION
+#define HAVE_RADIO_RSSI
 
 struct rda5802_dbg_info
 {
diff --git a/firmware/export/si4700.h b/firmware/export/si4700.h
index c4aff6f..debc176 100644
--- a/firmware/export/si4700.h
+++ b/firmware/export/si4700.h
@@ -26,6 +26,7 @@
 #define _SI4700_H_
 
 #define HAVE_RADIO_REGION
+#define HAVE_RADIO_RSSI
 
 struct si4700_dbg_info
 {
diff --git a/firmware/export/tea5760.h b/firmware/export/tea5760.h
index ea857de..a5af67a 100644
--- a/firmware/export/tea5760.h
+++ b/firmware/export/tea5760.h
@@ -27,6 +27,7 @@
 #include "tuner.h"
 
 #define HAVE_RADIO_REGION
+#define HAVE_RADIO_RSSI
 
 struct tea5760_dbg_info
 {
diff --git a/firmware/export/tea5767.h b/firmware/export/tea5767.h
index 64dd266..6def185 100644
--- a/firmware/export/tea5767.h
+++ b/firmware/export/tea5767.h
@@ -25,6 +25,7 @@
 
 #define HAVE_RADIO_REGION
 #define HAVE_RADIO_MUTE_TIMEOUT
+#define HAVE_RADIO_RSSI
 
 struct tea5767_dbg_info
 {
diff --git a/firmware/export/tuner.h b/firmware/export/tuner.h
index 9263c08..c8bea86 100644
--- a/firmware/export/tuner.h
+++ b/firmware/export/tuner.h
@@ -46,6 +46,9 @@
     RADIO_STEREO,
     /* RADIO_EVENT is an event that requests a screen update */
     RADIO_EVENT,
+    RADIO_RSSI,
+    RADIO_RSSI_MIN,
+    RADIO_RSSI_MAX,
 
     /* Put new general-purpose readback values above this line */
     __RADIO_GET_STANDARD_LAST
diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c
index 9a68834..b579ee2 100644
--- a/lib/skin_parser/tag_table.c
+++ b/lib/skin_parser/tag_table.c
@@ -153,6 +153,9 @@
     { SKIN_TOKEN_TUNER_MINFREQ,         "ta", "", SKIN_REFRESH_STATIC },
     { SKIN_TOKEN_TUNER_MAXFREQ,         "tb", "", SKIN_REFRESH_STATIC },
     { SKIN_TOKEN_TUNER_CURFREQ,         "tf", "", SKIN_REFRESH_DYNAMIC },
+    { SKIN_TOKEN_TUNER_RSSI,            "tr", "", SKIN_REFRESH_DYNAMIC },
+    { SKIN_TOKEN_TUNER_RSSI_MIN,        "tl", "", SKIN_REFRESH_STATIC },
+    { SKIN_TOKEN_TUNER_RSSI_MAX,        "th", "", SKIN_REFRESH_STATIC },
     { SKIN_TOKEN_PRESET_ID,             "Ti", "", SKIN_REFRESH_STATIC },
     { SKIN_TOKEN_PRESET_NAME,           "Tn", "", SKIN_REFRESH_STATIC },
     { SKIN_TOKEN_PRESET_FREQ,           "Tf", "", SKIN_REFRESH_STATIC },
diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h
index a7ac164..ad72dab 100644
--- a/lib/skin_parser/tag_table.h
+++ b/lib/skin_parser/tag_table.h
@@ -249,6 +249,9 @@
     SKIN_TOKEN_TUNER_MINFREQ, /* changes based on "region" */
     SKIN_TOKEN_TUNER_MAXFREQ, /* changes based on "region" */
     SKIN_TOKEN_TUNER_CURFREQ,
+    SKIN_TOKEN_TUNER_RSSI,
+    SKIN_TOKEN_TUNER_RSSI_MIN,
+    SKIN_TOKEN_TUNER_RSSI_MAX,
     SKIN_TOKEN_PRESET_ID, /* "id" of this preset.. really the array element number */
     SKIN_TOKEN_PRESET_NAME,
     SKIN_TOKEN_PRESET_FREQ,