diff options
Diffstat (limited to 'firmware/target')
5 files changed, 135 insertions, 3 deletions
diff --git a/firmware/target/arm/as3525/fmradio-i2c-as3525.c b/firmware/target/arm/as3525/fmradio-i2c-as3525.c index 1dbf2fde24..3da42e31b2 100644 --- a/firmware/target/arm/as3525/fmradio-i2c-as3525.c +++ b/firmware/target/arm/as3525/fmradio-i2c-as3525.c | |||
@@ -27,10 +27,14 @@ | |||
27 | I2C with a couple of GPIO pins. | 27 | I2C with a couple of GPIO pins. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "config.h" | ||
30 | #include "as3525.h" | 31 | #include "as3525.h" |
31 | #include "system.h" | 32 | #include "system.h" |
33 | #include "tuner.h" | ||
32 | #include "generic_i2c.h" | 34 | #include "generic_i2c.h" |
33 | #include "fmradio_i2c.h" | 35 | #include "fmradio_i2c.h" |
36 | #include "thread.h" | ||
37 | #include "rds.h" | ||
34 | 38 | ||
35 | #if defined(SANSA_CLIP) || defined(SANSA_C200V2) | 39 | #if defined(SANSA_CLIP) || defined(SANSA_C200V2) |
36 | #define I2C_SCL_GPIO(x) GPIOB_PIN(x) | 40 | #define I2C_SCL_GPIO(x) GPIOB_PIN(x) |
@@ -179,3 +183,58 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) | |||
179 | #endif | 183 | #endif |
180 | return ret; | 184 | return ret; |
181 | } | 185 | } |
186 | |||
187 | #ifdef HAVE_RDS_CAP | ||
188 | /* Low-level RDS Support */ | ||
189 | static struct semaphore rds_sema; | ||
190 | static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)]; | ||
191 | |||
192 | /* RDS GPIO interrupt handler */ | ||
193 | void tuner_isr(void) | ||
194 | { | ||
195 | /* read and clear the interrupt */ | ||
196 | if (GPIOA_MIS & (1<<4)) { | ||
197 | semaphore_release(&rds_sema); | ||
198 | } | ||
199 | GPIOA_IC = (1<<4); | ||
200 | } | ||
201 | |||
202 | /* Captures RDS data and processes it */ | ||
203 | static void NORETURN_ATTR rds_thread(void) | ||
204 | { | ||
205 | uint16_t rds_data[4]; | ||
206 | |||
207 | while (true) { | ||
208 | semaphore_wait(&rds_sema, TIMEOUT_BLOCK); | ||
209 | if (si4700_rds_read_raw(rds_data) && rds_process(rds_data)) { | ||
210 | si4700_rds_set_event(); | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /* Called with on=true after full radio power up, and with on=false before | ||
216 | powering down */ | ||
217 | void si4700_rds_powerup(bool on) | ||
218 | { | ||
219 | GPIOA_IE &= ~(1<<4); /* disable GPIO interrupt */ | ||
220 | |||
221 | if (on) { | ||
222 | GPIOA_DIR &= ~(1<<4); /* input */ | ||
223 | GPIOA_IS &= ~(1<<4); /* edge detect */ | ||
224 | GPIOA_IBE &= ~(1<<4); /* only one edge */ | ||
225 | GPIOA_IEV &= ~(1<<4); /* falling edge */ | ||
226 | GPIOA_IC = (1<<4); /* clear any pending interrupt */ | ||
227 | GPIOA_IE |= (1<<4); /* enable GPIO interrupt */ | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* One-time RDS init at startup */ | ||
232 | void si4700_rds_init(void) | ||
233 | { | ||
234 | semaphore_init(&rds_sema, 1, 0); | ||
235 | rds_init(); | ||
236 | create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds" | ||
237 | IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); | ||
238 | } | ||
239 | #endif /* HAVE_RDS_CAP */ | ||
240 | |||
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index 7e2e480eda..965030ecc3 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c | |||
@@ -155,6 +155,10 @@ void INT_GPIOA(void) | |||
155 | void button_gpioa_isr(void); | 155 | void button_gpioa_isr(void); |
156 | button_gpioa_isr(); | 156 | button_gpioa_isr(); |
157 | #endif | 157 | #endif |
158 | #ifdef HAVE_RDS_CAP | ||
159 | void tuner_isr(void); | ||
160 | tuner_isr(); | ||
161 | #endif | ||
158 | } | 162 | } |
159 | 163 | ||
160 | void irq_handler(void) | 164 | void irq_handler(void) |
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 39a2cdab04..e0457e367a 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 | |||
@@ -23,8 +23,12 @@ | |||
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "mc13783.h" | 24 | #include "mc13783.h" |
25 | #include "iomuxc-imx31.h" | 25 | #include "iomuxc-imx31.h" |
26 | #include "gpio-imx31.h" | ||
26 | #include "i2c-imx31.h" | 27 | #include "i2c-imx31.h" |
27 | #include "fmradio_i2c.h" | 28 | #include "fmradio_i2c.h" |
29 | #include "thread.h" | ||
30 | #include "rds.h" | ||
31 | #include "tuner.h" | ||
28 | 32 | ||
29 | static struct i2c_node si4700_i2c_node = | 33 | static struct i2c_node si4700_i2c_node = |
30 | { | 34 | { |
@@ -117,7 +121,57 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) | |||
117 | return 0; | 121 | return 0; |
118 | } | 122 | } |
119 | 123 | ||
120 | int si4700_st(void) | 124 | bool si4700_st(void) |
121 | { | 125 | { |
122 | return (GPIO1_DR & (1 << 28)) >> 28; | 126 | return (GPIO1_DR & (1 << 28)) >> 28; |
123 | } | 127 | } |
128 | |||
129 | |||
130 | /* Low-level RDS Support */ | ||
131 | static struct semaphore rds_sema; | ||
132 | static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)]; | ||
133 | |||
134 | /* RDS GPIO interrupt handler */ | ||
135 | void si4700_stc_rds_event(void) | ||
136 | { | ||
137 | /* read and clear the interrupt */ | ||
138 | SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE); | ||
139 | semaphore_release(&rds_sema); | ||
140 | } | ||
141 | |||
142 | /* Called with on=true after full radio power up, and with on=false before | ||
143 | powering down */ | ||
144 | void si4700_rds_powerup(bool on) | ||
145 | { | ||
146 | gpio_disable_event(SI4700_STC_RDS_EVENT_ID); | ||
147 | |||
148 | if (on) | ||
149 | { | ||
150 | SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE); | ||
151 | gpio_enable_event(SI4700_STC_RDS_EVENT_ID); | ||
152 | } | ||
153 | } | ||
154 | |||
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 */ | ||
171 | void si4700_rds_init(void) | ||
172 | { | ||
173 | semaphore_init(&rds_sema, 1, 0); | ||
174 | rds_init(); | ||
175 | create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds" | ||
176 | IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); | ||
177 | } | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c index f4402d5617..e6bbb2345d 100644 --- a/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c | |||
@@ -39,5 +39,12 @@ const struct gpio_event gpio1_events[] = | |||
39 | .mask = 1 << MC13783_GPIO_LINE, | 39 | .mask = 1 << MC13783_GPIO_LINE, |
40 | .sense = GPIO_SENSE_HIGH_LEVEL, | 40 | .sense = GPIO_SENSE_HIGH_LEVEL, |
41 | .callback = mc13783_event, | 41 | .callback = mc13783_event, |
42 | } | 42 | }, |
43 | /* Generates a 5ms low pulse on the line - detect the falling edge */ | ||
44 | [SI4700_STC_RDS_EVENT_ID] = | ||
45 | { | ||
46 | .mask = 1 << SI4700_GPIO_STC_RDS_LINE, | ||
47 | .sense = GPIO_SENSE_FALLING, | ||
48 | .callback = si4700_stc_rds_event, | ||
49 | }, | ||
43 | }; | 50 | }; |
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-target.h b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h index 2eea27c3be..4903d0f631 100644 --- a/firmware/target/arm/imx31/gigabeat-s/gpio-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/gpio-target.h | |||
@@ -29,6 +29,12 @@ | |||
29 | #define MC13783_GPIO_ISR GPIO1_ISR | 29 | #define MC13783_GPIO_ISR GPIO1_ISR |
30 | #define MC13783_GPIO_LINE 31 | 30 | #define MC13783_GPIO_LINE 31 |
31 | 31 | ||
32 | /* SI4700 GPIO STC/RDS pin info for this target */ | ||
33 | #define SI4700_GPIO_STC_RDS_IMR GPIO1_IMR | ||
34 | #define SI4700_GPIO_STC_RDS_NUM GPIO1_NUM | ||
35 | #define SI4700_GPIO_STC_RDS_ISR GPIO1_ISR | ||
36 | #define SI4700_GPIO_STC_RDS_LINE 27 | ||
37 | |||
32 | #define GPIO1_INT_PRIO INT_PRIO_DEFAULT | 38 | #define GPIO1_INT_PRIO INT_PRIO_DEFAULT |
33 | 39 | ||
34 | /* Declare event indexes in priority order in a packed array */ | 40 | /* Declare event indexes in priority order in a packed array */ |
@@ -36,7 +42,8 @@ enum gpio_event_ids | |||
36 | { | 42 | { |
37 | /* GPIO1 event IDs */ | 43 | /* GPIO1 event IDs */ |
38 | MC13783_EVENT_ID = GPIO1_EVENT_FIRST, | 44 | MC13783_EVENT_ID = GPIO1_EVENT_FIRST, |
39 | GPIO1_NUM_EVENTS = 1, | 45 | SI4700_STC_RDS_EVENT_ID, |
46 | GPIO1_NUM_EVENTS = 2, | ||
40 | /* GPIO2 event IDs */ | 47 | /* GPIO2 event IDs */ |
41 | /* none defined */ | 48 | /* none defined */ |
42 | /* GPIO3 event IDs */ | 49 | /* GPIO3 event IDs */ |
@@ -44,5 +51,6 @@ enum gpio_event_ids | |||
44 | }; | 51 | }; |
45 | 52 | ||
46 | void mc13783_event(void); | 53 | void mc13783_event(void); |
54 | void si4700_stc_rds_event(void); | ||
47 | 55 | ||
48 | #endif /* GPIO_TARGET_H */ | 56 | #endif /* GPIO_TARGET_H */ |