208 lines
4.1 KiB
C
208 lines
4.1 KiB
C
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <util/delay.h>
|
|
|
|
#include <tool.h>
|
|
#include <i2c.h>
|
|
#include <radio.h>
|
|
|
|
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;
|
|
}
|
|
|