#[cfg(feature = "alloc")]
use super::MAX_FRAME_BYTES;
use super::config::{TncConfig, TncError};
use crate::aprs::AprsPacket;
use crate::ax25::{Address, Ax25Error, UiFrame, hdlc};
#[cfg(feature = "g3ruh")]
use crate::baseband::BasebandI16Samples;
use crate::modulator::{F32Samples, I16Samples, Modulator};
use crate::nrzi;
#[cfg(feature = "g3ruh")]
use crate::scrambler::Scrambler;
#[derive(Debug, Clone)]
pub struct TxI16Samples<'a> {
inner: TxI16Inner<'a>,
}
#[derive(Debug, Clone)]
enum TxI16Inner<'a> {
Tone(I16Samples<nrzi::EncodeIter<hdlc::FrameBits<'a>>>),
#[cfg(feature = "g3ruh")]
Baseband(
BasebandI16Samples<crate::scrambler::ScrambleIter<nrzi::EncodeIter<hdlc::FrameBits<'a>>>>,
),
}
impl Iterator for TxI16Samples<'_> {
type Item = i16;
fn next(&mut self) -> Option<i16> {
match self.inner {
TxI16Inner::Tone(ref mut it) => it.next(),
#[cfg(feature = "g3ruh")]
TxI16Inner::Baseband(ref mut it) => it.next(),
}
}
}
#[derive(Debug, Clone)]
pub struct TxF32Samples<'a> {
inner: TxF32Inner<'a>,
}
#[derive(Debug, Clone)]
enum TxF32Inner<'a> {
Tone(F32Samples<nrzi::EncodeIter<hdlc::FrameBits<'a>>>),
#[cfg(feature = "g3ruh")]
Baseband(
crate::baseband::BasebandF32Samples<
crate::scrambler::ScrambleIter<nrzi::EncodeIter<hdlc::FrameBits<'a>>>,
>,
),
}
impl Iterator for TxF32Samples<'_> {
type Item = f32;
fn next(&mut self) -> Option<f32> {
match self.inner {
TxF32Inner::Tone(ref mut it) => it.next(),
#[cfg(feature = "g3ruh")]
TxF32Inner::Baseband(ref mut it) => it.next(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TncTransmitter {
config: TncConfig,
}
impl TncTransmitter {
#[must_use]
pub const fn new(config: TncConfig) -> Self {
Self { config }
}
#[must_use]
pub const fn config(&self) -> TncConfig {
self.config
}
pub fn build_frame(
&self,
packet: &AprsPacket<'_>,
dest: Address,
src: Address,
path: &[Address],
info_buf: &mut [u8],
frame_buf: &mut [u8],
) -> Result<usize, TncError> {
Ok(crate::aprs::build_ui_frame(
packet, dest, src, path, info_buf, frame_buf,
)?)
}
#[must_use]
pub fn frame_samples_i16<'a>(&self, frame: &'a [u8]) -> TxI16Samples<'a> {
let bits = nrzi::encode_iter(hdlc::frame_bits(
frame,
self.config.preamble_flags,
self.config.tail_flags,
));
#[cfg(feature = "g3ruh")]
if let Some(baseband) = self.config.baseband {
return TxI16Samples {
inner: TxI16Inner::Baseband(
baseband.i16_samples(Scrambler::default().scramble_iter(bits)),
),
};
}
TxI16Samples {
inner: TxI16Inner::Tone(Modulator::new(self.config.modulator).i16_samples(bits)),
}
}
#[must_use]
pub fn frame_samples_f32<'a>(&self, frame: &'a [u8]) -> TxF32Samples<'a> {
let bits = nrzi::encode_iter(hdlc::frame_bits(
frame,
self.config.preamble_flags,
self.config.tail_flags,
));
#[cfg(feature = "g3ruh")]
if let Some(baseband) = self.config.baseband {
return TxF32Samples {
inner: TxF32Inner::Baseband(
baseband.f32_samples(Scrambler::default().scramble_iter(bits)),
),
};
}
TxF32Samples {
inner: TxF32Inner::Tone(Modulator::new(self.config.modulator).f32_samples(bits)),
}
}
pub fn transmit_i16<'a>(
&self,
packet: &AprsPacket<'_>,
dest: Address,
src: Address,
path: &[Address],
info_buf: &mut [u8],
frame_buf: &'a mut [u8],
) -> Result<TxI16Samples<'a>, TncError> {
let len = self.build_frame(packet, dest, src, path, info_buf, frame_buf)?;
let frame = frame_buf
.get(..len)
.ok_or(TncError::Ax25(Ax25Error::FrameTooLarge {
len,
max: frame_buf.len(),
}))?;
Ok(self.frame_samples_i16(frame))
}
pub fn transmit_f32<'a>(
&self,
packet: &AprsPacket<'_>,
dest: Address,
src: Address,
path: &[Address],
info_buf: &mut [u8],
frame_buf: &'a mut [u8],
) -> Result<TxF32Samples<'a>, TncError> {
let len = self.build_frame(packet, dest, src, path, info_buf, frame_buf)?;
let frame = frame_buf
.get(..len)
.ok_or(TncError::Ax25(Ax25Error::FrameTooLarge {
len,
max: frame_buf.len(),
}))?;
Ok(self.frame_samples_f32(frame))
}
pub fn build_frame_raw(
&self,
dest: Address,
src: Address,
path: &[Address],
info: &[u8],
frame_buf: &mut [u8],
) -> Result<usize, TncError> {
let frame = UiFrame::with_path(dest, src, path, info)?;
Ok(frame.build(frame_buf)?)
}
#[cfg(feature = "alloc")]
pub fn transmit_to_vec_i16(
&self,
packet: &AprsPacket<'_>,
dest: Address,
src: Address,
path: &[Address],
) -> Result<alloc::vec::Vec<i16>, TncError> {
let mut info_buf = [0u8; MAX_FRAME_BYTES];
let mut frame_buf = [0u8; MAX_FRAME_BYTES];
let samples = self.transmit_i16(packet, dest, src, path, &mut info_buf, &mut frame_buf)?;
Ok(samples.collect())
}
#[cfg(feature = "alloc")]
pub fn transmit_to_vec_f32(
&self,
packet: &AprsPacket<'_>,
dest: Address,
src: Address,
path: &[Address],
) -> Result<alloc::vec::Vec<f32>, TncError> {
let mut info_buf = [0u8; MAX_FRAME_BYTES];
let mut frame_buf = [0u8; MAX_FRAME_BYTES];
let samples = self.transmit_f32(packet, dest, src, path, &mut info_buf, &mut frame_buf)?;
Ok(samples.collect())
}
}