summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c63
1 files changed, 41 insertions, 22 deletions
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 e0457e367a..a7b9bc21da 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
@@ -128,15 +128,52 @@ bool si4700_st(void)
128 128
129 129
130/* Low-level RDS Support */ 130/* Low-level RDS Support */
131static struct semaphore rds_sema;
132static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
133 131
134/* RDS GPIO interrupt handler */ 132/* Transfer descriptor for RDS async operations */
133struct si4700_i2c_transfer_desc
134{
135 struct i2c_transfer_desc xfer;
136 unsigned char regbuf[32];
137} si4700_xfer =
138{
139 .xfer = { .node = &si4700_i2c_node }
140};
141
142static void si4700_rds_read_raw_callback(struct i2c_transfer_desc *xfer)
143{
144 struct si4700_i2c_transfer_desc *xf =
145 (struct si4700_i2c_transfer_desc *)xfer;
146
147 if (xfer->rxcount != 0)
148 return; /* Read didn't finish */
149
150 uint16_t rds_data[4];
151
152 si4700_rds_read_raw_async_complete(xf->regbuf, rds_data);
153
154 if (rds_process(rds_data))
155 si4700_rds_set_event();
156}
157
158/* Callback from si4700_rds_read_raw to execute the read */
159void si4700_read_raw_async(int count)
160{
161 si4700_xfer.xfer.txdata = NULL;
162 si4700_xfer.xfer.txcount = 0;
163 si4700_xfer.xfer.rxdata = si4700_xfer.regbuf;
164 si4700_xfer.xfer.rxcount = count;
165 si4700_xfer.xfer.callback = si4700_rds_read_raw_callback;
166 si4700_xfer.xfer.next = NULL;
167
168 i2c_transfer(&si4700_xfer.xfer);
169}
170
171/* RDS GPIO interrupt handler - start RDS data read */
135void si4700_stc_rds_event(void) 172void si4700_stc_rds_event(void)
136{ 173{
137 /* read and clear the interrupt */ 174 /* read and clear the interrupt */
138 SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE); 175 SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE);
139 semaphore_release(&rds_sema); 176 si4700_rds_read_raw_async();
140} 177}
141 178
142/* Called with on=true after full radio power up, and with on=false before 179/* Called with on=true after full radio power up, and with on=false before
@@ -152,26 +189,8 @@ void si4700_rds_powerup(bool on)
152 } 189 }
153} 190}
154 191
155/* Captures RDS data and processes it */
156/* Use of a thread here is likely temporary */
157static void NORETURN_ATTR rds_thread(void)
158{
159 uint16_t rds_data[4];
160
161 while (1)
162 {
163 semaphore_wait(&rds_sema, TIMEOUT_BLOCK);
164
165 if (si4700_rds_read_raw(rds_data) && rds_process(rds_data))
166 si4700_rds_set_event();
167 }
168}
169
170/* One-time RDS init at startup */ 192/* One-time RDS init at startup */
171void si4700_rds_init(void) 193void si4700_rds_init(void)
172{ 194{
173 semaphore_init(&rds_sema, 1, 0);
174 rds_init(); 195 rds_init();
175 create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
176 IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
177} 196}