summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorWolfram Sang <wsa@the-dreams.de>2021-11-15 20:46:28 +0100
committerSolomon Peachy <pizza@shaftnet.org>2021-11-18 16:44:21 -0500
commitde0346065b415e03efad5746ffdee99d607a0d3c (patch)
tree87397e0435d5e9dcf03af7ef81c80a777e2f6fd1 /firmware
parent701d4ba77e61984a71ddbf552193e5567be4e3af (diff)
downloadrockbox-de0346065b415e03efad5746ffdee99d607a0d3c.tar.gz
rockbox-de0346065b415e03efad5746ffdee99d607a0d3c.zip
Sansa Clip+: add RDS support
Based on a patch by Amaury Pouly which was based on a patch from Ryan Hitchman. I mainly moved the code for polling into the tuner driver so it can be reused by other targets. I added the CONFIG parameter for the polling frequency (in ticks) to save energy. Also, I did some minor cleanups. Change-Id: I95a62e7e1e42c62dbf47ecb27a3b312a42be62aa
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/tuner/si4700.c55
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/export/config/sansaclipplus.h6
-rw-r--r--firmware/export/si4700.h8
-rw-r--r--firmware/target/arm/as3525/fmradio-i2c-as3525.c6
-rw-r--r--firmware/target/arm/as3525/system-as3525.c2
6 files changed, 76 insertions, 2 deletions
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c
index 88ff6c69f7..57006b4e3c 100644
--- a/firmware/drivers/tuner/si4700.c
+++ b/firmware/drivers/tuner/si4700.c
@@ -587,12 +587,67 @@ void si4700_rds_process(void)
if (tuner_powered())
{
si4700_read_reg(RDSD);
+#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 */
diff --git a/firmware/export/config.h b/firmware/export/config.h
index e887796acc..52f647f2fa 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -718,6 +718,7 @@ Lyre prototype 1 */
#define RDS_CFG_ISR 0x1 /* uses ISR to process packets */
#define RDS_CFG_PROCESS 0x2 /* uses raw packet processing */
#define RDS_CFG_PUSH 0x4 /* pushes processed information */
+#define RDS_CFG_POLL 0x8 /* tuner driver provides a polling function */
#ifndef CONFIG_RDS
#define CONFIG_RDS RDS_CFG_PROCESS /* thread processing+raw processing */
#endif /* CONFIG_RDS */
diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h
index 3108bace61..e0df0c28c3 100644
--- a/firmware/export/config/sansaclipplus.h
+++ b/firmware/export/config/sansaclipplus.h
@@ -17,6 +17,9 @@
#ifndef BOOTLOADER
#define HAVE_HOTSWAP
+#define HAVE_RDS_CAP
+#define CONFIG_RDS (RDS_CFG_POLL | RDS_CFG_PROCESS)
+#define CONFIG_RDS_POLL_TICKS 4
#endif
#define HW_SAMPR_CAPS SAMPR_CAP_ALL_96
@@ -146,6 +149,9 @@
/* define this if the flash memory uses the SecureDigital Memory Card protocol */
#define CONFIG_STORAGE STORAGE_SD
+/* Define this if target has an additional number of threads specific to it */
+#define TARGET_EXTRA_THREADS 1 /* RDS thread */
+
#define BATTERY_CAPACITY_DEFAULT 290 /* default battery capacity */
#define BATTERY_CAPACITY_MIN 290 /* min. capacity selectable */
#define BATTERY_CAPACITY_MAX 290 /* max. capacity selectable */
diff --git a/firmware/export/si4700.h b/firmware/export/si4700.h
index bd75bf0817..033b435f2a 100644
--- a/firmware/export/si4700.h
+++ b/firmware/export/si4700.h
@@ -55,7 +55,13 @@ void si4700_rds_read_raw_async(unsigned char *buf, int count); /* implemented by
void si4700_rds_interrupt(void);
#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
-/* Read raw RDS info for processing */
+/* Read raw RDS info for processing.
+ * - If RDS_CFG_ISR is set, the tuner driver will call si4700_rds_read_raw_async() which should
+ * perform an asynchronous read and call this function when the data has been read.
+ * - If RDS_CFG_POLL is set, this function will read status and RDS data and process it if a new
+ * packet is available.
+ * - Otherwise this function will read a RDS packet and process it under the assumption that it is
+ * new. */
void si4700_rds_process(void);
#endif /* HAVE_RDS_CAP */
diff --git a/firmware/target/arm/as3525/fmradio-i2c-as3525.c b/firmware/target/arm/as3525/fmradio-i2c-as3525.c
index 5b629f5ad4..7f6cb8366b 100644
--- a/firmware/target/arm/as3525/fmradio-i2c-as3525.c
+++ b/firmware/target/arm/as3525/fmradio-i2c-as3525.c
@@ -185,6 +185,11 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
}
#ifdef HAVE_RDS_CAP
+/* On the Sansa Clip Zip, the tuner interrupt line is routed to the SoC so we
+ * can use to detect when a RDS packet is ready. On the Clip+, we have to
+ * regularly poll. */
+
+#if !(CONFIG_RDS & RDS_CFG_POLL)
/* Low-level RDS Support */
static struct semaphore rds_sema;
static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
@@ -231,4 +236,5 @@ void si4700_rds_init(void)
create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
}
+#endif /* !(CONFIG_RDS & RDS_CFG_POLL) */
#endif /* HAVE_RDS_CAP */
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index 83ccb55f79..0450c8b410 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -180,7 +180,7 @@ void INT_GPIOA(void)
void button_gpioa_isr(void);
button_gpioa_isr();
#endif
-#ifdef HAVE_RDS_CAP
+#if defined(HAVE_RDS_CAP) && !(CONFIG_RDS & RDS_CFG_POLL)
void tuner_isr(void);
tuner_isr();
#endif