diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c | 63 |
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 */ |
131 | static struct semaphore rds_sema; | ||
132 | static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)]; | ||
133 | 131 | ||
134 | /* RDS GPIO interrupt handler */ | 132 | /* Transfer descriptor for RDS async operations */ |
133 | struct 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 | |||
142 | static 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 */ | ||
159 | void 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 */ | ||
135 | void si4700_stc_rds_event(void) | 172 | void 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 */ | ||
157 | static 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 */ |
171 | void si4700_rds_init(void) | 193 | void 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 | } |