Skip to content

Commit

Permalink
extend PhyRxTx to handle antenna gain and max pow
Browse files Browse the repository at this point in the history
  • Loading branch information
lthiery committed Nov 6, 2023
1 parent a5d1824 commit b3415fb
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 13 deletions.
17 changes: 12 additions & 5 deletions device/src/async_device/lora_radio.rs
Expand Up @@ -6,16 +6,19 @@ use lora_phy::mod_params::{BoardType, ChipType, RadioError};
use lora_phy::mod_traits::RadioKind;
use lora_phy::{DelayUs, LoRa};

/// LoRa radio using the physical layer API in the external lora-phy crate
pub struct LoRaRadio<RK, DLY>
/// LoRa radio using the physical layer API in the external lora-phy crate.
///
/// The const generic P is the max power the radio may be instructed to transmit at. The const
/// generic G is the antenna gain and board loss in dBi.
pub struct LoRaRadio<RK, DLY, const P: u8, const G: i8 = 0>
where
RK: RadioKind,
DLY: DelayUs,
{
pub(crate) lora: LoRa<RK, DLY>,
rx_pkt_params: Option<lora_phy::mod_params::PacketParams>,
}
impl<RK, DLY> LoRaRadio<RK, DLY>
impl<RK, DLY, const G: i8, const P: u8> LoRaRadio<RK, DLY, P, G>
where
RK: RadioKind,
DLY: DelayUs,
Expand All @@ -26,7 +29,7 @@ where
}

/// Provide the timing values for boards supported by the external lora-phy crate
impl<RK, DLY> Timings for LoRaRadio<RK, DLY>
impl<RK, DLY, const P: u8, const G: i8> Timings for LoRaRadio<RK, DLY, P, G>
where
RK: RadioKind,
DLY: DelayUs,
Expand Down Expand Up @@ -63,13 +66,17 @@ impl From<RadioError> for Error {

/// Provide the LoRa physical layer rx/tx interface for boards supported by the external lora-phy
/// crate
impl<RK, DLY> PhyRxTx for LoRaRadio<RK, DLY>
impl<RK, DLY, const P: u8, const G: i8> PhyRxTx for LoRaRadio<RK, DLY, P, G>
where
RK: RadioKind,
DLY: DelayUs,
{
type PhyError = Error;

const ANTENNA_GAIN: i8 = G;

const MAX_RADIO_POWER: u8 = P;

async fn tx(&mut self, config: TxConfig, buffer: &[u8]) -> Result<u32, Self::PhyError> {
let mdltn_params = self.lora.create_modulation_params(
config.rf.bb.sf,
Expand Down
8 changes: 6 additions & 2 deletions device/src/async_device/mod.rs
Expand Up @@ -195,12 +195,14 @@ where
pub async fn join(&mut self, join_mode: &JoinMode) -> Result<JoinResponse, Error<R::PhyError>> {
match join_mode {
JoinMode::OTAA { deveui, appeui, appkey } => {
let (tx_config, _) = self.mac.join_otaa::<C, G, N>(
let (mut tx_config, _) = self.mac.join_otaa::<C, G, N>(
&mut self.rng,
NetworkCredentials::new(*appeui, *deveui, *appkey),
&mut self.radio_buffer,
);

tx_config.adjust_power(R::ANTENNA_GAIN, R::MAX_RADIO_POWER);

// Transmit the join payload
let ms = self
.radio
Expand Down Expand Up @@ -233,11 +235,13 @@ where
confirmed: bool,
) -> Result<SendResponse, Error<R::PhyError>> {
// Prepare transmission buffer
let (tx_config, _fcnt_up) = self.mac.send::<C, G, N>(
let (mut tx_config, _fcnt_up) = self.mac.send::<C, G, N>(
&mut self.rng,
&mut self.radio_buffer,
&SendData { data, fport, confirmed },
)?;
tx_config.adjust_power(R::ANTENNA_GAIN, R::MAX_RADIO_POWER);

// Transmit our data packet
let ms = self
.radio
Expand Down
7 changes: 7 additions & 0 deletions device/src/async_device/radio.rs
Expand Up @@ -29,6 +29,13 @@ pub trait PhyRxTx: Sized {
#[cfg(not(feature = "defmt"))]
type PhyError;

/// The antenna gain and board loss in dBi.
const ANTENNA_GAIN: i8 = 0;

/// The max power the radio can be instructed to transmit at. When preparing an instruction
/// for the radio, this max power will be used an upper bound.
const MAX_RADIO_POWER: u8;

/// Transmit data buffer with the given transceiver configuration. The returned future
/// should only complete once data have been transmitted.
async fn tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, Self::PhyError>;
Expand Down
3 changes: 3 additions & 0 deletions device/src/async_device/test/radio.rs
Expand Up @@ -31,6 +31,9 @@ pub struct TestRadio {
impl PhyRxTx for TestRadio {
type PhyError = &'static str;

const ANTENNA_GAIN: i8 = 0;
const MAX_RADIO_POWER: u8 = 26;

async fn tx(&mut self, config: TxConfig, buffer: &[u8]) -> Result<u32, Self::PhyError> {
let length = buffer.len();
// stash the uplink, to be consumed by channel or by rx handler
Expand Down
4 changes: 2 additions & 2 deletions device/src/nb_device/mod.rs
Expand Up @@ -13,7 +13,7 @@ type TimestampMs = u32;

pub struct Device<R, C, RNG, const N: usize>
where
R: radio::PhyRxTx + Timings,
R: PhyRxTx + Timings,
C: CryptoFactory + Default,
RNG: RngCore,
{
Expand Down Expand Up @@ -108,7 +108,7 @@ where
}
}

pub(crate) struct Shared<R: radio::PhyRxTx + Timings, RNG: RngCore, const N: usize> {
pub(crate) struct Shared<R: PhyRxTx + Timings, RNG: RngCore, const N: usize> {
pub(crate) radio: R,
pub(crate) rng: RNG,
pub(crate) tx_buffer: RadioBuffer<N>,
Expand Down
7 changes: 7 additions & 0 deletions device/src/nb_device/radio.rs
Expand Up @@ -33,6 +33,13 @@ pub trait PhyRxTx {
type PhyError: fmt::Debug;
type PhyResponse: fmt::Debug;

/// The antenna gain and board loss in dBi.
const ANTENNA_GAIN: i8 = 0;

/// The max power the radio can be instructed to transmit at. When preparing an instruction
/// for the radio, this max power will be used an upper bound.
const MAX_RADIO_POWER: u8;

fn get_mut_radio(&mut self) -> &mut Self;

// we require mutability so we may decrypt in place
Expand Down
10 changes: 6 additions & 4 deletions device/src/nb_device/state.rs
Expand Up @@ -149,18 +149,20 @@ impl Idle {
let response = match event {
// tolerate unexpected timeout
Event::Join(creds) => {
let (tx_config, dev_nonce) = mac.join_otaa::<C, RNG, N>(rng, creds, buf);
let (mut tx_config, dev_nonce) = mac.join_otaa::<C, RNG, N>(rng, creds, buf);
tx_config.adjust_power(R::ANTENNA_GAIN, R::MAX_RADIO_POWER);
IntermediateResponse::RadioTx((Frame::Join, tx_config, dev_nonce as u32))
}
Event::TimeoutFired => IntermediateResponse::EarlyReturn(Ok(Response::NoUpdate)),
Event::RadioEvent(_radio_event) => {
IntermediateResponse::EarlyReturn(Err(Error::RadioEventWhileIdle.into()))
}
Event::SendDataRequest(send_data) => {
let tx_config = mac.send::<C, RNG, N>(rng, buf, &send_data);
match tx_config {
let result = mac.send::<C, RNG, N>(rng, buf, &send_data);
match result {
Err(e) => IntermediateResponse::EarlyReturn(Err(e.into())),
Ok((tx_config, fcnt_up)) => {
Ok((mut tx_config, fcnt_up)) => {
tx_config.adjust_power(R::ANTENNA_GAIN, R::MAX_RADIO_POWER);
IntermediateResponse::RadioTx((Frame::Data, tx_config, fcnt_up))
}
}
Expand Down
3 changes: 3 additions & 0 deletions device/src/nb_device/test/util.rs
Expand Up @@ -45,6 +45,9 @@ impl PhyRxTx for TestRadio {
type PhyError = &'static str;
type PhyResponse = ();

const ANTENNA_GAIN: i8 = 0;
const MAX_RADIO_POWER: u8 = 26;

fn get_mut_radio(&mut self) -> &mut Self {
self
}
Expand Down
7 changes: 7 additions & 0 deletions device/src/radio.rs
Expand Up @@ -14,6 +14,13 @@ pub struct TxConfig {
pub rf: RfConfig,
}

impl TxConfig {
pub fn adjust_power(&mut self, antenna_gain: i8, max_power: u8) {
self.pw -= antenna_gain;
self.pw = core::cmp::min(self.pw, max_power as i8);
}
}

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RxQuality {
Expand Down
1 change: 1 addition & 0 deletions device/src/region/fixed_channel_plans/mod.rs
Expand Up @@ -58,6 +58,7 @@ impl<const D: usize, F: FixedChannelRegion<D>> FixedChannelPlan<D, F> {
self.channel_mask.set_bank(7, mask);
}

#[allow(unused)]
pub fn get_max_payload_length(datarate: DR, repeater_compatible: bool, dwell_time: bool) -> u8 {
F::get_max_payload_length(datarate, repeater_compatible, dwell_time)
}
Expand Down

0 comments on commit b3415fb

Please sign in to comment.