use crate::register_acces::Register;
use crate::MAX_PAYLOAD_SIZE;
#[cfg(feature = "micro-fmt")]
use ufmt::{uDebug, uWrite, uwrite, Formatter};
const MAX_CHANNEL: u8 = 125;
#[derive(Copy, Debug, Clone)]
pub struct NrfConfig {
pub(crate) payload_size: PayloadSize,
pub(crate) channel: u8,
pub(crate) addr_width: AddressWidth,
pub(crate) data_rate: DataRate,
pub(crate) pa_level: PALevel,
pub(crate) crc_encoding_scheme: Option<EncodingScheme>,
pub(crate) ack_payloads_enabled: bool,
pub(crate) auto_retry: AutoRetransmission,
}
impl NrfConfig {
pub fn payload_size<T: Into<PayloadSize>>(mut self, payload_size: T) -> Self {
self.payload_size = payload_size.into();
self
}
pub fn channel(mut self, channel: u8) -> Self {
self.channel = core::cmp::min(channel, MAX_CHANNEL);
self
}
pub fn addr_width<T: Into<AddressWidth>>(mut self, addr_width: T) -> Self {
self.addr_width = addr_width.into();
self
}
pub fn data_rate(mut self, data_rate: DataRate) -> Self {
self.data_rate = data_rate;
self
}
pub fn pa_level(mut self, pa_level: PALevel) -> Self {
self.pa_level = pa_level;
self
}
pub fn crc_encoding_scheme(mut self, crc_encoding_scheme: Option<EncodingScheme>) -> Self {
self.crc_encoding_scheme = crc_encoding_scheme;
self
}
pub fn ack_payloads_enabled(mut self, ack_payloads_enabled: bool) -> Self {
self.ack_payloads_enabled = ack_payloads_enabled;
self
}
pub fn auto_retry<T: Into<AutoRetransmission>>(mut self, auto_retry: T) -> Self {
self.auto_retry = auto_retry.into();
self
}
}
impl Default for NrfConfig {
fn default() -> Self {
Self {
channel: 76,
payload_size: PayloadSize::default(),
addr_width: AddressWidth::default(),
crc_encoding_scheme: Some(EncodingScheme::R2Bytes),
pa_level: PALevel::default(),
data_rate: DataRate::default(),
ack_payloads_enabled: false,
auto_retry: AutoRetransmission::default(),
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for NrfConfig {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
f.debug_struct("nRF configuration")?
.field("channel", &self.channel)?
.field("payload size", &self.payload_size)?
.field("power amplification level", &self.pa_level)?
.field("data rate", &self.data_rate)?
.field("auto retransmission", &self.auto_retry)?
.field(
"acknowledgement payloads enabled",
&self.ack_payloads_enabled,
)?
.field("address width", &self.addr_width)?
.field("crc encoding scheme", &self.crc_encoding_scheme)?
.finish()
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum PALevel {
Min = 0b0000_0000,
Low = 0b0000_0010,
High = 0b0000_0100,
Max = 0b0000_0110,
}
impl PALevel {
pub(crate) fn bitmask() -> u8 {
0b0000_0110
}
pub(crate) fn level(&self) -> u8 {
*self as u8
}
}
impl Default for PALevel {
fn default() -> Self {
PALevel::Min
}
}
impl From<u8> for PALevel {
fn from(t: u8) -> Self {
match t & Self::bitmask() {
0b0000_0000 => Self::Min,
0b0000_0010 => Self::Low,
0b0000_0100 => Self::High,
0b0000_0110 => Self::Max,
_ => unreachable!(),
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for PALevel {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
match *self {
PALevel::Min => f.write_str("min (-18 dBm)"),
PALevel::Low => f.write_str("low (-12 dBm)"),
PALevel::High => f.write_str("high (-6 dBm)"),
PALevel::Max => f.write_str("max (0 dBm)"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PayloadSize {
Dynamic,
Static(u8),
}
impl PayloadSize {
pub(crate) fn truncate(self) -> Self {
match self {
Self::Dynamic => Self::Dynamic,
Self::Static(n) => Self::Static(core::cmp::min(n, MAX_PAYLOAD_SIZE)),
}
}
}
impl Default for PayloadSize {
fn default() -> Self {
Self::Static(MAX_PAYLOAD_SIZE)
}
}
impl From<u8> for PayloadSize {
fn from(size: u8) -> Self {
match size {
0 => Self::Dynamic,
n => Self::Static(core::cmp::min(n, MAX_PAYLOAD_SIZE)),
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for PayloadSize {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
match *self {
Self::Dynamic => f.write_str("dynamic payloads"),
Self::Static(n) => uwrite!(f, "{:?} byte static payloads", n),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum DataRate {
R1Mbps = 0b0000_0000,
R2Mbps = 0b0000_0001,
}
impl DataRate {
pub(crate) fn bitmask() -> u8 {
0b1111_1110
}
pub(crate) fn rate(&self) -> u8 {
*self as u8
}
}
impl Default for DataRate {
fn default() -> Self {
DataRate::R1Mbps
}
}
impl From<u8> for DataRate {
fn from(t: u8) -> Self {
match t & Self::bitmask() {
0 => Self::R1Mbps,
1 => Self::R2Mbps,
_ => unreachable!(),
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for DataRate {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
match *self {
DataRate::R1Mbps => f.write_str("1 Mbps"),
DataRate::R2Mbps => f.write_str("2 Mbps"),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum EncodingScheme {
R1Byte = 0,
R2Bytes = 1,
}
impl EncodingScheme {
pub(crate) fn scheme(&self) -> u8 {
*self as u8
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for EncodingScheme {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
match *self {
Self::R1Byte => f.write_str("1 byte"),
Self::R2Bytes => f.write_str("2 bytes"),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum AddressWidth {
R3Bytes = 1,
R4Bytes = 2,
R5Bytes = 3,
}
impl AddressWidth {
pub(crate) fn value(&self) -> u8 {
*self as u8
}
}
impl Default for AddressWidth {
fn default() -> Self {
Self::R5Bytes
}
}
impl From<u8> for AddressWidth {
fn from(t: u8) -> Self {
match t {
0..=3 => Self::R3Bytes,
4 => Self::R4Bytes,
5..=u8::MAX => Self::R5Bytes,
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for AddressWidth {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
match *self {
Self::R3Bytes => f.write_str("3 bytes"),
Self::R4Bytes => f.write_str("4 bytes"),
Self::R5Bytes => f.write_str("5 bytes"),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct AutoRetransmission {
delay: u8,
count: u8,
}
impl Default for AutoRetransmission {
fn default() -> Self {
Self {
delay: 5,
count: 15,
}
}
}
impl AutoRetransmission {
pub(crate) fn from_register(reg: u8) -> Self {
Self {
delay: reg >> 4,
count: reg & 0b0000_1111,
}
}
pub fn raw_delay(&self) -> u8 {
self.delay
}
pub fn delay(&self) -> u32 {
((self.delay as u32 + 1) * 250) + 86
}
pub fn count(&self) -> u8 {
self.count
}
}
impl From<(u8, u8)> for AutoRetransmission {
fn from((d, c): (u8, u8)) -> Self {
Self {
delay: core::cmp::min(d, 15),
count: core::cmp::min(c, 15),
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for AutoRetransmission {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
f.debug_struct("AutoRetransmission")?
.field("delay", &self.delay)?
.field("count", &self.count)?
.finish()
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[repr(u8)]
pub enum DataPipe {
DP0 = 0,
DP1 = 1,
DP2 = 2,
DP3 = 3,
DP4 = 4,
DP5 = 5,
}
impl DataPipe {
pub(crate) fn pipe(&self) -> u8 {
*self as u8
}
}
impl Default for DataPipe {
fn default() -> Self {
DataPipe::DP0
}
}
impl From<u8> for DataPipe {
fn from(t: u8) -> Self {
match t {
0 => DataPipe::DP0,
1 => DataPipe::DP1,
2 => DataPipe::DP2,
3 => DataPipe::DP3,
4 => DataPipe::DP4,
5 => DataPipe::DP5,
_ => DataPipe::DP0,
}
}
}
impl Into<Register> for DataPipe {
fn into(self) -> Register {
match self {
DataPipe::DP0 => Register::RX_ADDR_P0,
DataPipe::DP1 => Register::RX_ADDR_P1,
DataPipe::DP2 => Register::RX_ADDR_P2,
DataPipe::DP3 => Register::RX_ADDR_P3,
DataPipe::DP4 => Register::RX_ADDR_P4,
DataPipe::DP5 => Register::RX_ADDR_P5,
}
}
}
#[cfg(feature = "micro-fmt")]
impl uDebug for DataPipe {
fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
where
W: uWrite,
{
match *self {
DataPipe::DP0 => f.write_str("data pipe 0"),
DataPipe::DP1 => f.write_str("data pipe 1"),
DataPipe::DP2 => f.write_str("data pipe 2"),
DataPipe::DP3 => f.write_str("data pipe 3"),
DataPipe::DP4 => f.write_str("data pipe 4"),
DataPipe::DP5 => f.write_str("data pipe 5"),
}
}
}