#![no_std]
use crate::register_address::{
ConfigBitFlags, Register, RssiBitFlag, StatusRegister, TuningBitFlag, VolumeBitFlag,
VolumeRegister,
};
pub mod register_address;
#[derive(Debug)]
pub enum Error<E> {
I2C(E),
}
const DEVICE_BASE_SEQ_ADDRESS: u8 = 0b10001;
const DEVICE_BASE_RANDOM_ADDRESS: u8 = 0b10001;
const DEVICE_ID: u16 = 0x5804;
#[derive(Debug)]
pub struct Rda5708m<I2C> {
pub(crate) i2c: I2C,
pub(crate) address: u8,
}
impl<I2C, E> Rda5708m<I2C>
where
I2C: embedded_hal::blocking::i2c::Write<Error = E>
+ embedded_hal::blocking::i2c::Read<Error = E>
+ embedded_hal::blocking::i2c::WriteRead<Error = E>,
{
pub fn new<A: Into<Address>>(i2c: I2C, address: A) -> Self {
let a = address.into();
Rda5708m { i2c, address: a.0 }
}
fn write_register(&mut self, register: u8, data: u16) -> Result<(), Error<E>> {
self.i2c
.write(
self.address,
&[register, (data >> 8) as u8, (data & 0xff) as u8],
)
.map_err(Error::I2C)
}
fn read_register(&mut self, register: u8) -> Result<u16, Error<E>> {
let mut data = [0; 2];
self.i2c
.write_read(self.address, &[register], &mut data)
.map_err(Error::I2C)?;
Ok(((data[0] as u16) << 8) | data[1] as u16)
}
fn update_register(
&mut self,
register: u8,
mask: u16,
new_mask_value: u16,
) -> Result<(), Error<E>> {
let data = self.read_register(register)?;
self.update_register_by_old(register, data, mask, new_mask_value)
}
fn update_register_by_old(
&mut self,
register: u8,
old_value: u16,
mask: u16,
new_value: u16,
) -> Result<(), Error<E>> {
let new_mask_value = (new_value & mask) | (old_value & !mask);
self.write_register(register, new_mask_value)
}
pub fn check_id(&mut self) -> Result<bool, Error<E>> {
let id = self.read_register(Register::RDA5807M_REG_CHIPID)?;
Ok(id == DEVICE_ID)
}
pub fn start(&mut self) -> Result<(), Error<E>> {
let config = ConfigBitFlags::DHIZ
| ConfigBitFlags::DMUTE
| ConfigBitFlags::BASS
| ConfigBitFlags::SEEKUP
| ConfigBitFlags::RDS
| ConfigBitFlags::NEW
| ConfigBitFlags::ENABLE;
let tuning = TuningBitFlag::BAND_87_108_MHZ | TuningBitFlag::SPACE_100_KHZ;
self.write_register(Register::RDA5807M_REG_CONFIG, config)?;
self.write_register(Register::RDA5807M_REG_TUNING, tuning)
}
pub fn stop(&mut self) -> Result<(), Error<E>> {
self.write_register(Register::RDA5807M_REG_CONFIG, 0x0)
}
pub fn destroy(self) -> I2C {
self.i2c
}
pub fn set_volume(&mut self, volume: u8) -> Result<(), Error<E>> {
let mut volume = volume;
if volume > 15 {
volume = 15;
}
self.update_register(
Register::RDA5807M_REG_VOLUME,
VolumeBitFlag::VOLUME_MASK,
volume as u16,
)
}
pub fn get_volume(&mut self) -> Result<VolumeRegister, Error<E>> {
let config = self.read_register(Register::RDA5807M_REG_VOLUME)?;
Ok(VolumeRegister::from_u16(config))
}
pub fn mute(&mut self, mute: bool) -> Result<(), Error<E>> {
self.update_register(
Register::RDA5807M_REG_CONFIG,
ConfigBitFlags::DMUTE,
if mute { ConfigBitFlags::DMUTE } else { 0 },
)
}
pub fn set_seek_threshold(&mut self, threshold: u8) -> Result<(), Error<E>> {
self.update_register(
Register::RDA5807M_REG_VOLUME,
VolumeBitFlag::SEEK_TH_MASK,
(threshold as u16) << VolumeBitFlag::SEEK_TH_SHIFT,
)
}
pub fn volume_up(&mut self, wrap: bool) -> Result<(), Error<E>> {
let config = self.read_register(Register::RDA5807M_REG_VOLUME)?;
let volume = config & VolumeBitFlag::VOLUME_MASK;
let mut volume = volume + 1;
if !wrap {
if volume > 15 {
volume = 15;
}
}
self.update_register_by_old(
Register::RDA5807M_REG_VOLUME,
config,
VolumeBitFlag::VOLUME_MASK,
volume,
)
}
pub fn volume_down(&mut self, wrap: bool) -> Result<(), Error<E>> {
let config = self.read_register(Register::RDA5807M_REG_VOLUME)?;
let volume = config & VolumeBitFlag::VOLUME_MASK;
let mut volume = volume - 1;
if !wrap {
if volume > 15 {
volume = 0;
}
}
self.update_register_by_old(
Register::RDA5807M_REG_VOLUME,
config,
VolumeBitFlag::VOLUME_MASK,
volume,
)
}
pub fn seek_up(&mut self, wrap: bool) -> Result<(), Error<E>> {
self.update_register(
Register::RDA5807M_REG_CONFIG,
ConfigBitFlags::SEEKUP | ConfigBitFlags::SEEK | ConfigBitFlags::SKMODE,
ConfigBitFlags::SEEKUP
| ConfigBitFlags::SEEK
| if wrap { 0 } else { ConfigBitFlags::SKMODE },
)
}
pub fn seek_down(&mut self, wrap: bool) -> Result<(), Error<E>> {
self.update_register(
Register::RDA5807M_REG_CONFIG,
ConfigBitFlags::SEEKUP | ConfigBitFlags::SEEK | ConfigBitFlags::SKMODE,
0 | ConfigBitFlags::SEEK | if wrap { 0 } else { ConfigBitFlags::SKMODE },
)
}
pub fn get_rssi(&mut self) -> Result<u8, Error<E>> {
let rssi = self.read_register(Register::RDA5807M_REG_RSSI)?;
Ok(((rssi & RssiBitFlag::RSSI_MASK) >> RssiBitFlag::RSSI_SHIFT) as u8)
}
pub fn get_band_and_spacing(&mut self) -> Result<(u8, u8, u16), Error<E>> {
let config = self.read_register(Register::RDA5807M_REG_TUNING)?;
let band = (config & TuningBitFlag::BAND_MASK) >> TuningBitFlag::BAND_SHIFT;
let spacing = config & TuningBitFlag::SPACE_MASK;
Ok((band as u8, spacing as u8, config))
}
pub fn get_frequency(&mut self) -> Result<u32, Error<E>> {
let (band, spacing, _) = self.get_band_and_spacing()?;
let spacing: u32 = match spacing {
0b00 => 100,
0b01 => 200,
0b10 => 50,
0b11 => 25,
_ => 0,
};
let chan = self.get_status()?.readchan as u32;
let freq = match band {
0b00 => 87_000 + spacing * chan,
0b01 | 0b10 => 76_000 + spacing * chan,
0b11 => 65_000 + spacing * chan,
_ => 0,
};
Ok(freq)
}
pub fn set_frequency(&mut self, freq: u32) -> Result<(), Error<E>> {
let (band, spacing, config) = self.get_band_and_spacing()?;
let spacing: u32 = match spacing {
0b00 => 100,
0b01 => 200,
0b10 => 50,
0b11 => 25,
_ => 0,
};
let chan = match band {
0b00 => (freq - 87_000) / spacing,
0b01 | 0b10 => (freq - 76_000) / spacing,
0b11 => (freq - 65_000) / spacing,
_ => 0,
};
let mask = TuningBitFlag::CHAN_MASK | TuningBitFlag::TUNE;
let new_mask_value = ((chan as u16) << TuningBitFlag::CHAN_SHIFT) | TuningBitFlag::TUNE;
self.update_register_by_old(Register::RDA5807M_REG_TUNING, config, mask, new_mask_value)
}
pub fn get_status(&mut self) -> Result<StatusRegister, Error<E>> {
let status_flag = self.read_register(Register::RDA5807M_REG_STATUS)?;
Ok(StatusRegister::from_u16(status_flag))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Address(pub(crate) u8);
impl Default for Address {
fn default() -> Self {
Address(DEVICE_BASE_RANDOM_ADDRESS)
}
}
impl From<u8> for Address {
fn from(value: u8) -> Self {
Address(value)
}
}
impl Address {
pub fn seq() -> Self {
Address(DEVICE_BASE_SEQ_ADDRESS)
}
}