mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
Gigabeat S: Update RDS processing to use asynchronous I2C rather than thread.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31462 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
20d81d979a
commit
7b596416bf
5 changed files with 119 additions and 27 deletions
|
@ -36,14 +36,46 @@ static char rt_copy[65];
|
|||
static int rt_segment;
|
||||
static int rt_abflag;
|
||||
|
||||
#ifdef SI4700_RDS_ASYNC
|
||||
/* Functions are called in ISR context */
|
||||
#define rds_disable_irq_save() disable_irq_save()
|
||||
#define rds_restore_irq(old) restore_irq(old)
|
||||
/* Need triple buffer so string isn't clobbered while caller is using it */
|
||||
static inline char * get_ps(void)
|
||||
{
|
||||
static char ps_out[9];
|
||||
int oldlevel = rds_disable_irq_save();
|
||||
strcpy(ps_out, ps_copy);
|
||||
rds_restore_irq(oldlevel);
|
||||
return ps_out;
|
||||
}
|
||||
static inline char * get_rt(void)
|
||||
{
|
||||
static char rt_out[65];
|
||||
int oldlevel = rds_disable_irq_save();
|
||||
strcpy(rt_out, rt_copy);
|
||||
rds_restore_irq(oldlevel);
|
||||
return rt_out;
|
||||
}
|
||||
#else /* ndef SI4700_RDS_ASYNC */
|
||||
#define rds_disable_irq_save() 0
|
||||
#define rds_restore_irq(old) ((void)(old))
|
||||
static inline char * get_ps(void) { return ps_copy; }
|
||||
static inline char * get_rt(void) { return rt_copy; }
|
||||
#endif /* SI4700_RDS_ASYNC */
|
||||
|
||||
/* resets the rds parser */
|
||||
void rds_reset(void)
|
||||
{
|
||||
int oldlevel = rds_disable_irq_save();
|
||||
|
||||
ps_copy[0] = '\0';
|
||||
ps_segment = 0;
|
||||
rt_copy[0] = '\0';
|
||||
rt_segment = 0;
|
||||
pi = 0;
|
||||
|
||||
rds_restore_irq(oldlevel);
|
||||
}
|
||||
|
||||
/* initialises the rds parser */
|
||||
|
@ -172,6 +204,9 @@ bool rds_process(uint16_t data[4])
|
|||
return false;
|
||||
}
|
||||
|
||||
/* TODO: The caller really should provide the buffer in order to regulate
|
||||
access */
|
||||
|
||||
/* returns the programme identification code */
|
||||
uint16_t rds_get_pi(void)
|
||||
{
|
||||
|
@ -181,12 +216,12 @@ uint16_t rds_get_pi(void)
|
|||
/* returns the most recent valid programme service name */
|
||||
char* rds_get_ps(void)
|
||||
{
|
||||
return ps_copy;
|
||||
return get_ps();
|
||||
}
|
||||
|
||||
/* returns the most recent valid RadioText message */
|
||||
char* rds_get_rt(void)
|
||||
{
|
||||
return rt_copy;
|
||||
return get_rt();
|
||||
}
|
||||
|
||||
|
|
|
@ -556,6 +556,34 @@ void si4700_dbg_info(struct si4700_dbg_info *nfo)
|
|||
}
|
||||
|
||||
#ifdef HAVE_RDS_CAP
|
||||
|
||||
#ifdef SI4700_RDS_ASYNC
|
||||
/* Read raw RDS info for processing - asynchronously */
|
||||
|
||||
/* Assumes regbuf is 32 bytes */
|
||||
void si4700_rds_read_raw_async(void)
|
||||
{
|
||||
si4700_read_raw_async((RDSD - STATUSRSSI + 1) * 2);
|
||||
}
|
||||
|
||||
void si4700_rds_read_raw_async_complete(unsigned char *regbuf,
|
||||
uint16_t data[4])
|
||||
{
|
||||
const int index = (RDSA - STATUSRSSI) * 2;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
data[i] = regbuf[index] << 8 | regbuf[index + 1];
|
||||
regbuf += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the event flag */
|
||||
void si4700_rds_set_event(void)
|
||||
{
|
||||
rds_event = 1;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Read raw RDS info for processing */
|
||||
bool si4700_rds_read_raw(uint16_t data[4])
|
||||
{
|
||||
|
@ -582,6 +610,7 @@ void si4700_rds_set_event(void)
|
|||
rds_event = 1;
|
||||
mutex_unlock(&fmr_mutex);
|
||||
}
|
||||
#endif /* SI4700_RDS_ASYNC */
|
||||
|
||||
char * si4700_get_rds_info(int setting)
|
||||
{
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#define CONFIG_TUNER SI4700
|
||||
|
||||
#define HAVE_RDS_CAP
|
||||
#define SI4700_RDS_ASYNC
|
||||
|
||||
/* Define this if you have the WM8978 audio codec */
|
||||
#define HAVE_WM8978
|
||||
|
@ -163,7 +164,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 3
|
||||
#define TARGET_EXTRA_THREADS 2
|
||||
|
||||
/* Type of mobile power - check this out */
|
||||
#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */
|
||||
|
|
|
@ -44,10 +44,18 @@ bool si4700_st(void);
|
|||
|
||||
/** RDS support **/
|
||||
void si4700_rds_init(void);
|
||||
/* Read raw RDS info for processing */
|
||||
bool si4700_rds_read_raw(uint16_t data[4]);
|
||||
/* Radio is fully powered up or about to be powered down */
|
||||
void si4700_rds_powerup(bool on);
|
||||
#ifdef SI4700_RDS_ASYNC
|
||||
/* Read raw RDS info for processing - asynchronously */
|
||||
void si4700_read_raw_async(int count);
|
||||
void si4700_rds_read_raw_async(void);
|
||||
void si4700_rds_read_raw_async_complete(unsigned char *regbuf,
|
||||
uint16_t data[4]);
|
||||
#else
|
||||
/* Read raw RDS info for processing */
|
||||
bool si4700_rds_read_raw(uint16_t data[4]);
|
||||
#endif
|
||||
/* Obtain specified string */
|
||||
char* si4700_get_rds_info(int setting);
|
||||
/* Set the event flag */
|
||||
|
|
|
@ -128,15 +128,52 @@ bool si4700_st(void)
|
|||
|
||||
|
||||
/* Low-level RDS Support */
|
||||
static struct semaphore rds_sema;
|
||||
static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
|
||||
|
||||
/* RDS GPIO interrupt handler */
|
||||
/* Transfer descriptor for RDS async operations */
|
||||
struct si4700_i2c_transfer_desc
|
||||
{
|
||||
struct i2c_transfer_desc xfer;
|
||||
unsigned char regbuf[32];
|
||||
} si4700_xfer =
|
||||
{
|
||||
.xfer = { .node = &si4700_i2c_node }
|
||||
};
|
||||
|
||||
static void si4700_rds_read_raw_callback(struct i2c_transfer_desc *xfer)
|
||||
{
|
||||
struct si4700_i2c_transfer_desc *xf =
|
||||
(struct si4700_i2c_transfer_desc *)xfer;
|
||||
|
||||
if (xfer->rxcount != 0)
|
||||
return; /* Read didn't finish */
|
||||
|
||||
uint16_t rds_data[4];
|
||||
|
||||
si4700_rds_read_raw_async_complete(xf->regbuf, rds_data);
|
||||
|
||||
if (rds_process(rds_data))
|
||||
si4700_rds_set_event();
|
||||
}
|
||||
|
||||
/* Callback from si4700_rds_read_raw to execute the read */
|
||||
void si4700_read_raw_async(int count)
|
||||
{
|
||||
si4700_xfer.xfer.txdata = NULL;
|
||||
si4700_xfer.xfer.txcount = 0;
|
||||
si4700_xfer.xfer.rxdata = si4700_xfer.regbuf;
|
||||
si4700_xfer.xfer.rxcount = count;
|
||||
si4700_xfer.xfer.callback = si4700_rds_read_raw_callback;
|
||||
si4700_xfer.xfer.next = NULL;
|
||||
|
||||
i2c_transfer(&si4700_xfer.xfer);
|
||||
}
|
||||
|
||||
/* RDS GPIO interrupt handler - start RDS data read */
|
||||
void si4700_stc_rds_event(void)
|
||||
{
|
||||
/* read and clear the interrupt */
|
||||
SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE);
|
||||
semaphore_release(&rds_sema);
|
||||
si4700_rds_read_raw_async();
|
||||
}
|
||||
|
||||
/* Called with on=true after full radio power up, and with on=false before
|
||||
|
@ -152,26 +189,8 @@ void si4700_rds_powerup(bool on)
|
|||
}
|
||||
}
|
||||
|
||||
/* Captures RDS data and processes it */
|
||||
/* Use of a thread here is likely temporary */
|
||||
static void NORETURN_ATTR rds_thread(void)
|
||||
{
|
||||
uint16_t rds_data[4];
|
||||
|
||||
while (1)
|
||||
{
|
||||
semaphore_wait(&rds_sema, TIMEOUT_BLOCK);
|
||||
|
||||
if (si4700_rds_read_raw(rds_data) && rds_process(rds_data))
|
||||
si4700_rds_set_event();
|
||||
}
|
||||
}
|
||||
|
||||
/* One-time RDS init at startup */
|
||||
void si4700_rds_init(void)
|
||||
{
|
||||
semaphore_init(&rds_sema, 1, 0);
|
||||
rds_init();
|
||||
create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
|
||||
IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue