/* * spreadspace avr utils * * * Copyright (C) 2013 Christian Pointner * Othmar Gsenger * * This file is part of spreadspace avr utils. * * spreadspace avr utils 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 3 of the License, or * any later version. * * spreadspace avr utils is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with spreadspace avr utils. If not, see . */ #include "LUFA/Drivers/Peripheral/TWI.h" #include #include "rda1846.h" #define RDA1846_CHIP_ADDR 0xE2 #define RDA1846_ADDR_W (0<<7) #define RDA1846_ADDR_R (1<<7) #define RDA1846_ADDR_LIMIT 0x7F #define RDA1846_RF_BAND_2M 0x00C0 #define RDA1846_BAND_LOW 134000 #define RDA1846_BAND_HIGH 174000 #define RDA1846_XTAL_FREQ 12288 #define RDA1846_ADCLK_FREQ 6144 #define RDA1846_CLK_MODE (1<<0) #define RDA1846_REG_CLK_MODE 0x04 #define RDA1846_REG_RF_BAND 0x0F #define RDA1846_REG_FREQH 0x29 #define RDA1846_REG_FREQL 0x2A #define RDA1846_REG_XTAL 0x2B #define RDA1846_REG_ADCLK 0x2C static uint8_t rda1846_write_register_raw(const uint8_t addr, const uint16_t data) { if(TWI_StartTransmission(RDA1846_CHIP_ADDR | TWI_ADDRESS_WRITE,10) != TWI_ERROR_NoError) return 1; if(!TWI_SendByte(addr | RDA1846_ADDR_W)) goto i2c_error; if(!TWI_SendByte((uint8_t)(data>>8))) goto i2c_error; if(!TWI_SendByte((uint8_t)data)) goto i2c_error; TWI_StopTransmission(); return 0; i2c_error: TWI_StopTransmission(); return 1; } static uint8_t rda1846_read_register_raw(const uint8_t addr, uint16_t* data) { if(TWI_StartTransmission(RDA1846_CHIP_ADDR | TWI_ADDRESS_WRITE,10) != TWI_ERROR_NoError) return 1; if(!TWI_SendByte(addr | RDA1846_ADDR_R)) goto i2c_error; if(TWI_StartTransmission(RDA1846_CHIP_ADDR | TWI_ADDRESS_READ,10) != TWI_ERROR_NoError) goto i2c_error; uint8_t tmp; if(!TWI_ReceiveByte(&tmp, 0)) goto i2c_error; *data = tmp << 8; if(!TWI_ReceiveByte(&tmp, 1)) goto i2c_error; *data |= tmp; TWI_StopTransmission(); return 0; i2c_error: TWI_StopTransmission(); return 1; } static uint8_t rda1846_write_register(const uint8_t addr, const uint16_t data) { if(addr < RDA1846_ADDR_LIMIT) return rda1846_write_register_raw(addr, data); if(addr > RDA1846_ADDR_LIMIT) { uint8_t ret = rda1846_write_register_raw(RDA1846_ADDR_LIMIT, 1); if(ret) return ret; ret = rda1846_write_register_raw(addr, data); if(ret) return ret; return rda1846_write_register_raw(RDA1846_ADDR_LIMIT, 0); } return 1; } static uint8_t rda1846_read_register(const uint8_t addr, uint16_t* data) { if(addr < RDA1846_ADDR_LIMIT) return rda1846_read_register_raw(addr, data); if(addr > RDA1846_ADDR_LIMIT) { uint8_t ret = rda1846_write_register_raw(RDA1846_ADDR_LIMIT, 1); if(ret) return ret; ret = rda1846_read_register_raw(addr - RDA1846_ADDR_LIMIT + 1, data); if(ret) return ret; return rda1846_write_register_raw(RDA1846_ADDR_LIMIT, 0); } return 1; } void rda1846_init(void) { TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000)); // switch to 2m Band (134 ~ 174 MHz) rda1846_write_register(RDA1846_REG_RF_BAND, RDA1846_RF_BAND_2M); // set crystal frequency (12.288 MHz) rda1846_write_register(RDA1846_REG_XTAL, RDA1846_XTAL_FREQ); rda1846_write_register(RDA1846_REG_ADCLK, RDA1846_ADCLK_FREQ); rda1846_write_register(RDA1846_REG_CLK_MODE, RDA1846_CLK_MODE); } int32_t rda1846_get_freq_kHz(void) { int32_t freq; uint16_t data; uint8_t ret = rda1846_read_register(RDA1846_REG_FREQH, &data); if(ret) return -1; freq = (((uint32_t)data)<<16); ret = rda1846_read_register(RDA1846_REG_FREQL, &data); if(ret) return -1; freq |= data; return (freq>>3); } uint8_t rda1846_set_freq_kHz(int32_t freq) { if(freq < RDA1846_BAND_LOW || freq > RDA1846_BAND_HIGH) return 1; freq = freq<<3; uint8_t ret = rda1846_write_register(RDA1846_REG_FREQH, (uint16_t)(freq>>16)); if(ret) return 1; return rda1846_write_register(RDA1846_REG_FREQL, (uint16_t)(freq & 0x0000FFFF)); }