lorawan_device/region/fixed_channel_plans/
mod.rs1use super::*;
2use core::marker::PhantomData;
3use lorawan::maccommands::ChannelMask;
4
5mod join_channels;
6use join_channels::JoinChannels;
7
8#[cfg(feature = "region-au915")]
9mod au915;
10#[cfg(feature = "region-us915")]
11mod us915;
12
13#[cfg(feature = "region-au915")]
14pub use au915::AU915;
15#[cfg(feature = "region-us915")]
16pub use us915::US915;
17
18seq_macro::seq!(
19 N in 1..=8 {
20 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
23 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24 #[repr(usize)]
25 pub enum Subband {
26 #(
27 _~N = N,
28 )*
29 }
30 }
31);
32
33impl From<Subband> for usize {
34 fn from(value: Subband) -> Self {
35 value as usize
36 }
37}
38
39#[derive(Default, Clone)]
40#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41pub(crate) struct FixedChannelPlan<const NUM_DR: usize, F: FixedChannelRegion<NUM_DR>> {
42 last_tx_channel: u8,
43 channel_mask: ChannelMask<9>,
44 _fixed_channel_region: PhantomData<F>,
45 join_channels: JoinChannels,
46}
47
48impl<const D: usize, F: FixedChannelRegion<D>> FixedChannelPlan<D, F> {
49 pub fn set_125k_channels(&mut self, enabled: bool) {
50 let mask = if enabled {
51 0xFF
52 } else {
53 0x00
54 };
55 self.channel_mask.set_bank(0, mask);
56 self.channel_mask.set_bank(1, mask);
57 self.channel_mask.set_bank(2, mask);
58 self.channel_mask.set_bank(3, mask);
59 self.channel_mask.set_bank(4, mask);
60 self.channel_mask.set_bank(5, mask);
61 self.channel_mask.set_bank(6, mask);
62 self.channel_mask.set_bank(7, mask);
63 }
64
65 #[allow(unused)]
66 pub fn get_max_payload_length(datarate: DR, repeater_compatible: bool, dwell_time: bool) -> u8 {
67 F::get_max_payload_length(datarate, repeater_compatible, dwell_time)
68 }
69}
70
71pub(crate) trait FixedChannelRegion<const D: usize>: ChannelRegion<D> {
72 fn uplink_channels() -> &'static [u32; 72];
73 fn downlink_channels() -> &'static [u32; 8];
74 fn get_default_rx2() -> u32;
75 fn get_rx_datarate(tx_datarate: DR, frame: &Frame, window: &Window) -> Datarate;
76 fn get_dbm() -> i8;
77}
78
79impl<const D: usize, F: FixedChannelRegion<D>> RegionHandler for FixedChannelPlan<D, F> {
80 fn process_join_accept<T: AsRef<[u8]>, C>(
81 &mut self,
82 join_accept: &DecryptedJoinAcceptPayload<T, C>,
83 ) {
84 if let Some(CfList::FixedChannel(channel_mask)) = join_accept.c_f_list() {
85 self.join_channels.reset();
87 self.channel_mask = channel_mask;
88 }
89 }
90
91 fn handle_link_adr_channel_mask(
92 &mut self,
93 channel_mask_control: u8,
94 channel_mask: ChannelMask<2>,
95 ) {
96 self.join_channels.reset();
97 match channel_mask_control {
98 0..=4 => {
99 let base_index = channel_mask_control as usize * 2;
100 self.channel_mask.set_bank(base_index, channel_mask.get_index(0));
101 self.channel_mask.set_bank(base_index + 1, channel_mask.get_index(1));
102 }
103 5 => {
104 let channel_mask: u16 =
105 channel_mask.get_index(0) as u16 | ((channel_mask.get_index(1) as u16) << 8);
106 self.channel_mask.set_bank(0, ((channel_mask & 0b1) * 0xFF) as u8);
107 self.channel_mask.set_bank(1, ((channel_mask & 0b10) * 0xFF) as u8);
108 self.channel_mask.set_bank(2, ((channel_mask & 0b100) * 0xFF) as u8);
109 self.channel_mask.set_bank(3, ((channel_mask & 0b1000) * 0xFF) as u8);
110 self.channel_mask.set_bank(4, ((channel_mask & 0b10000) * 0xFF) as u8);
111 self.channel_mask.set_bank(5, ((channel_mask & 0b100000) * 0xFF) as u8);
112 self.channel_mask.set_bank(6, ((channel_mask & 0b1000000) * 0xFF) as u8);
113 self.channel_mask.set_bank(7, ((channel_mask & 0b10000000) * 0xFF) as u8);
114 self.channel_mask.set_bank(8, ((channel_mask & 0b100000000) * 0xFF) as u8);
115 }
116 6 => {
117 self.set_125k_channels(true);
118 }
119 7 => {
120 self.set_125k_channels(false);
121 }
122 _ => {
123 }
125 }
126 }
127
128 fn get_tx_dr_and_frequency<RNG: RngCore>(
129 &mut self,
130 rng: &mut RNG,
131 datarate: DR,
132 frame: &Frame,
133 ) -> (Datarate, u32) {
134 match frame {
135 Frame::Join => {
136 let channel = self.join_channels.get_next_channel(rng);
137 let dr = if channel < 64 {
138 DR::_0
139 } else {
140 DR::_4
141 };
142 self.last_tx_channel = channel;
143 let data_rate = F::datarates()[dr as usize].clone().unwrap();
144 (data_rate, F::uplink_channels()[channel as usize])
145 }
146 Frame::Data => {
147 let (data_rate, channel) = if self.join_channels.has_bias_and_not_exhausted() {
152 let channel = self.join_channels.get_next_channel(rng);
153 let dr = if channel < 64 {
154 DR::_0
155 } else {
156 DR::_4
157 };
158 (F::datarates()[dr as usize].clone().unwrap(), channel)
159 } else if let Some(channel) = self.join_channels.first_data_channel(rng) {
162 (F::datarates()[datarate as usize].clone().unwrap(), channel)
163 } else {
164 let datarate = F::datarates()[datarate as usize].clone().unwrap();
168 if datarate.bandwidth == Bandwidth::_500KHz {
169 let mut channel = (rng.next_u32() & 0b111) as u8;
170 while !self.channel_mask.is_enabled(channel.into()).unwrap() {
172 channel = (rng.next_u32() & 0b111) as u8;
173 }
174 (datarate, 64 + channel)
175 } else {
176 let mut channel = (rng.next_u32() & 0b111111) as u8;
177 while !self.channel_mask.is_enabled(channel.into()).unwrap() {
179 channel = (rng.next_u32() & 0b111111) as u8;
180 }
181 (datarate, channel)
182 }
183 };
184 self.last_tx_channel = channel;
185 (data_rate, F::uplink_channels()[channel as usize])
186 }
187 }
188 }
189
190 fn get_rx_frequency(&self, _frame: &Frame, window: &Window) -> u32 {
191 let channel = self.last_tx_channel % 8;
192 match window {
193 Window::_1 => F::downlink_channels()[channel as usize],
194 Window::_2 => F::get_default_rx2(),
195 }
196 }
197
198 fn get_dbm(&self) -> i8 {
199 F::get_dbm()
200 }
201
202 fn get_rx_datarate(&self, tx_datarate: DR, frame: &Frame, window: &Window) -> Datarate {
203 F::get_rx_datarate(tx_datarate, frame, window)
204 }
205}