static void si4700_set_frequency(int freq) { static const unsigned int spacings[3] = { 200000, /* SYSCONFIG2_SPACE_200KHZ */ 100000, /* SYSCONFIG2_SPACE_100KHZ */ 50000, /* SYSCONFIG2_SPACE_50KHZ */ }; static const unsigned int bands[3] = { 87500000, /* SYSCONFIG2_BAND_875_1080 */ 76000000, /* SYSCONFIG2_BAND_760_1080 */ 76000000, /* SYSCONFIG2_BAND_760_900 */ }; /* check BAND and spacings */ int space = SYSCONFIG2_SPACEr(cache[SYSCONFIG2]); int band = SYSCONFIG2_BANDr(cache[SYSCONFIG2]); int chan = (freq - bands[band]) / spacings[space]; int readchan; do { /* tuning should be done within 60 ms according to the datasheet */ si4700_write_reg(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE); sleep(HZ * 60 / 1000); /* get tune result */ readchan = si4700_read_reg(READCHAN) & READCHAN_READCHAN; si4700_write_clear(CHANNEL, CHANNEL_TUNE); } while (!((cache[STATUSRSSI] & STATUSRSSI_STC) && (readchan == chan))); }
bool si4700_detect(void) { if (!tuner_present) { tuner_power(true); tuner_present = (si4700_read_reg(DEVICEID) == 0x1242); tuner_power(false); } return tuner_present; }
static int si4700_tuned(void) { /* Primitive tuning check: sufficient level and AFC not railed */ uint16_t status = si4700_read_reg(STATUSRSSI); if (STATUSRSSI_RSSIr(status) >= SEEK_THRESHOLD && (status & STATUSRSSI_AFCRL) == 0) return 1; return 0; }
bool si4700_detect(void) { bool detected; tuner_power(true); detected = (si4700_read_reg(DEVICEID) == 0x1242); tuner_power(false); return detected; }
/* tuner abstraction layer: read something from the tuner */ int si4700_get(int setting) { int val = -1; /* default for unsupported query */ if(!tuner_powered() && setting != RADIO_PRESENT) return -1; mutex_lock(&fmr_mutex); switch(setting) { case RADIO_PRESENT: val = tuner_present; break; case RADIO_TUNED: val = si4700_tuned(); break; case RADIO_STEREO: val = si4700_st(); break; case RADIO_RSSI: val = STATUSRSSI_RSSIr(si4700_read_reg(STATUSRSSI)); break; case RADIO_RSSI_MIN: val = RSSI_MIN; break; case RADIO_RSSI_MAX: val = RSSI_MAX; break; #ifdef HAVE_RDS_CAP case RADIO_EVENT: { #ifdef RDS_ISR_PROCESSING int oldlevel = disable_irq_save(); #endif val = rds_event; rds_event = 0; #ifdef RDS_ISR_PROCESSING restore_irq(oldlevel); #endif break; } #endif } mutex_unlock(&fmr_mutex); return val; }
/* Read raw RDS info for processing */ bool si4700_rds_read_raw(uint16_t data[4]) { bool retval = false; mutex_lock(&fmr_mutex); if (tuner_powered()) { si4700_read_reg(RDSD); memcpy(data, &cache[RDSA], 4 * sizeof (uint16_t)); retval = true; } mutex_unlock(&fmr_mutex); return retval; }
/* Poll i2c for the stereo status */ bool si4700_st(void) { return (si4700_read_reg(STATUSRSSI) & STATUSRSSI_ST) >> 8; }
/* Poll i2c for the stereo status */ static inline int si4700_st(void) { return (si4700_read_reg(STATUSRSSI) & STATUSRSSI_ST) >> 8; }