summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfram Sang <wsa@the-dreams.de>2021-12-10 16:13:49 +0100
committerWolfram Sang <wsa@the-dreams.de>2022-02-07 22:01:20 +0100
commit5b8873bf333add9ec7208901c62bbd30ad7ea8c3 (patch)
treef17916b7dcf0fb8059354094858a9f691c703b9f
parent8d453ae9c3beef82bd61401af6216f74a400cbd0 (diff)
downloadrockbox-5b8873bf333add9ec7208901c62bbd30ad7ea8c3.tar.gz
rockbox-5b8873bf333add9ec7208901c62bbd30ad7ea8c3.zip
RFT: convert Gigabeat RDS to thread
This kind of reverts 7b596416bf ("Gigabeat S: Update RDS processing to use asynchronous I2C rather than thread."). However, requiring RDS to run in thread context will a) allow more upcoming features and b) remove quite some complexity from the codebase (see the diffstat here) because Gigabeat is the only user. iMX31 should be able to handle one more thread, as it can even run Linux. Change-Id: I46130034595ba66392c5417c275d036f4bd26943
-rw-r--r--firmware/drivers/rds.c21
-rw-r--r--firmware/drivers/tuner/si4700.c27
-rw-r--r--firmware/export/config.h2
-rw-r--r--firmware/export/config/gigabeats.h3
-rw-r--r--firmware/export/si4700.h8
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c49
6 files changed, 16 insertions, 94 deletions
diff --git a/firmware/drivers/rds.c b/firmware/drivers/rds.c
index 0b9b227563..2d8466ae36 100644
--- a/firmware/drivers/rds.c
+++ b/firmware/drivers/rds.c
@@ -72,15 +72,6 @@ static int rt_data_idx; /* rt_data[0 or 1] */
72#define RT_DATA_INC(x) rt_data[rt_data_idx ^= (x)] 72#define RT_DATA_INC(x) rt_data[rt_data_idx ^= (x)]
73#endif /* (CONFIG_RDS & RDS_CFG_PROCESS) */ 73#endif /* (CONFIG_RDS & RDS_CFG_PROCESS) */
74 74
75#if (CONFIG_RDS & RDS_CFG_ISR)
76/* Functions are called in ISR context */
77#define rds_disable_irq_save() disable_irq_save()
78#define rds_restore_irq(old) restore_irq(old)
79#else /* !(CONFIG_RDS & RDS_CFG_ISR) */
80#define rds_disable_irq_save() 0
81#define rds_restore_irq(old) ((void)(old))
82#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
83
84/* RDS code table G0 to UTF-8 translation */ 75/* RDS code table G0 to UTF-8 translation */
85static const uint16_t rds_tbl_g0[0x100-0x20] = 76static const uint16_t rds_tbl_g0[0x100-0x20] =
86{ 77{
@@ -195,8 +186,6 @@ static void register_activity(void)
195/* resets the rds parser */ 186/* resets the rds parser */
196void rds_reset(void) 187void rds_reset(void)
197{ 188{
198 int oldlevel = rds_disable_irq_save();
199
200 /* reset general info */ 189 /* reset general info */
201 pi_code = 0; 190 pi_code = 0;
202 ct_data = 0; 191 ct_data = 0;
@@ -210,8 +199,6 @@ void rds_reset(void)
210 ps_segment = 0; 199 ps_segment = 0;
211 rt_segment = 0; 200 rt_segment = 0;
212#endif /* (CONFIG_RDS & RDS_CFG_PROCESS) */ 201#endif /* (CONFIG_RDS & RDS_CFG_PROCESS) */
213
214 rds_restore_irq(oldlevel);
215} 202}
216 203
217/* initialises the rds parser */ 204/* initialises the rds parser */
@@ -223,8 +210,6 @@ void rds_init(void)
223/* sync RDS state */ 210/* sync RDS state */
224void rds_sync(void) 211void rds_sync(void)
225{ 212{
226 int oldlevel = rds_disable_irq_save();
227
228 if (rds_active) { 213 if (rds_active) {
229 if (TIMED_OUT(rds_timeout)) { 214 if (TIMED_OUT(rds_timeout)) {
230 rds_reset(); 215 rds_reset();
@@ -238,8 +223,6 @@ void rds_sync(void)
238 } 223 }
239 } 224 }
240 } 225 }
241
242 rds_restore_irq(oldlevel);
243} 226}
244 227
245#if (CONFIG_RDS & RDS_CFG_PROCESS) 228#if (CONFIG_RDS & RDS_CFG_PROCESS)
@@ -458,8 +441,6 @@ void rds_push_info(enum rds_info_id info_id, uintptr_t data, size_t size)
458/* read fully-processed RDS data */ 441/* read fully-processed RDS data */
459size_t rds_pull_info(enum rds_info_id info_id, uintptr_t data, size_t size) 442size_t rds_pull_info(enum rds_info_id info_id, uintptr_t data, size_t size)
460{ 443{
461 int oldlevel = rds_disable_irq_save();
462
463 rds_sync(); 444 rds_sync();
464 445
465 switch (info_id) { 446 switch (info_id) {
@@ -490,7 +471,5 @@ size_t rds_pull_info(enum rds_info_id info_id, uintptr_t data, size_t size)
490 default: 471 default:
491 size = 0; 472 size = 0;
492 } 473 }
493
494 rds_restore_irq(oldlevel);
495 return size; 474 return size;
496} 475}
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c
index cce203fde9..7b54526f61 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)
553} 553}
554 554
555#ifdef HAVE_RDS_CAP 555#ifdef HAVE_RDS_CAP
556
557#if (CONFIG_RDS & RDS_CFG_ISR)
558static unsigned char isr_regbuf[(RDSD - STATUSRSSI + 1) * 2];
559
560/* Called by RDS interrupt on target */
561void si4700_rds_interrupt(void)
562{
563 si4700_rds_read_raw_async(isr_regbuf, sizeof (isr_regbuf));
564}
565
566/* Handle RDS event from ISR */
567void si4700_rds_process(void)
568{
569 uint16_t rds_data[4];
570 int index = (RDSA - STATUSRSSI) * 2;
571
572 for (int i = 0; i < 4; i++) {
573 rds_data[i] = isr_regbuf[index] << 8 | isr_regbuf[index + 1];
574 index += 2;
575 }
576
577 rds_process(rds_data);
578}
579
580#else /* !(CONFIG_RDS & RDS_CFG_ISR) */
581
582/* Handle RDS event from thread */ 556/* Handle RDS event from thread */
583void si4700_rds_process(void) 557void si4700_rds_process(void)
584{ 558{
@@ -603,7 +577,6 @@ void si4700_rds_process(void)
603 577
604 mutex_unlock(&fmr_mutex); 578 mutex_unlock(&fmr_mutex);
605} 579}
606#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
607 580
608#if (CONFIG_RDS & RDS_CFG_POLL) 581#if (CONFIG_RDS & RDS_CFG_POLL)
609static struct event_queue rds_queue; 582static struct event_queue rds_queue;
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 2ae7ef2c53..efd99569b6 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -728,7 +728,7 @@ Lyre prototype 1 */
728 728
729#ifdef HAVE_RDS_CAP 729#ifdef HAVE_RDS_CAP
730/* combinable bitflags */ 730/* combinable bitflags */
731#define RDS_CFG_ISR 0x1 /* uses ISR to process packets */ 731/* 0x01 can be reused, was RDS_CFG_ISR */
732#define RDS_CFG_PROCESS 0x2 /* uses raw packet processing */ 732#define RDS_CFG_PROCESS 0x2 /* uses raw packet processing */
733#define RDS_CFG_PUSH 0x4 /* pushes processed information */ 733#define RDS_CFG_PUSH 0x4 /* pushes processed information */
734#define RDS_CFG_POLL 0x8 /* tuner driver provides a polling function */ 734#define RDS_CFG_POLL 0x8 /* tuner driver provides a polling function */
diff --git a/firmware/export/config/gigabeats.h b/firmware/export/config/gigabeats.h
index 8d82b44065..edf76d0e98 100644
--- a/firmware/export/config/gigabeats.h
+++ b/firmware/export/config/gigabeats.h
@@ -121,7 +121,6 @@
121/* Define this if you have a SI4700 fm radio tuner */ 121/* Define this if you have a SI4700 fm radio tuner */
122#define CONFIG_TUNER SI4700 122#define CONFIG_TUNER SI4700
123#define HAVE_RDS_CAP 123#define HAVE_RDS_CAP
124#define CONFIG_RDS (RDS_CFG_ISR | RDS_CFG_PROCESS)
125 124
126/* define this if you can flip your LCD */ 125/* define this if you can flip your LCD */
127#define HAVE_LCD_FLIP 126#define HAVE_LCD_FLIP
@@ -164,7 +163,7 @@
164#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS) 163#define GPIO_EVENT_MASK (USE_GPIO1_EVENTS)
165 164
166/* Define this if target has an additional number of threads specific to it */ 165/* Define this if target has an additional number of threads specific to it */
167#define TARGET_EXTRA_THREADS 1 166#define TARGET_EXTRA_THREADS 2 /* one is for RDS */
168 167
169/* Type of mobile power - check this out */ 168/* Type of mobile power - check this out */
170#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */ 169#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */
diff --git a/firmware/export/si4700.h b/firmware/export/si4700.h
index 033b435f2a..cf9e0f077b 100644
--- a/firmware/export/si4700.h
+++ b/firmware/export/si4700.h
@@ -49,15 +49,7 @@ void si4700_rds_init(void) INIT_ATTR;
49/* Radio is fully powered up or about to be powered down */ 49/* Radio is fully powered up or about to be powered down */
50void si4700_rds_powerup(bool on); 50void si4700_rds_powerup(bool on);
51 51
52#if (CONFIG_RDS & RDS_CFG_ISR)
53/* Read raw RDS info for processing - asynchronously */
54void si4700_rds_read_raw_async(unsigned char *buf, int count); /* implemented by target */
55void si4700_rds_interrupt(void);
56#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
57
58/* Read raw RDS info for processing. 52/* Read raw RDS info for processing.
59 * - If RDS_CFG_ISR is set, the tuner driver will call si4700_rds_read_raw_async() which should
60 * perform an asynchronous read and call this function when the data has been read.
61 * - If RDS_CFG_POLL is set, this function will read status and RDS data and process it if a new 53 * - If RDS_CFG_POLL is set, this function will read status and RDS data and process it if a new
62 * packet is available. 54 * packet is available.
63 * - Otherwise this function will read a RDS packet and process it under the assumption that it is 55 * - Otherwise this function will read a RDS packet and process it under the assumption that it is
diff --git a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
index 5b0c71110d..c84f1cf41c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
@@ -125,53 +125,30 @@ bool si4700_st(void)
125 return (GPIO1_DR & (1 << 28)) >> 28; 125 return (GPIO1_DR & (1 << 28)) >> 28;
126} 126}
127 127
128
129/* Low-level RDS Support */ 128/* Low-level RDS Support */
130static bool int_restore; 129static struct semaphore rds_sema;
131 130static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
132/* Called after I2C read cycle completes */
133static void si4700_rds_read_raw_async_callback(struct i2c_transfer_desc *xfer)
134{
135 if (xfer->rxcount == 0)
136 si4700_rds_process();
137 /* else read didn't finish */
138
139 if (int_restore)
140 gpio_int_enable(SI4700_EVENT_ID);
141}
142
143/* Called to read registers from ISR context */
144void si4700_rds_read_raw_async(unsigned char *buf, int count)
145{
146 /* transfer descriptor for RDS async operations */
147 static struct i2c_transfer_desc xfer = { .node = &si4700_i2c_node };
148
149 xfer.txdata = NULL;
150 xfer.txcount = 0;
151 xfer.rxdata = buf;
152 xfer.rxcount = count;
153 xfer.callback = si4700_rds_read_raw_async_callback;
154 xfer.next = NULL;
155
156 i2c_transfer(&xfer);
157}
158 131
159/* RDS GPIO interrupt handler - start RDS data read */ 132/* RDS GPIO interrupt handler - start RDS data read */
160void INT_SI4700_RDS(void) 133void INT_SI4700_RDS(void)
161{ 134{
162 /* mask and clear the interrupt until we're done */
163 gpio_int_disable(SI4700_EVENT_ID);
164 gpio_int_clear(SI4700_EVENT_ID); 135 gpio_int_clear(SI4700_EVENT_ID);
136 semaphore_release(&rds_sema);
137}
165 138
166 /* tell radio driver about it */ 139/* Captures RDS data and processes it */
167 si4700_rds_interrupt(); 140static void NORETURN_ATTR rds_thread(void)
141{
142 while (true) {
143 semaphore_wait(&rds_sema, TIMEOUT_BLOCK);
144 si4700_rds_process();
145 }
168} 146}
169 147
170/* Called with on=true after full radio power up, and with on=false before 148/* Called with on=true after full radio power up, and with on=false before
171 powering down */ 149 powering down */
172void si4700_rds_powerup(bool on) 150void si4700_rds_powerup(bool on)
173{ 151{
174 int_restore = on;
175 gpio_int_disable(SI4700_EVENT_ID); 152 gpio_int_disable(SI4700_EVENT_ID);
176 gpio_int_clear(SI4700_EVENT_ID); 153 gpio_int_clear(SI4700_EVENT_ID);
177 gpio_enable_event(SI4700_EVENT_ID, on); 154 gpio_enable_event(SI4700_EVENT_ID, on);
@@ -180,5 +157,7 @@ void si4700_rds_powerup(bool on)
180/* One-time RDS init at startup */ 157/* One-time RDS init at startup */
181void si4700_rds_init(void) 158void si4700_rds_init(void)
182{ 159{
183 /* nothing to do */ 160 semaphore_init(&rds_sema, 1, 0);
161 create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
162 IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
184} 163}