Index: apps/debug_menu.c =================================================================== --- apps/debug_menu.c (revision 30912) +++ apps/debug_menu.c (working copy) @@ -1733,6 +1733,13 @@ simplelist_addline(SIMPLELIST_ADD_LINE,"%02X: %04X %04X %04X %04X", i, nfo.regs[i], nfo.regs[i+1], nfo.regs[i+2], nfo.regs[i+3]); } + simplelist_addline(SIMPLELIST_ADD_LINE, ""); + simplelist_addline(SIMPLELIST_ADD_LINE, "RDS Info:"); + simplelist_addline(SIMPLELIST_ADD_LINE, + si4700_get_rds_info(RADIO_RDS_NAME)); + + simplelist_addline(SIMPLELIST_ADD_LINE, + si4700_get_rds_info(RADIO_RDS_TEXT)); } #endif /* SI4700 */ #if (CONFIG_TUNER & RDA5802) Index: firmware/export/si4700.h =================================================================== --- firmware/export/si4700.h (revision 30912) +++ firmware/export/si4700.h (working copy) @@ -39,10 +39,24 @@ int si4700_set(int setting, int value); int si4700_get(int setting); void si4700_dbg_info(struct si4700_dbg_info *nfo); +/* For interrupt-based mono/stereo indicator */ +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); +/* Obtain specified string */ +char* si4700_get_rds_info(int setting); +/* Set the event flag */ +void si4700_rds_set_event(void); + #ifndef CONFIG_TUNER_MULTI #define tuner_set si4700_set #define tuner_get si4700_get +#define tuner_get_rds_info si4700_get_rds_info #endif #endif /* _SI4700_H_ */ Index: firmware/export/config/sansaclipzip.h =================================================================== --- firmware/export/config/sansaclipzip.h (revision 30912) +++ firmware/export/config/sansaclipzip.h (working copy) @@ -27,6 +27,8 @@ explicitly if different */ #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) +#define HAVE_RDS_CAP + /* define this if you have a bitmap LCD display */ #define HAVE_LCD_BITMAP /* define this if you have a colour LCD */ Index: firmware/export/config/gigabeats.h =================================================================== --- firmware/export/config/gigabeats.h (revision 30912) +++ firmware/export/config/gigabeats.h (working copy) @@ -89,6 +89,8 @@ /* Define this if you have a SI4700 fm radio tuner */ #define CONFIG_TUNER SI4700 +#define HAVE_RDS_CAP + /* Define this if you have the WM8978 audio codec */ #define HAVE_WM8978 @@ -161,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 2 +#define TARGET_EXTRA_THREADS 3 /* Type of mobile power - check this out */ #define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */ Index: firmware/export/rds.h =================================================================== --- firmware/export/rds.h (revision 0) +++ firmware/export/rds.h (revision 0) @@ -0,0 +1,38 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (c) 2011 by Bertrik Sikken + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include + +enum rds_event { + RDS_EVENT_NONE = 0, + RDS_EVENT_PS, + RDS_EVENT_RT +}; + +void rds_init(void); + +void rds_reset(void); +enum rds_event rds_process(uint16_t data[4]); + +uint16_t rds_get_pi(void); +char* rds_get_ps(void); +char* rds_get_rt(void); + + Property changes on: firmware/export/rds.h ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Index: firmware/SOURCES =================================================================== --- firmware/SOURCES (revision 30912) +++ firmware/SOURCES (working copy) @@ -296,6 +296,7 @@ #endif /* (CONFIG_TUNER & TEA5767) */ #if (CONFIG_TUNER & SI4700) drivers/tuner/si4700.c +drivers/rds.c #endif /* (CONFIG_TUNER & SI4700) */ #if (CONFIG_TUNER & IPOD_REMOTE_TUNER) drivers/tuner/ipod_remote_tuner.c Index: firmware/target/arm/as3525/system-as3525.c =================================================================== --- firmware/target/arm/as3525/system-as3525.c (revision 30912) +++ firmware/target/arm/as3525/system-as3525.c (working copy) @@ -155,6 +155,8 @@ void button_gpioa_isr(void); button_gpioa_isr(); #endif + void tuner_isr(void); + tuner_isr(); } void irq_handler(void) Index: firmware/target/arm/as3525/fmradio-i2c-as3525.c =================================================================== --- firmware/target/arm/as3525/fmradio-i2c-as3525.c (revision 30912) +++ firmware/target/arm/as3525/fmradio-i2c-as3525.c (working copy) @@ -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,55 @@ #endif return ret; } + +/* 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)); +} Index: firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c =================================================================== --- firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c (revision 30912) +++ firmware/target/arm/imx31/gigabeat-s/gpio-gigabeat-s.c (working copy) @@ -39,5 +39,12 @@ .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, + }, }; Index: firmware/target/arm/imx31/gigabeat-s/gpio-target.h =================================================================== --- firmware/target/arm/imx31/gigabeat-s/gpio-target.h (revision 30912) +++ firmware/target/arm/imx31/gigabeat-s/gpio-target.h (working copy) @@ -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 @@ { /* 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 @@ }; void mc13783_event(void); +void si4700_stc_rds_event(void); #endif /* GPIO_TARGET_H */ Index: firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c =================================================================== --- firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c (revision 30912) +++ firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c (working copy) @@ -23,8 +23,11 @@ #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" static struct i2c_node si4700_i2c_node = { @@ -121,3 +124,53 @@ { 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)); +} Index: firmware/drivers/rds.c =================================================================== --- firmware/drivers/rds.c (revision 0) +++ firmware/drivers/rds.c (revision 0) @@ -0,0 +1,190 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (c) 2011 by Bertrik Sikken + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include +#include +#include +#include "rds.h" + +/* programme identification */ +static uint16_t pi; +/* program service name */ +static char ps_data[9]; +static char ps_copy[9]; +static int ps_segment; +/* radio text */ +static char rt_data[65]; +static char rt_copy[65]; +static int rt_segment; +static int rt_abflag; + +/* resets the rds parser */ +void rds_reset(void) +{ + ps_copy[0] = '\0'; + rt_copy[0] = '\0'; + pi = 0; +} + +/* initialises the rds parser */ +void rds_init(void) +{ + rds_reset(); +} + +/* handles a group 0 packet, returns true if a complete message was received */ +static bool handle_group0(uint16_t data[4]) +{ + int segment, pos; + + segment = data[1] & 3; + + /* reset parsing if not in order */ + if (segment != ps_segment) { + ps_segment = 0; + if (segment != 0) { + return false; + } + } + + /* store data */ + pos = segment * 2; + ps_data[pos++] = (data[3] >> 8) & 0xFF; + ps_data[pos++] = (data[3] >> 0) & 0xFF; + if (++ps_segment == 4) { + ps_data[pos] = '\0'; + strcpy(ps_copy, ps_data); + return true; + } + return false; +} + +/* handles a radio text characters, returns true if end-of-line found */ +static bool handle_rt(int pos, char c) +{ + switch (c) { + case 0x0A: + /* line break hint */ + rt_data[pos] = ' '; + return false; + case 0x0D: + /* end of line */ + rt_data[pos] = '\0'; + return true; + default: + rt_data[pos] = c; + return false; + } +} + +/* handles a group 2 packet, returns true if a complete message was received */ +static bool handle_group2(uint16_t data[4]) +{ + int abflag, segment, version, pos; + bool done; + + /* reset parsing if not in order */ + abflag = (data[1] >> 4) & 1; + segment = data[1] & 0xF; + if ((abflag != rt_abflag) || (segment != rt_segment)) { + rt_abflag = abflag; + rt_segment = 0; + if (segment != 0) { + return false; + } + } + + /* store data */ + version = (data[1] >> 11) & 1; + done = false; + if (version == 0) { + pos = segment * 4; + done = done || handle_rt(pos++, (data[2] >> 8) & 0xFF); + done = done || handle_rt(pos++, (data[2] >> 0) & 0xFF); + done = done || handle_rt(pos++, (data[3] >> 8) & 0xFF); + done = done || handle_rt(pos++, (data[3] >> 0) & 0xFF); + } else { + pos = segment * 2; + done = done || handle_rt(pos++, (data[3] >> 8) & 0xFF); + done = done || handle_rt(pos++, (data[3] >> 0) & 0xFF); + } + if ((++rt_segment == 16) || done) { + rt_data[pos] = '\0'; + strcpy(rt_copy, rt_data); + return true; + } + + return false; +} + +/* processes one rds packet, return value indicates kind of message received */ +enum rds_event rds_process(uint16_t data[4]) +{ + int group; + + /* get programme identification */ + if (pi == 0) { + pi = data[0]; + } + + /* handle rds data based on group */ + group = (data[1] >> 11) & 0x1F; + switch (group) { + + case 0: /* group 0A: basic info */ + case 1: /* group 0B: basic info */ + if (handle_group0(data)) { + return RDS_EVENT_PS; + } + break; + + case 4: /* group 2A: radio text */ + case 5: /* group 2B: radio text */ + if (handle_group2(data)) { + return RDS_EVENT_RT; + } + break; + + default: + break; + } + + return RDS_EVENT_NONE; +} + +/* returns the programme identification code */ +uint16_t rds_get_pi(void) +{ + return pi; +} + +/* returns the most recent valid programme service name */ +char* rds_get_ps(void) +{ + return ps_copy; +} + +/* returns the most recent valid RadioText message */ +char* rds_get_rt(void) +{ + return rt_copy; +} + Property changes on: firmware/drivers/rds.c ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Index: firmware/drivers/tuner/si4700.c =================================================================== --- firmware/drivers/tuner/si4700.c (revision 30912) +++ firmware/drivers/tuner/si4700.c (working copy) @@ -29,23 +29,17 @@ #include "tuner.h" /* tuner abstraction interface */ #include "fmradio.h" #include "fmradio_i2c.h" /* physical interface driver */ +#include "rds.h" +#if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_C200V2) /* some models use the internal 32 kHz oscillator which needs special attention - during initialisation, power-up and power-down. -*/ -#if defined(SANSA_CLIP) || defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_C200V2) -#define USE_INTERNAL_OSCILLATOR + during initialisation, power-up and power-down. */ +#define SI4700_USE_INTERNAL_OSCILLATOR #elif defined(TOSHIBA_GIGABEAT_S) -#define SI4700_GPIO_SETUP (SYSCONFIG1_GPIO1_HI_Z | \ - SYSCONFIG1_GPIO2_HI_Z | \ - SYSCONFIG1_GPIO3_MO_ST_I) -extern int si4700_st(void); +/* gigabeat S uses the GPIO for stereo/mono detection */ +#define SI4700_USE_MO_ST_I #endif -#ifndef SI4700_GPIO_SETUP -#define SI4700_GPIO_SETUP 0 -#endif - #define SEEK_THRESHOLD 0x16 #define I2C_ADR 0x20 @@ -81,7 +75,8 @@ /* CHIPID (0x1) */ -#if 0 /* Informational */ +#if 0 +/* Informational */ /* Si4700/01 */ #define CHIPID_REV (0x3f << 10) #define CHIPID_DEV (0x1 << 9) @@ -98,8 +93,11 @@ /* 1000 before PU = Si4703 */ /* 1001 after PU = Si4703 */ #define CHIPID_FIRMWARE (0x3f << 0) -#endif /* 0 */ +#endif +/* Indicates Si4701/2/3 after powerup */ +#define CHIPID_DEV_0 (0x1 << 9) + /* POWERCFG (0x2) */ #define POWERCFG_DSMUTE (0x1 << 15) #define POWERCFG_DMUTE (0x1 << 14) @@ -214,7 +212,32 @@ static bool tuner_present = false; static uint16_t cache[16]; +static struct mutex fmr_mutex SHAREDBSS_ATTR; +static int rds_event = 0; +static void si4700_mutex_init(void) +{ + /* Have to block multiple init attempts */ + static bool mutex_initialized = false; + + if (!mutex_initialized) { + mutex_initialized = true; + mutex_init(&fmr_mutex); + } +} + +/* Lock or unlock the mutex - can be un-staticed and used externally if + needed */ +static void si4700_mutex_lock(void) +{ + mutex_lock(&fmr_mutex); +} + +static void si4700_mutex_unlock(void) +{ + mutex_unlock(&fmr_mutex); +} + /* reads registers from radio at offset 0x0A into cache */ static void si4700_read(int len) { @@ -277,19 +300,23 @@ si4700_write_reg(reg, cache[reg] & ~mask); } -#if (SI4700_GPIO_SETUP & SYSCONFIG1_GPIO3) != SYSCONFIG1_GPIO3_MO_ST_I +#ifndef SI4700_USE_MO_ST_I /* Poll i2c for the stereo status */ -static inline int si4700_st(void) +bool si4700_st(void) { return (si4700_read_reg(STATUSRSSI) & STATUSRSSI_ST) >> 8; } -#endif +#endif /* ndef SI4700_USE_MO_ST_I */ static void si4700_sleep(int snooze) { if (snooze) { /** power down **/ + if (cache[CHIPID] & CHIPID_DEV_0) { + si4700_rds_powerup(false); + } + /* ENABLE high, DISABLE high */ si4700_write_set(POWERCFG, POWERCFG_DISABLE | POWERCFG_ENABLE); @@ -307,9 +334,8 @@ /* init register cache */ si4700_read(16); -#if SI4700_GPIO_SETUP != 0 - si4700_write_masked(SYSCONFIG1, SI4700_GPIO_SETUP, - SYSCONFIG1_GPIO1 | SYSCONFIG1_GPIO2 | +#ifdef SI4700_USE_MO_ST_I + si4700_write_masked(SYSCONFIG1, SYSCONFIG1_GPIO3_MO_ST_I, SYSCONFIG1_GPIO3); #endif /* set mono->stereo switching RSSI range to lowest setting */ @@ -320,17 +346,55 @@ SYSCONFIG2_SKEETHw(SEEK_THRESHOLD) | SYSCONFIG2_VOLUMEw(0xF), SYSCONFIG2_VOLUME | SYSCONFIG2_SEEKTH); + + /* enable RDS and RDS interrupt if supported (bit 9 of CHIPID) */ + if (cache[CHIPID] & CHIPID_DEV_0) { + /* Is Si4701/2/3 - Enable RDS and interrupt */ + si4700_write_set(SYSCONFIG1, SYSCONFIG1_RDS | SYSCONFIG1_RDSIEN); + si4700_write_masked(SYSCONFIG1, SYSCONFIG1_GPIO2_STC_RDS_I, + SYSCONFIG1_GPIO2); + si4700_rds_powerup(true); + } } } +char * si4700_get_rds_info(int setting) +{ + char *text = NULL; + + switch(setting) + { + case RADIO_RDS_NAME: + text = rds_get_ps(); + break; + + case RADIO_RDS_TEXT: + text = rds_get_rt(); + break; + } + + return text; +} + bool si4700_detect(void) { bool detected; + si4700_mutex_init(); + + si4700_mutex_lock(); + tuner_power(true); + detected = (si4700_read_reg(DEVICEID) == 0x1242); + + if (detected) + tuner_present = true; + tuner_power(false); + si4700_mutex_unlock(); + return detected; } @@ -338,7 +402,7 @@ { /* check device id */ if (si4700_detect()) { - tuner_present = true; + si4700_mutex_lock(); tuner_power(true); @@ -346,7 +410,7 @@ si4700_read(16); si4700_sleep(0); -#ifdef USE_INTERNAL_OSCILLATOR +#ifdef SI4700_USE_INTERNAL_OSCILLATOR /* Enable the internal oscillator (Si4702-16 needs this register to be initialised to 0x100) */ si4700_write_set(TEST1, TEST1_XOSCEN | 0x100); @@ -355,6 +419,10 @@ si4700_sleep(1); tuner_power(false); + + si4700_rds_init(); + + si4700_mutex_unlock(); } } @@ -421,21 +489,29 @@ /* tuner abstraction layer: set something to the tuner */ int si4700_set(int setting, int value) { + int val = 1; + + si4700_mutex_lock(); + switch(setting) { case RADIO_SLEEP: + rds_reset(); if (value != 2) si4700_sleep(value); /* else actually it's 'pause' */ break; case RADIO_FREQUENCY: + rds_reset(); si4700_set_frequency(value); break; case RADIO_SCAN_FREQUENCY: + rds_reset(); si4700_set_frequency(value); - return si4700_tuned(); + val = si4700_tuned(); + break; case RADIO_MUTE: si4700_write_masked(POWERCFG, value ? 0 : POWERCFG_DMUTE, @@ -452,10 +528,13 @@ break; default: - return -1; + val = -1; + break; } - return 1; + si4700_mutex_unlock(); + + return val; } /* tuner abstraction layer: read something from the tuner */ @@ -463,6 +542,8 @@ { int val = -1; /* default for unsupported query */ + si4700_mutex_lock(); + switch(setting) { case RADIO_PRESENT: @@ -488,8 +569,15 @@ case RADIO_RSSI_MAX: val = RSSI_MAX; break; + + case RADIO_EVENT: + val = rds_event; + rds_event = 0; + break; } + si4700_mutex_unlock(); + return val; } @@ -497,10 +585,39 @@ { memset(nfo->regs, 0, sizeof (nfo->regs)); + si4700_mutex_lock(); + if (tuner_powered()) { si4700_read(16); memcpy(nfo->regs, cache, sizeof (nfo->regs)); } + + si4700_mutex_unlock(); } +/* Read raw RDS info for processing */ +bool si4700_rds_read_raw(uint16_t data[4]) +{ + bool retval = false; + + si4700_mutex_lock(); + + if (tuner_powered()) + { + si4700_read_reg(RDSD); + memcpy(data, &cache[RDSA], 4 * sizeof (uint16_t)); + retval = true; + } + + si4700_mutex_unlock(); + + return retval; +} + +/* Set the event flag */ +void si4700_rds_set_event(void) +{ + rds_event = 1; +} +