use crate::status::{Status,Intr};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HwType {
Lr1110 = 1,
Lr1120 = 2,
Lr1121 = 3,
Bootloader = 223,
}
impl From<u8> for HwType {
fn from(value: u8) -> Self {
match value {
223 => HwType::Bootloader,
3 => HwType::Lr1121,
2 => HwType::Lr1120,
_ => HwType::Lr1110,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum LfClock {
Rc = 0,
Xtal = 1,
Dio11 = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TcxoVoltage {
Tcxo1v6 = 0,
Tcxo1v7 = 1,
Tcxo1v8 = 2,
Tcxo2v2 = 3,
Tcxo2v4 = 4,
Tcxo2v7 = 5,
Tcxo3v0 = 6,
Tcxo3v3 = 7,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum StayInBootloader {
SoftwareRestart = 0,
BootloaderMode = 3,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum StandbyMode {
Rc = 0,
Xosc = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum RegMode {
LdoOnly = 0,
DcdcEnabled = 1,
}
pub fn get_status_req() -> [u8; 2] {
[0x01, 0x00]
}
pub fn get_errors_req() -> [u8; 2] {
[0x01, 0x0D]
}
pub fn clear_errors_cmd() -> [u8; 2] {
[0x01, 0x0E]
}
pub fn write_buffer8_cmd() -> [u8; 2] {
[0x01, 0x09]
}
pub fn read_buffer8_cmd(offset: u8, len: u8) -> [u8; 4] {
let mut cmd = [0u8; 4];
cmd[0] = 0x01;
cmd[1] = 0x0A;
cmd[2] |= offset;
cmd[3] |= len;
cmd
}
pub fn clear_rx_buffer_cmd() -> [u8; 2] {
[0x01, 0x0B]
}
pub fn get_random_number_req() -> [u8; 2] {
[0x01, 0x20]
}
pub fn enable_spi_crc_cmd(enable: u8, crc: u8) -> [u8; 4] {
let mut cmd = [0u8; 4];
cmd[0] = 0x01;
cmd[1] = 0x28;
cmd[2] |= enable;
cmd[3] |= crc;
cmd
}
pub fn get_version_req() -> [u8; 2] {
[0x01, 0x01]
}
pub fn calibrate_cmd(lf_rc: bool, hf_rc: bool, pll: bool, adc: bool, img: bool, pll_tx: bool) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x01;
cmd[1] = 0x0F;
if lf_rc { cmd[2] |= 1; }
if hf_rc { cmd[2] |= 2; }
if pll { cmd[2] |= 4; }
if adc { cmd[2] |= 8; }
if img { cmd[2] |= 16; }
if pll_tx { cmd[2] |= 32; }
cmd
}
pub fn calib_image_cmd(freq1: u8, freq2: u8) -> [u8; 4] {
let mut cmd = [0u8; 4];
cmd[0] = 0x01;
cmd[1] = 0x11;
cmd[2] |= freq1;
cmd[3] |= freq2;
cmd
}
pub fn config_lf_clock_cmd(lf_clock: LfClock, busy_release: bool) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x01;
cmd[1] = 0x16;
cmd[2] |= (lf_clock as u8) & 0x3;
if busy_release { cmd[2] |= 4; }
cmd
}
pub fn set_tcxo_mode_cmd(tcxo_voltage: TcxoVoltage, delay: u32) -> [u8; 6] {
let mut cmd = [0u8; 6];
cmd[0] = 0x01;
cmd[1] = 0x17;
cmd[2] |= tcxo_voltage as u8;
cmd[3] |= ((delay >> 16) & 0xFF) as u8;
cmd[4] |= ((delay >> 8) & 0xFF) as u8;
cmd[5] |= (delay & 0xFF) as u8;
cmd
}
pub fn reboot_cmd(stay_in_bootloader: StayInBootloader) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x01;
cmd[1] = 0x18;
cmd[2] |= stay_in_bootloader as u8;
cmd
}
pub fn set_sleep_cmd(wakeup_rtc: bool, ret_en: bool, sleep_time: u32) -> [u8; 7] {
let mut cmd = [0u8; 7];
cmd[0] = 0x01;
cmd[1] = 0x1B;
if wakeup_rtc { cmd[2] |= 2; }
if ret_en { cmd[2] |= 1; }
cmd[3] |= ((sleep_time >> 24) & 0xFF) as u8;
cmd[4] |= ((sleep_time >> 16) & 0xFF) as u8;
cmd[5] |= ((sleep_time >> 8) & 0xFF) as u8;
cmd[6] |= (sleep_time & 0xFF) as u8;
cmd
}
pub fn set_standby_cmd(standby_mode: StandbyMode) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x01;
cmd[1] = 0x1C;
cmd[2] |= standby_mode as u8;
cmd
}
pub fn set_fs_cmd() -> [u8; 2] {
[0x01, 0x1D]
}
pub fn set_dio_irq_params_cmd(irq1_to_enable: u32, irq2_to_enable: u32) -> [u8; 10] {
let mut cmd = [0u8; 10];
cmd[0] = 0x01;
cmd[1] = 0x13;
cmd[2] |= ((irq1_to_enable >> 24) & 0xFF) as u8;
cmd[3] |= ((irq1_to_enable >> 16) & 0xFF) as u8;
cmd[4] |= ((irq1_to_enable >> 8) & 0xFF) as u8;
cmd[5] |= (irq1_to_enable & 0xFF) as u8;
cmd[6] |= ((irq2_to_enable >> 24) & 0xFF) as u8;
cmd[7] |= ((irq2_to_enable >> 16) & 0xFF) as u8;
cmd[8] |= ((irq2_to_enable >> 8) & 0xFF) as u8;
cmd[9] |= (irq2_to_enable & 0xFF) as u8;
cmd
}
pub fn clear_irq_cmd(irq_to_clear: u32) -> [u8; 6] {
let mut cmd = [0u8; 6];
cmd[0] = 0x01;
cmd[1] = 0x14;
cmd[2] |= ((irq_to_clear >> 24) & 0xFF) as u8;
cmd[3] |= ((irq_to_clear >> 16) & 0xFF) as u8;
cmd[4] |= ((irq_to_clear >> 8) & 0xFF) as u8;
cmd[5] |= (irq_to_clear & 0xFF) as u8;
cmd
}
#[allow(clippy::too_many_arguments)]
pub fn set_dio_as_rf_switch_cmd(rfsw_enable: u8, rfsw_stby_cfg: u8, rfsw_rx_cfg: u8, rfsw_tx_cfg: u8, rfsw_tx_hp_cfg: u8, rfsw_tx_hf_cfg: u8, rfsw_gnss_cfg: u8, rfsw_wifi_cfg: u8) -> [u8; 10] {
let mut cmd = [0u8; 10];
cmd[0] = 0x01;
cmd[1] = 0x12;
cmd[2] |= rfsw_enable;
cmd[3] |= rfsw_stby_cfg;
cmd[4] |= rfsw_rx_cfg;
cmd[5] |= rfsw_tx_cfg;
cmd[6] |= rfsw_tx_hp_cfg;
cmd[7] |= rfsw_tx_hf_cfg;
cmd[8] |= rfsw_gnss_cfg;
cmd[9] |= rfsw_wifi_cfg;
cmd
}
pub fn drive_dios_in_sleep_mode_cmd(enable: u8) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x01;
cmd[1] = 0x2A;
cmd[2] |= enable;
cmd
}
pub fn get_temp_req() -> [u8; 2] {
[0x01, 0x1A]
}
pub fn set_reg_mode_cmd(reg_mode: RegMode) -> [u8; 3] {
let mut cmd = [0u8; 3];
cmd[0] = 0x01;
cmd[1] = 0x10;
cmd[2] |= reg_mode as u8;
cmd
}
pub fn get_vbat_req() -> [u8; 2] {
[0x01, 0x19]
}
pub fn get_chip_eui_req() -> [u8; 2] {
[0x01, 0x25]
}
pub fn get_semtech_join_eui_req() -> [u8; 2] {
[0x01, 0x26]
}
#[derive(Default)]
pub struct StatusRsp([u8; 6]);
impl StatusRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
Status::from_array([self.0[0], self.0[1]])
}
pub fn intr(&self) -> Intr {
Intr::from_slice(&self.0[2..6])
}
}
impl AsMut<[u8]> for StatusRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct ErrorsRsp([u8; 3]);
impl ErrorsRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn lf_rc_calib(&self) -> bool {
self.0[1] & 0x1 != 0
}
pub fn hf_rc_calib(&self) -> bool {
(self.0[1] >> 1) & 0x1 != 0
}
pub fn adc_calib(&self) -> bool {
(self.0[1] >> 2) & 0x1 != 0
}
pub fn pll_calib(&self) -> bool {
(self.0[1] >> 3) & 0x1 != 0
}
pub fn img_calib(&self) -> bool {
(self.0[1] >> 4) & 0x1 != 0
}
pub fn hf_xosc_start(&self) -> bool {
(self.0[1] >> 5) & 0x1 != 0
}
pub fn lf_xosc_start(&self) -> bool {
(self.0[1] >> 6) & 0x1 != 0
}
pub fn pll_lock(&self) -> bool {
(self.0[1] >> 7) & 0x1 != 0
}
pub fn rx_adc_offset(&self) -> bool {
self.0[2] & 0x1 != 0
}
pub fn value(&self) -> u16 {
u16::from_be_bytes([self.0[1], self.0[2]])
}
pub fn none(&self) -> bool {
self.0[1] == 0 && self.0[2] == 0
}
}
impl AsMut<[u8]> for ErrorsRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for ErrorsRsp {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "Errors: ");
if self.none() {
defmt::write!(f, "None");
return;
}
if self.lf_rc_calib() {defmt::write!(f, "LfRcCalib ")};
if self.hf_rc_calib() {defmt::write!(f, "HfRcCalib ")};
if self.adc_calib() {defmt::write!(f, "AdcCalib ")};
if self.pll_calib() {defmt::write!(f, "PllCalib ")};
if self.img_calib() {defmt::write!(f, "ImgCalib ")};
if self.hf_xosc_start() {defmt::write!(f, "HfXoscStart ")};
if self.lf_xosc_start() {defmt::write!(f, "LfXoscStart ")};
if self.pll_lock() {defmt::write!(f, "PllLock ")};
if self.rx_adc_offset() {defmt::write!(f, "RxAdcOffset ")};
}
}
#[derive(Default)]
pub struct RandomNumberRsp([u8; 5]);
impl RandomNumberRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn random_number(&self) -> u32 {
(self.0[4] as u32) |
((self.0[3] as u32) << 8) |
((self.0[2] as u32) << 16) |
((self.0[1] as u32) << 24)
}
}
impl AsMut<[u8]> for RandomNumberRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct VersionRsp([u8; 5]);
impl VersionRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn hw_version(&self) -> u8 {
self.0[1]
}
pub fn hw_type(&self) -> HwType {
self.0[2].into()
}
pub fn major(&self) -> u8 {
self.0[3]
}
pub fn minor(&self) -> u8 {
self.0[4]
}
}
impl AsMut<[u8]> for VersionRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for VersionRsp {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}.{:02x}", self.major(), self.minor());
}
}
#[derive(Default)]
pub struct TempRsp([u8; 3]);
impl TempRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn temp(&self) -> u16 {
(self.0[2] as u16) |
((self.0[1] as u16) << 8)
}
}
impl AsMut<[u8]> for TempRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct VbatRsp([u8; 2]);
impl VbatRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn vbat(&self) -> u8 {
self.0[1]
}
}
impl AsMut<[u8]> for VbatRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct ChipEuiRsp([u8; 9]);
impl ChipEuiRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn chip_eui(&self) -> u64 {
(self.0[8] as u64) |
((self.0[7] as u64) << 8) |
((self.0[6] as u64) << 16) |
((self.0[5] as u64) << 24) |
((self.0[4] as u64) << 32) |
((self.0[3] as u64) << 40) |
((self.0[2] as u64) << 48) |
((self.0[1] as u64) << 56)
}
}
impl AsMut<[u8]> for ChipEuiRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
#[derive(Default)]
pub struct SemtechJoinEuiRsp([u8; 9]);
impl SemtechJoinEuiRsp {
pub fn new() -> Self {
Self::default()
}
pub fn status(&mut self) -> Status {
self.0[0].into()
}
pub fn semtech_join_eui(&self) -> u64 {
(self.0[8] as u64) |
((self.0[7] as u64) << 8) |
((self.0[6] as u64) << 16) |
((self.0[5] as u64) << 24) |
((self.0[4] as u64) << 32) |
((self.0[3] as u64) << 40) |
((self.0[2] as u64) << 48) |
((self.0[1] as u64) << 56)
}
}
impl AsMut<[u8]> for SemtechJoinEuiRsp {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}