summaryrefslogtreecommitdiffstats
path: root/firmware/drivers/tuner/si4700.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/tuner/si4700.c')
-rw-r--r--firmware/drivers/tuner/si4700.c84
1 files changed, 56 insertions, 28 deletions
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c
index 88ff6c69f7..8b4d0a1b19 100644
--- a/firmware/drivers/tuner/si4700.c
+++ b/firmware/drivers/tuner/si4700.c
@@ -553,32 +553,6 @@ void si4700_dbg_info(struct si4700_dbg_info *nfo)
}
#ifdef HAVE_RDS_CAP
-
-#if (CONFIG_RDS & RDS_CFG_ISR)
-static unsigned char isr_regbuf[(RDSD - STATUSRSSI + 1) * 2];
-
-/* Called by RDS interrupt on target */
-void si4700_rds_interrupt(void)
-{
- si4700_rds_read_raw_async(isr_regbuf, sizeof (isr_regbuf));
-}
-
-/* Handle RDS event from ISR */
-void si4700_rds_process(void)
-{
- uint16_t rds_data[4];
- int index = (RDSA - STATUSRSSI) * 2;
-
- for (int i = 0; i < 4; i++) {
- rds_data[i] = isr_regbuf[index] << 8 | isr_regbuf[index + 1];
- index += 2;
- }
-
- rds_process(rds_data);
-}
-
-#else /* !(CONFIG_RDS & RDS_CFG_ISR) */
-
/* Handle RDS event from thread */
void si4700_rds_process(void)
{
@@ -586,13 +560,67 @@ void si4700_rds_process(void)
if (tuner_powered())
{
- si4700_read_reg(RDSD);
+ si4700_read(6);
+#if (CONFIG_RDS & RDS_CFG_POLL)
+ /* we need to keep track of the ready bit because it stays set for 80ms
+ * and we must avoid processing it twice */
+
+ static bool old_rdsr = false;
+ bool rdsr = (cache[STATUSRSSI] & STATUSRSSI_RDSR);
+ if (rdsr && !old_rdsr)
+ rds_process(&cache[RDSA]);
+ old_rdsr = rdsr;
+#else
rds_process(&cache[RDSA]);
+#endif /* !(CONFIG_RDS & RDS_CFG_POLL) */
}
mutex_unlock(&fmr_mutex);
}
-#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
+
+#if (CONFIG_RDS & RDS_CFG_POLL)
+static struct event_queue rds_queue;
+static uint32_t rds_stack[DEFAULT_STACK_SIZE / sizeof(uint32_t)];
+
+enum {
+ Q_POWERUP,
+};
+
+static void NORETURN_ATTR rds_thread(void)
+{
+ /* start up frozen */
+ int timeout = TIMEOUT_BLOCK;
+ struct queue_event ev;
+
+ while (true) {
+ queue_wait_w_tmo(&rds_queue, &ev, timeout);
+ switch (ev.id) {
+ case Q_POWERUP:
+ /* power up: timeout after 1 tick, else block indefinitely */
+ timeout = ev.data ? CONFIG_RDS_POLL_TICKS : TIMEOUT_BLOCK;
+ break;
+ case SYS_TIMEOUT:
+ /* Captures RDS data and processes it */
+ si4700_rds_process();
+ break;
+ }
+ }
+}
+
+/* true after full radio power up, and false before powering down */
+void si4700_rds_powerup(bool on)
+{
+ queue_post(&rds_queue, Q_POWERUP, on);
+}
+
+/* One-time RDS init at startup */
+void si4700_rds_init(void)
+{
+ queue_init(&rds_queue, false);
+ create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
+ IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
+}
+#endif /* !(CONFIG_RDS & RDS_CFG_POLL) */
#endif /* HAVE_RDS_CAP */