use crate::bladerf1::board::RfLinkSession;
use crate::bladerf1::hardware::lms6002d::gain::{LmsLowNoiseAmplifier, LmsPowerAmplifier};
use crate::channel::Channel;
use crate::error::{Error, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RfPort {
None,
Lna1,
Lna2,
Lna3,
Pa1,
Pa2,
Aux,
}
impl RfPort {
pub const RX_PORTS: [RfPort; 4] = [RfPort::None, RfPort::Lna1, RfPort::Lna2, RfPort::Lna3];
pub const TX_PORTS: [RfPort; 4] = [RfPort::Aux, RfPort::Pa1, RfPort::Pa2, RfPort::None];
pub fn is_valid_for(self, channel: Channel) -> bool {
match channel {
Channel::Rx => matches!(
self,
RfPort::None | RfPort::Lna1 | RfPort::Lna2 | RfPort::Lna3
),
Channel::Tx => matches!(self, RfPort::None | RfPort::Pa1 | RfPort::Pa2 | RfPort::Aux),
}
}
}
impl From<LmsLowNoiseAmplifier> for RfPort {
fn from(lna: LmsLowNoiseAmplifier) -> RfPort {
match lna {
LmsLowNoiseAmplifier::LnaNone => RfPort::None,
LmsLowNoiseAmplifier::Lna1 => RfPort::Lna1,
LmsLowNoiseAmplifier::Lna2 => RfPort::Lna2,
LmsLowNoiseAmplifier::Lna3 => RfPort::Lna3,
}
}
}
impl From<LmsPowerAmplifier> for RfPort {
fn from(pa: LmsPowerAmplifier) -> RfPort {
match pa {
LmsPowerAmplifier::PaNone => RfPort::None,
LmsPowerAmplifier::Pa1 => RfPort::Pa1,
LmsPowerAmplifier::Pa2 => RfPort::Pa2,
LmsPowerAmplifier::PaAux => RfPort::Aux,
}
}
}
impl TryFrom<RfPort> for LmsLowNoiseAmplifier {
type Error = Error;
fn try_from(port: RfPort) -> Result<Self> {
match port {
RfPort::None => Ok(LmsLowNoiseAmplifier::LnaNone),
RfPort::Lna1 => Ok(LmsLowNoiseAmplifier::Lna1),
RfPort::Lna2 => Ok(LmsLowNoiseAmplifier::Lna2),
RfPort::Lna3 => Ok(LmsLowNoiseAmplifier::Lna3),
_ => Err(Error::Argument("RX port does not map to LNA".into())),
}
}
}
impl TryFrom<RfPort> for LmsPowerAmplifier {
type Error = Error;
fn try_from(port: RfPort) -> Result<Self> {
match port {
RfPort::None => Ok(LmsPowerAmplifier::PaNone),
RfPort::Pa1 => Ok(LmsPowerAmplifier::Pa1),
RfPort::Pa2 => Ok(LmsPowerAmplifier::Pa2),
RfPort::Aux => Ok(LmsPowerAmplifier::PaAux),
_ => Err(Error::Argument("TX port does not map to PA".into())),
}
}
}
impl TryFrom<&str> for RfPort {
type Error = Error;
fn try_from(name: &str) -> Result<Self> {
match name.to_lowercase().as_str() {
"none" => Ok(RfPort::None),
"lna1" => Ok(RfPort::Lna1),
"lna2" => Ok(RfPort::Lna2),
"lna3" => Ok(RfPort::Lna3),
"pa1" => Ok(RfPort::Pa1),
"pa2" => Ok(RfPort::Pa2),
"aux" => Ok(RfPort::Aux),
_ => Err(Error::Argument("unknown RF port".into())),
}
}
}
impl From<RfPort> for &'static str {
fn from(port: RfPort) -> Self {
match port {
RfPort::None => "none",
RfPort::Lna1 => "lna1",
RfPort::Lna2 => "lna2",
RfPort::Lna3 => "lna3",
RfPort::Pa1 => "pa1",
RfPort::Pa2 => "pa2",
RfPort::Aux => "aux",
}
}
}
impl RfLinkSession<'_> {
pub fn set_rf_port(&mut self, channel: Channel, port: RfPort) -> Result<()> {
self.require_initialized()?;
if !port.is_valid_for(channel) {
return Err(Error::Argument("RF port not valid for channel".into()));
}
match channel {
Channel::Rx => {
let lna = LmsLowNoiseAmplifier::try_from(port)?;
self.lms().select_lna(lna)
}
Channel::Tx => {
let pa = LmsPowerAmplifier::try_from(port)?;
self.lms().select_pa(pa)
}
}
}
pub fn get_rf_port(&mut self, channel: Channel) -> Result<RfPort> {
self.require_initialized()?;
match channel {
Channel::Rx => self.lms().get_lna().map(RfPort::from),
Channel::Tx => self.lms().get_pa().map(RfPort::from),
}
}
pub fn get_rf_ports(channel: Channel) -> &'static [RfPort] {
match channel {
Channel::Rx => &RfPort::RX_PORTS,
Channel::Tx => &RfPort::TX_PORTS,
}
}
}