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] */ #define RT_DATA_INC(x) rt_data[rt_data_idx ^= (x)] #endif /* (CONFIG_RDS & RDS_CFG_PROCESS) */ -#if (CONFIG_RDS & RDS_CFG_ISR) -/* Functions are called in ISR context */ -#define rds_disable_irq_save() disable_irq_save() -#define rds_restore_irq(old) restore_irq(old) -#else /* !(CONFIG_RDS & RDS_CFG_ISR) */ -#define rds_disable_irq_save() 0 -#define rds_restore_irq(old) ((void)(old)) -#endif /* (CONFIG_RDS & RDS_CFG_ISR) */ - /* RDS code table G0 to UTF-8 translation */ static const uint16_t rds_tbl_g0[0x100-0x20] = { @@ -195,8 +186,6 @@ static void register_activity(void) /* resets the rds parser */ void rds_reset(void) { - int oldlevel = rds_disable_irq_save(); - /* reset general info */ pi_code = 0; ct_data = 0; @@ -210,8 +199,6 @@ void rds_reset(void) ps_segment = 0; rt_segment = 0; #endif /* (CONFIG_RDS & RDS_CFG_PROCESS) */ - - rds_restore_irq(oldlevel); } /* initialises the rds parser */ @@ -223,8 +210,6 @@ void rds_init(void) /* sync RDS state */ void rds_sync(void) { - int oldlevel = rds_disable_irq_save(); - if (rds_active) { if (TIMED_OUT(rds_timeout)) { rds_reset(); @@ -238,8 +223,6 @@ void rds_sync(void) } } } - - rds_restore_irq(oldlevel); } #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) /* read fully-processed RDS data */ size_t rds_pull_info(enum rds_info_id info_id, uintptr_t data, size_t size) { - int oldlevel = rds_disable_irq_save(); - rds_sync(); switch (info_id) { @@ -490,7 +471,5 @@ size_t rds_pull_info(enum rds_info_id info_id, uintptr_t data, size_t size) default: size = 0; } - - rds_restore_irq(oldlevel); return size; } 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) } #ifdef HAVE_RDS_CAP - -#if (CONFIG_RDS & RDS_CFG_ISR) -static unsigned char isr_regbuf[(RDSD - STATUSRSSI + 1) * 2]; - -/* Called by RDS interrupt on target */ -void si4700_rds_interrupt(void) -{ - si4700_rds_read_raw_async(isr_regbuf, sizeof (isr_regbuf)); -} - -/* Handle RDS event from ISR */ -void si4700_rds_process(void) -{ - uint16_t rds_data[4]; - int index = (RDSA - STATUSRSSI) * 2; - - for (int i = 0; i < 4; i++) { - rds_data[i] = isr_regbuf[index] << 8 | isr_regbuf[index + 1]; - index += 2; - } - - rds_process(rds_data); -} - -#else /* !(CONFIG_RDS & RDS_CFG_ISR) */ - /* Handle RDS event from thread */ void si4700_rds_process(void) { @@ -603,7 +577,6 @@ void si4700_rds_process(void) mutex_unlock(&fmr_mutex); } -#endif /* (CONFIG_RDS & RDS_CFG_ISR) */ #if (CONFIG_RDS & RDS_CFG_POLL) static 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 */ #ifdef HAVE_RDS_CAP /* combinable bitflags */ -#define RDS_CFG_ISR 0x1 /* uses ISR to process packets */ +/* 0x01 can be reused, was RDS_CFG_ISR */ #define RDS_CFG_PROCESS 0x2 /* uses raw packet processing */ #define RDS_CFG_PUSH 0x4 /* pushes processed information */ #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 @@ /* Define this if you have a SI4700 fm radio tuner */ #define CONFIG_TUNER SI4700 #define HAVE_RDS_CAP -#define CONFIG_RDS (RDS_CFG_ISR | RDS_CFG_PROCESS) /* define this if you can flip your LCD */ #define HAVE_LCD_FLIP @@ -164,7 +163,7 @@ #define GPIO_EVENT_MASK (USE_GPIO1_EVENTS) /* Define this if target has an additional number of threads specific to it */ -#define TARGET_EXTRA_THREADS 1 +#define TARGET_EXTRA_THREADS 2 /* one is for RDS */ /* Type of mobile power - check this out */ #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; /* Radio is fully powered up or about to be powered down */ void si4700_rds_powerup(bool on); -#if (CONFIG_RDS & RDS_CFG_ISR) -/* Read raw RDS info for processing - asynchronously */ -void si4700_rds_read_raw_async(unsigned char *buf, int count); /* implemented by target */ -void si4700_rds_interrupt(void); -#endif /* (CONFIG_RDS & RDS_CFG_ISR) */ - /* Read raw RDS info for processing. - * - If RDS_CFG_ISR is set, the tuner driver will call si4700_rds_read_raw_async() which should - * perform an asynchronous read and call this function when the data has been read. * - If RDS_CFG_POLL is set, this function will read status and RDS data and process it if a new * packet is available. * - 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) return (GPIO1_DR & (1 << 28)) >> 28; } - /* Low-level RDS Support */ -static bool int_restore; - -/* Called after I2C read cycle completes */ -static void si4700_rds_read_raw_async_callback(struct i2c_transfer_desc *xfer) -{ - if (xfer->rxcount == 0) - si4700_rds_process(); - /* else read didn't finish */ - - if (int_restore) - gpio_int_enable(SI4700_EVENT_ID); -} - -/* Called to read registers from ISR context */ -void si4700_rds_read_raw_async(unsigned char *buf, int count) -{ - /* transfer descriptor for RDS async operations */ - static struct i2c_transfer_desc xfer = { .node = &si4700_i2c_node }; - - xfer.txdata = NULL; - xfer.txcount = 0; - xfer.rxdata = buf; - xfer.rxcount = count; - xfer.callback = si4700_rds_read_raw_async_callback; - xfer.next = NULL; - - i2c_transfer(&xfer); -} +static struct semaphore rds_sema; +static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)]; /* RDS GPIO interrupt handler - start RDS data read */ void INT_SI4700_RDS(void) { - /* mask and clear the interrupt until we're done */ - gpio_int_disable(SI4700_EVENT_ID); gpio_int_clear(SI4700_EVENT_ID); + semaphore_release(&rds_sema); +} - /* tell radio driver about it */ - si4700_rds_interrupt(); +/* Captures RDS data and processes it */ +static void NORETURN_ATTR rds_thread(void) +{ + while (true) { + semaphore_wait(&rds_sema, TIMEOUT_BLOCK); + si4700_rds_process(); + } } /* Called with on=true after full radio power up, and with on=false before powering down */ void si4700_rds_powerup(bool on) { - int_restore = on; gpio_int_disable(SI4700_EVENT_ID); gpio_int_clear(SI4700_EVENT_ID); gpio_enable_event(SI4700_EVENT_ID, on); @@ -180,5 +157,7 @@ void si4700_rds_powerup(bool on) /* One-time RDS init at startup */ void si4700_rds_init(void) { - /* nothing to do */ + semaphore_init(&rds_sema, 1, 0); + create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds" + IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); }