Files
ats20/radio.c
Олег Бородин e32ff92716 fmrds 2
2025-02-02 21:12:33 +02:00

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;
}