From 8c19dcd598144d028ff1647d850d3a17483e6b9c Mon Sep 17 00:00:00 2001 From: Bertrik Sikken Date: Sat, 17 Dec 2011 20:24:19 +0000 Subject: 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 --- firmware/target/arm/as3525/fmradio-i2c-as3525.c | 59 +++++++++++++++++++++++++ firmware/target/arm/as3525/system-as3525.c | 4 ++ 2 files changed, 63 insertions(+) (limited to 'firmware/target/arm/as3525') diff --git a/firmware/target/arm/as3525/fmradio-i2c-as3525.c b/firmware/target/arm/as3525/fmradio-i2c-as3525.c index 1dbf2fde24..3da42e31b2 100644 --- a/firmware/target/arm/as3525/fmradio-i2c-as3525.c +++ b/firmware/target/arm/as3525/fmradio-i2c-as3525.c @@ -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 */ + diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index 7e2e480eda..965030ecc3 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c @@ -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) -- cgit v1.2.3