#include #include #include #include #include #include #include void udelay(void) { #define _DELAY 100 for (int i = 0; i < (_DELAY); i++) { __asm("nop"); } } typedef struct { uint8_t status; } radio_t; radio_t radio; uint8_t radio_get_status(void) { return radio.status; } #define RX_I2CADDR 0xC6 #define I2CADDR_WRITE_BIT 0 #define CMD_POWER_UP 0x01 #define CMD_GET_REV 0x10 #define CMD_POWER_DOWN 0x11 #define CMD_SET_PROP 0x12 #define CMD_GET_PROP 0x13 #define CMD_GET_INTSTAT 0x14 #define CMD_AM_TUNE_FREQ 0x40 #define CMD_FM_TUNE_FREQ 0x20 #define POWERUP_CTSIEN_BIT 7 #define POWERUP_GPO2OEN_BIT 6 #define POWERUP_PATCH_BIT 5 #define POWERUP_XOSCEN_BIT 4 #define POWERUP_FMRDS 0x00 #define POWERUP_AMSWLW 0x01 #define POWERUP_ANALOG 0x05 #define INT_CTS_BIT 7 #define INT_ERR_BIT 6 #define INT_RDSINT_BIT 2 #define INT_ASQINT_BIT 1 #define INT_STCIN_BIT 0 #define STATUS_CTS_BIT 7 #define STATUS_ERR_BIT 6 #define STATUS_RSQINT_BIT 3 #define STATUS_RDSINT_BIT 2 #define STATUS_STCINT_BIT 0 #define PROP_RX_VOLUME 0x4000 #define PROP_RX_HARD_MUTE 0x4001 #define PROP_HMUTE_L_BIT 1 #define PROP_HMUTE_R_BIT 0 #define HI_BYTE(word) (((word) >> 8) & 0xFF) #define LO_BYTE(word) (((word) >> 0) & 0xFF) #define RST_PIN PB4 uint8_t radio_read_cts(void) { uint8_t cts = 0; uint8_t rcount = 20; i2c_start(); i2c_write(RX_I2CADDR); i2c_write(CMD_GET_INTSTAT); i2c_restart(); i2c_write(RX_I2CADDR | BIT(I2CADDR_WRITE_BIT)); for (uint8_t i = 0; i < rcount; i++) { cts = i2c_read_ack(); if ((cts &= BIT(STATUS_CTS_BIT)) != 0) { break; } } i2c_read_nack(); i2c_stop(); return cts; } void radio_wait_cts(void) { uint8_t cts = 0; while ((cts &= BIT(STATUS_CTS_BIT)) == 0) { cts = radio_read_cts(); } } void radio_powerup_fmrds(void) { i2c_start(); i2c_write(RX_I2CADDR); i2c_write(CMD_POWER_UP); i2c_write(POWERUP_FMRDS | BIT(POWERUP_XOSCEN_BIT) | BIT(POWERUP_CTSIEN_BIT)); i2c_write(POWERUP_ANALOG); i2c_stop(); _delay_ms(300); } void radio_set_fm_freq(uint16_t freq) { i2c_start(); i2c_write(RX_I2CADDR); i2c_write(CMD_FM_TUNE_FREQ); i2c_write(0x01); i2c_write(HI_BYTE(freq)); i2c_write(LO_BYTE(freq)); i2c_write(0); #if 0 uint8_t cts = 0x00; i2c_restart(); i2c_write(RX_I2CADDR | BIT(I2CADDR_WRITE_BIT)); while (cts == 0) { cts = i2c_read_ack(); cts &= BIT(STATUS_CTS_BIT); } i2c_read_nack(); #endif i2c_stop(); } void radio_set_rx_volume(uint8_t volume) { i2c_start(); i2c_write(RX_I2CADDR); i2c_write(CMD_SET_PROP); i2c_write(0x00); i2c_write(HI_BYTE(PROP_RX_VOLUME)); i2c_write(LO_BYTE(PROP_RX_VOLUME)); i2c_write(0x00); i2c_write(volume); i2c_stop(); } void radio_set_rx_mute(void) { i2c_start(); i2c_write(RX_I2CADDR); i2c_write(CMD_SET_PROP); i2c_write(0x00); i2c_write(HI_BYTE(PROP_RX_HARD_MUTE)); i2c_write(LO_BYTE(PROP_RX_HARD_MUTE)); i2c_write(0x00); i2c_write(BIT(PROP_HMUTE_L_BIT)); i2c_stop(); } uint16_t radio_get_rev(void) { uint16_t rev = 0x0000; //i2c_write(CMD_GET_REV); //i2c_restart(); //i2c_write(RX_I2CADDR | 0x01); //radio.status = i2c_read_ack(); //i2c_read_ack(); //i2c_read_ack(); //i2c_read_ack(); //i2c_read_ack(); //i2c_read_ack(); //i2c_read_ack(); //i2c_read_ack(); //i2c_read_nack(); //i2c_stop(); return rev; } void radio_hw_reset(void) { REG_SETUP_BIT(DDRB, RST_PIN); REG_SETDOWN_BIT(PORTB, RST_PIN); _delay_ms(10); REG_SETUP_BIT(PORTB, RST_PIN); _delay_ms(10); } void radio_init(void) { radio.status = 0; radio_hw_reset(); radio_powerup_fmrds(); radio_wait_cts(); uint16_t freq = 10010; radio_set_fm_freq(freq); radio_wait_cts(); radio_set_rx_mute(); radio_wait_cts(); uint8_t volume = 38; radio_set_rx_volume(volume); radio_wait_cts(); return; }