mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
Sansa Clip+: add RDS support
Based on a patch by Amaury Pouly which was based on a patch from Ryan Hitchman. I mainly moved the code for polling into the tuner driver so it can be reused by other targets. I added the CONFIG parameter for the polling frequency (in ticks) to save energy. Also, I did some minor cleanups. Change-Id: I95a62e7e1e42c62dbf47ecb27a3b312a42be62aa
This commit is contained in:
parent
701d4ba77e
commit
de0346065b
6 changed files with 76 additions and 2 deletions
|
@ -587,12 +587,67 @@ void si4700_rds_process(void)
|
||||||
if (tuner_powered())
|
if (tuner_powered())
|
||||||
{
|
{
|
||||||
si4700_read_reg(RDSD);
|
si4700_read_reg(RDSD);
|
||||||
|
#if (CONFIG_RDS & RDS_CFG_POLL)
|
||||||
|
/* we need to keep track of the ready bit because it stays set for 80ms
|
||||||
|
* and we must avoid processing it twice */
|
||||||
|
|
||||||
|
static bool old_rdsr = false;
|
||||||
|
bool rdsr = (cache[STATUSRSSI] & STATUSRSSI_RDSR);
|
||||||
|
if (rdsr && !old_rdsr)
|
||||||
rds_process(&cache[RDSA]);
|
rds_process(&cache[RDSA]);
|
||||||
|
old_rdsr = rdsr;
|
||||||
|
#else
|
||||||
|
rds_process(&cache[RDSA]);
|
||||||
|
#endif /* !(CONFIG_RDS & RDS_CFG_POLL) */
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&fmr_mutex);
|
mutex_unlock(&fmr_mutex);
|
||||||
}
|
}
|
||||||
#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
|
#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
|
||||||
|
|
||||||
|
#if (CONFIG_RDS & RDS_CFG_POLL)
|
||||||
|
static struct event_queue rds_queue;
|
||||||
|
static uint32_t rds_stack[DEFAULT_STACK_SIZE / sizeof(uint32_t)];
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Q_POWERUP,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void NORETURN_ATTR rds_thread(void)
|
||||||
|
{
|
||||||
|
/* start up frozen */
|
||||||
|
int timeout = TIMEOUT_BLOCK;
|
||||||
|
struct queue_event ev;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
queue_wait_w_tmo(&rds_queue, &ev, timeout);
|
||||||
|
switch (ev.id) {
|
||||||
|
case Q_POWERUP:
|
||||||
|
/* power up: timeout after 1 tick, else block indefinitely */
|
||||||
|
timeout = ev.data ? CONFIG_RDS_POLL_TICKS : TIMEOUT_BLOCK;
|
||||||
|
break;
|
||||||
|
case SYS_TIMEOUT:;
|
||||||
|
/* Captures RDS data and processes it */
|
||||||
|
si4700_rds_process();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* true after full radio power up, and false before powering down */
|
||||||
|
void si4700_rds_powerup(bool on)
|
||||||
|
{
|
||||||
|
queue_post(&rds_queue, Q_POWERUP, on);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One-time RDS init at startup */
|
||||||
|
void si4700_rds_init(void)
|
||||||
|
{
|
||||||
|
queue_init(&rds_queue, false);
|
||||||
|
create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
|
||||||
|
IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
|
||||||
|
}
|
||||||
|
#endif /* !(CONFIG_RDS & RDS_CFG_POLL) */
|
||||||
|
|
||||||
#endif /* HAVE_RDS_CAP */
|
#endif /* HAVE_RDS_CAP */
|
||||||
|
|
||||||
|
|
|
@ -718,6 +718,7 @@ Lyre prototype 1 */
|
||||||
#define RDS_CFG_ISR 0x1 /* uses ISR to process packets */
|
#define RDS_CFG_ISR 0x1 /* uses ISR to process packets */
|
||||||
#define RDS_CFG_PROCESS 0x2 /* uses raw packet processing */
|
#define RDS_CFG_PROCESS 0x2 /* uses raw packet processing */
|
||||||
#define RDS_CFG_PUSH 0x4 /* pushes processed information */
|
#define RDS_CFG_PUSH 0x4 /* pushes processed information */
|
||||||
|
#define RDS_CFG_POLL 0x8 /* tuner driver provides a polling function */
|
||||||
#ifndef CONFIG_RDS
|
#ifndef CONFIG_RDS
|
||||||
#define CONFIG_RDS RDS_CFG_PROCESS /* thread processing+raw processing */
|
#define CONFIG_RDS RDS_CFG_PROCESS /* thread processing+raw processing */
|
||||||
#endif /* CONFIG_RDS */
|
#endif /* CONFIG_RDS */
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
#define HAVE_HOTSWAP
|
#define HAVE_HOTSWAP
|
||||||
|
#define HAVE_RDS_CAP
|
||||||
|
#define CONFIG_RDS (RDS_CFG_POLL | RDS_CFG_PROCESS)
|
||||||
|
#define CONFIG_RDS_POLL_TICKS 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HW_SAMPR_CAPS SAMPR_CAP_ALL_96
|
#define HW_SAMPR_CAPS SAMPR_CAP_ALL_96
|
||||||
|
@ -146,6 +149,9 @@
|
||||||
/* define this if the flash memory uses the SecureDigital Memory Card protocol */
|
/* define this if the flash memory uses the SecureDigital Memory Card protocol */
|
||||||
#define CONFIG_STORAGE STORAGE_SD
|
#define CONFIG_STORAGE STORAGE_SD
|
||||||
|
|
||||||
|
/* Define this if target has an additional number of threads specific to it */
|
||||||
|
#define TARGET_EXTRA_THREADS 1 /* RDS thread */
|
||||||
|
|
||||||
#define BATTERY_CAPACITY_DEFAULT 290 /* default battery capacity */
|
#define BATTERY_CAPACITY_DEFAULT 290 /* default battery capacity */
|
||||||
#define BATTERY_CAPACITY_MIN 290 /* min. capacity selectable */
|
#define BATTERY_CAPACITY_MIN 290 /* min. capacity selectable */
|
||||||
#define BATTERY_CAPACITY_MAX 290 /* max. capacity selectable */
|
#define BATTERY_CAPACITY_MAX 290 /* max. capacity selectable */
|
||||||
|
|
|
@ -55,7 +55,13 @@ void si4700_rds_read_raw_async(unsigned char *buf, int count); /* implemented by
|
||||||
void si4700_rds_interrupt(void);
|
void si4700_rds_interrupt(void);
|
||||||
#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
|
#endif /* (CONFIG_RDS & RDS_CFG_ISR) */
|
||||||
|
|
||||||
/* Read raw RDS info for processing */
|
/* 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
|
||||||
|
* new. */
|
||||||
void si4700_rds_process(void);
|
void si4700_rds_process(void);
|
||||||
|
|
||||||
#endif /* HAVE_RDS_CAP */
|
#endif /* HAVE_RDS_CAP */
|
||||||
|
|
|
@ -185,6 +185,11 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_RDS_CAP
|
#ifdef HAVE_RDS_CAP
|
||||||
|
/* On the Sansa Clip Zip, the tuner interrupt line is routed to the SoC so we
|
||||||
|
* can use to detect when a RDS packet is ready. On the Clip+, we have to
|
||||||
|
* regularly poll. */
|
||||||
|
|
||||||
|
#if !(CONFIG_RDS & RDS_CFG_POLL)
|
||||||
/* Low-level RDS Support */
|
/* Low-level RDS Support */
|
||||||
static struct semaphore rds_sema;
|
static struct semaphore rds_sema;
|
||||||
static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
|
static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
|
||||||
|
@ -231,4 +236,5 @@ void si4700_rds_init(void)
|
||||||
create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
|
create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
|
||||||
IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
|
IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
|
||||||
}
|
}
|
||||||
|
#endif /* !(CONFIG_RDS & RDS_CFG_POLL) */
|
||||||
#endif /* HAVE_RDS_CAP */
|
#endif /* HAVE_RDS_CAP */
|
||||||
|
|
|
@ -180,7 +180,7 @@ void INT_GPIOA(void)
|
||||||
void button_gpioa_isr(void);
|
void button_gpioa_isr(void);
|
||||||
button_gpioa_isr();
|
button_gpioa_isr();
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_RDS_CAP
|
#if defined(HAVE_RDS_CAP) && !(CONFIG_RDS & RDS_CFG_POLL)
|
||||||
void tuner_isr(void);
|
void tuner_isr(void);
|
||||||
tuner_isr();
|
tuner_isr();
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue