RFT: convert Gigabeat RDS to thread

This kind of reverts 7b596416bf ("Gigabeat S: Update RDS processing to
use asynchronous I2C rather than thread."). However, requiring RDS to
run in thread context will a) allow more upcoming features and b) remove
quite some complexity from the codebase (see the diffstat here) because
Gigabeat is the only user. iMX31 should be able to handle one more
thread, as it can even run Linux.

Change-Id: I46130034595ba66392c5417c275d036f4bd26943
This commit is contained in:
Wolfram Sang 2021-12-10 16:13:49 +01:00
parent 8d453ae9c3
commit 5b8873bf33
6 changed files with 16 additions and 94 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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));
}