use core::marker::PhantomData;
use embassy_time::Duration;
use embedded_hal::digital::OutputPin;
use embedded_hal_async::spi::SpiBus;
pub use crate::cmd::cmd_wifi::*;
use super::{BusyPin, Lr1120, Lr1120Error};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct WifiScanParams {
pub chan_mask: u16,
pub standard: WifiStandard,
pub acq_mode: AcqMode,
pub max_res: u8,
pub max_scan: u8,
pub timeout: u16,
pub abort_on_timeout: bool,
}
impl WifiScanParams {
pub fn new(standard: WifiStandard, acq_mode: AcqMode) -> Self {
Self {
chan_mask: 0x3FFF,
standard,
acq_mode,
max_res: 16,
max_scan: 8,
timeout: 105,
abort_on_timeout: true,
}
}
}
trait ResultFromSlice<T> {
fn from_slice(buffer: &[u8]) -> T;
const SIZE : u8;
}
const WIFI_RES_SHORT_SIZE : u8 = 9;
const WIFI_RES_LONG_SIZE : u8 = 22;
const WIFI_RES_EXT_SIZE : u8 = 79;
const WIFI_RES_COUNTRY_SIZE : u8 = 10;
impl ResultFromSlice<WifiReadResultsRsp> for WifiReadResultsRsp {
const SIZE : u8 = WIFI_RES_SHORT_SIZE;
fn from_slice(buffer: &[u8]) -> WifiReadResultsRsp {
WifiReadResultsRsp::from_slice(buffer)
}
}
impl ResultFromSlice<WifiReadLongResultsRsp> for WifiReadLongResultsRsp {
const SIZE : u8 = WIFI_RES_LONG_SIZE;
fn from_slice(buffer: &[u8]) -> WifiReadLongResultsRsp {
WifiReadLongResultsRsp::from_slice(buffer)
}
}
impl ResultFromSlice<WifiReadExtendedResultsRsp> for WifiReadExtendedResultsRsp {
const SIZE : u8 = WIFI_RES_EXT_SIZE;
fn from_slice(buffer: &[u8]) -> WifiReadExtendedResultsRsp {
WifiReadExtendedResultsRsp::from_slice(buffer)
}
}
impl ResultFromSlice<WifiReadCountryCodeResultsRsp> for WifiReadCountryCodeResultsRsp {
const SIZE : u8 = WIFI_RES_COUNTRY_SIZE;
fn from_slice(buffer: &[u8]) -> WifiReadCountryCodeResultsRsp {
WifiReadCountryCodeResultsRsp::from_slice(buffer)
}
}
struct WifiResultsIter<'a, T> {
marker: PhantomData<T>,
buffer: &'a[u8],
index: usize,
max: usize,
}
impl<'a, T: ResultFromSlice<T> > WifiResultsIter<'a, T> {
fn new(buffer: &'a [u8], nb: u8) -> Self {
WifiResultsIter {
marker: PhantomData,
buffer,
index: 0,
max: nb as usize * T::SIZE as usize
}
}
}
impl<'a,T: ResultFromSlice<T>> Iterator for WifiResultsIter<'a,T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index>=self.max {
return None;
}
let next = self.index + T::SIZE as usize;
let v = T::from_slice(&self.buffer[self.index..next]);
self.index = next;
Some(v)
}
}
impl<O,SPI, M> Lr1120<O,SPI, M> where
O: OutputPin, SPI: SpiBus<u8>, M: BusyPin
{
pub async fn wifi_scan(&mut self, params: &WifiScanParams) -> Result<(), Lr1120Error> {
let req = wifi_scan_cmd(params.standard, params.chan_mask, params.acq_mode, params.max_res, params.max_scan, params.timeout, params.abort_on_timeout);
self.cmd_wr(&req).await
}
pub async fn wifi_scan_time_limit(&mut self, params: &WifiScanParams, time_limit: u16) -> Result<(), Lr1120Error> {
let req = wifi_scan_time_limit_cmd(params.standard, params.chan_mask, params.acq_mode, params.max_res, time_limit, params.timeout);
self.cmd_wr(&req).await
}
pub async fn wifi_scan_country_code(&mut self, params: &WifiScanParams) -> Result<(), Lr1120Error> {
let req = wifi_country_code_cmd(params.chan_mask, params.max_res, params.max_scan, params.timeout, params.abort_on_timeout);
self.cmd_wr(&req).await
}
pub async fn wifi_scan_country_code_time_limit(&mut self, params: &WifiScanParams, time_limit: u16) -> Result<(), Lr1120Error> {
let req = wifi_country_code_time_limit_cmd(params.chan_mask, params.max_res, time_limit, params.timeout);
self.cmd_wr(&req).await
}
pub async fn wifi_get_nb_res(&mut self) -> Result<u8, Lr1120Error> {
let req = wifi_get_nb_results_req();
let mut rsp = WifiGetNbResultsRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.nb_results())
}
pub async fn wifi_get_nb_country_code(&mut self) -> Result<u8, Lr1120Error> {
let req = wifi_get_nb_country_code_results_req();
let mut rsp = WifiGetNbCountryCodeResultsRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp.nb_results())
}
pub async fn wifi_reset_timings(&mut self) -> Result<(), Lr1120Error> {
let req = wifi_reset_cumul_timings_cmd();
self.cmd_wr(&req).await
}
pub async fn wifi_get_timings(&mut self) -> Result<WifiReadCumulTimingsRsp, Lr1120Error> {
let req = wifi_read_cumul_timings_req();
let mut rsp = WifiReadCumulTimingsRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok(rsp)
}
pub async fn wifi_set_timestamp_thr(&mut self, threshold: u32) -> Result<(), Lr1120Error> {
let req = wifi_cfg_timestamp_a_pphone_cmd(threshold);
self.cmd_wr(&req).await
}
pub async fn wifi_get_fw_version(&mut self) -> Result<(u8,u8), Lr1120Error> {
let req = wifi_read_version_req();
let mut rsp = WifiReadVersionRsp::new();
self.cmd_rd(&req, rsp.as_mut()).await?;
Ok((rsp.version_major(), rsp.version_minor()))
}
pub async fn wifi_get_result_short(&mut self, index: u8, nb: u8) -> Result<impl Iterator<Item=WifiReadResultsRsp>, Lr1120Error> {
let req = wifi_read_results_req(index, nb, WifiResultFormat::Short);
let nb_byte = nb.min(32) as usize * WIFI_RES_SHORT_SIZE as usize;
self.cmd_wr(&req).await?;
self.wait_ready(Duration::from_millis(100)).await?;
self.rsp_rd(nb_byte).await?;
let iter : WifiResultsIter<'_, WifiReadResultsRsp> = WifiResultsIter::new(&self.buffer()[..nb_byte],nb);
Ok(iter)
}
pub async fn wifi_get_result_long(&mut self, index: u8, nb: u8) -> Result<impl Iterator<Item=WifiReadLongResultsRsp>, Lr1120Error> {
let req = wifi_read_results_req(index, nb, WifiResultFormat::Long);
let nb_byte = nb.min(32) as usize * WIFI_RES_LONG_SIZE as usize;
self.cmd_wr(&req).await?;
self.wait_ready(Duration::from_millis(100)).await?;
self.rsp_rd(nb_byte).await?;
let iter : WifiResultsIter<'_, WifiReadLongResultsRsp> = WifiResultsIter::new(&self.buffer()[..nb_byte],nb);
Ok(iter)
}
pub async fn wifi_get_result_ext(&mut self, index: u8, nb: u8) -> Result<impl Iterator<Item=WifiReadExtendedResultsRsp>, Lr1120Error> {
let req = wifi_read_results_req(index, nb, WifiResultFormat::Long);
let nb_byte = nb.min(12) as usize * WIFI_RES_EXT_SIZE as usize;
self.cmd_wr(&req).await?;
self.wait_ready(Duration::from_millis(100)).await?;
self.rsp_rd(nb_byte).await?;
let iter : WifiResultsIter<'_, WifiReadExtendedResultsRsp> = WifiResultsIter::new(&self.buffer()[..nb_byte],nb);
Ok(iter)
}
pub async fn wifi_get_result_country(&mut self, index: u8, nb: u8) -> Result<impl Iterator<Item=WifiReadCountryCodeResultsRsp>, Lr1120Error> {
let req = wifi_read_country_code_results_req(index, nb);
let nb_byte = nb.min(32) as usize * WIFI_RES_COUNTRY_SIZE as usize;
self.cmd_wr(&req).await?;
self.wait_ready(Duration::from_millis(100)).await?;
self.rsp_rd(nb_byte).await?;
let iter : WifiResultsIter<'_, WifiReadCountryCodeResultsRsp> = WifiResultsIter::new(&self.buffer()[..nb_byte],nb);
Ok(iter)
}
}