summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}