FS#12370: Initial RDS support for Si4701/Si4703 tuner (beast and clip zip)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31346 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Bertrik Sikken 2011-12-17 20:24:19 +00:00
parent 17ed3253fc
commit 8c19dcd598
13 changed files with 525 additions and 37 deletions

View file

@ -27,10 +27,14 @@
I2C with a couple of GPIO pins.
*/
#include "config.h"
#include "as3525.h"
#include "system.h"
#include "tuner.h"
#include "generic_i2c.h"
#include "fmradio_i2c.h"
#include "thread.h"
#include "rds.h"
#if defined(SANSA_CLIP) || defined(SANSA_C200V2)
#define I2C_SCL_GPIO(x) GPIOB_PIN(x)
@ -179,3 +183,58 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
#endif
return ret;
}
#ifdef HAVE_RDS_CAP
/* Low-level RDS Support */
static struct semaphore rds_sema;
static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
/* RDS GPIO interrupt handler */
void tuner_isr(void)
{
/* read and clear the interrupt */
if (GPIOA_MIS & (1<<4)) {
semaphore_release(&rds_sema);
}
GPIOA_IC = (1<<4);
}
/* Captures RDS data and processes it */
static void NORETURN_ATTR rds_thread(void)
{
uint16_t rds_data[4];
while (true) {
semaphore_wait(&rds_sema, TIMEOUT_BLOCK);
if (si4700_rds_read_raw(rds_data) && rds_process(rds_data)) {
si4700_rds_set_event();
}
}
}
/* Called with on=true after full radio power up, and with on=false before
powering down */
void si4700_rds_powerup(bool on)
{
GPIOA_IE &= ~(1<<4); /* disable GPIO interrupt */
if (on) {
GPIOA_DIR &= ~(1<<4); /* input */
GPIOA_IS &= ~(1<<4); /* edge detect */
GPIOA_IBE &= ~(1<<4); /* only one edge */
GPIOA_IEV &= ~(1<<4); /* falling edge */
GPIOA_IC = (1<<4); /* clear any pending interrupt */
GPIOA_IE |= (1<<4); /* enable GPIO interrupt */
}
}
/* 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));
}
#endif /* HAVE_RDS_CAP */

View file

@ -155,6 +155,10 @@ void INT_GPIOA(void)
void button_gpioa_isr(void);
button_gpioa_isr();
#endif
#ifdef HAVE_RDS_CAP
void tuner_isr(void);
tuner_isr();
#endif
}
void irq_handler(void)

View file

@ -23,8 +23,12 @@
#include "system.h"
#include "mc13783.h"
#include "iomuxc-imx31.h"
#include "gpio-imx31.h"
#include "i2c-imx31.h"
#include "fmradio_i2c.h"
#include "thread.h"
#include "rds.h"
#include "tuner.h"
static struct i2c_node si4700_i2c_node =
{
@ -117,7 +121,57 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
return 0;
}
int si4700_st(void)
bool si4700_st(void)
{
return (GPIO1_DR & (1 << 28)) >> 28;
}
/* Low-level RDS Support */
static struct semaphore rds_sema;
static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
/* RDS GPIO interrupt handler */
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);
}
/* Called with on=true after full radio power up, and with on=false before
powering down */
void si4700_rds_powerup(bool on)
{
gpio_disable_event(SI4700_STC_RDS_EVENT_ID);
if (on)
{
SI4700_GPIO_STC_RDS_ISR = (1ul << SI4700_GPIO_STC_RDS_LINE);
gpio_enable_event(SI4700_STC_RDS_EVENT_ID);
}
}
/* 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));
}

View file

@ -39,5 +39,12 @@ const struct gpio_event gpio1_events[] =
.mask = 1 << MC13783_GPIO_LINE,
.sense = GPIO_SENSE_HIGH_LEVEL,
.callback = mc13783_event,
}
},
/* Generates a 5ms low pulse on the line - detect the falling edge */
[SI4700_STC_RDS_EVENT_ID] =
{
.mask = 1 << SI4700_GPIO_STC_RDS_LINE,
.sense = GPIO_SENSE_FALLING,
.callback = si4700_stc_rds_event,
},
};

View file

@ -29,6 +29,12 @@
#define MC13783_GPIO_ISR GPIO1_ISR
#define MC13783_GPIO_LINE 31
/* SI4700 GPIO STC/RDS pin info for this target */
#define SI4700_GPIO_STC_RDS_IMR GPIO1_IMR
#define SI4700_GPIO_STC_RDS_NUM GPIO1_NUM
#define SI4700_GPIO_STC_RDS_ISR GPIO1_ISR
#define SI4700_GPIO_STC_RDS_LINE 27
#define GPIO1_INT_PRIO INT_PRIO_DEFAULT
/* Declare event indexes in priority order in a packed array */
@ -36,7 +42,8 @@ enum gpio_event_ids
{
/* GPIO1 event IDs */
MC13783_EVENT_ID = GPIO1_EVENT_FIRST,
GPIO1_NUM_EVENTS = 1,
SI4700_STC_RDS_EVENT_ID,
GPIO1_NUM_EVENTS = 2,
/* GPIO2 event IDs */
/* none defined */
/* GPIO3 event IDs */
@ -44,5 +51,6 @@ enum gpio_event_ids
};
void mc13783_event(void);
void si4700_stc_rds_event(void);
#endif /* GPIO_TARGET_H */