Skip to main content

pamoja_lora/region/
plans.rs

1//! The published channel plans, transcribed from RP002-1.0.5.
2//!
3//! Each region is behind its own cargo feature, all on by default, because a
4//! device only ever operates in one region and a microcontroller should not
5//! carry the other nine in flash.
6
7use super::ChannelPlan;
8// The table types follow the regions: a build that selects one band, or none,
9// must not be told it imported types no plan in it uses.
10#[cfg(any(
11    feature = "eu868",
12    feature = "us915",
13    feature = "eu433",
14    feature = "au915",
15    feature = "cn470",
16    feature = "as923",
17    feature = "kr920",
18    feature = "in865",
19    feature = "ru864"
20))]
21use super::{
22    Beacon, ChannelBlock, DataRate, JoinSequence, MaskControl, MaxPayload, PlanKind, PowerReference,
23};
24// A numbering for type 1 channel lists belongs to the dynamic plans that name one.
25#[cfg(any(
26    feature = "eu868",
27    feature = "as923",
28    feature = "kr920",
29    feature = "in865",
30    feature = "ru864"
31))]
32use super::FixedChannelList;
33// Only CN470-510 picks its plan by the channel a device joined on.
34#[cfg(feature = "cn470")]
35use super::JoinPlan;
36// Every region with relay parameters in RP002-1.0.5; EU433 has none.
37#[cfg(any(
38    feature = "eu868",
39    feature = "us915",
40    feature = "au915",
41    feature = "cn470",
42    feature = "as923",
43    feature = "kr920",
44    feature = "in865",
45    feature = "ru864"
46))]
47use super::RelayChannel;
48// Only the bands whose regulators cap airtime describe sub-bands; the 900 MHz
49// plans and IN865 leave the table empty.
50#[cfg(any(
51    feature = "eu868",
52    feature = "eu433",
53    feature = "as923",
54    feature = "kr920",
55    feature = "ru864"
56))]
57use super::SubBand;
58
59/// A named regional channel plan.
60///
61/// This is a convenience over [`ChannelPlan`], not the only way to get one: a
62/// deployment on licensed spectrum builds its own plan and every method still
63/// applies. Each variant is behind its own cargo feature.
64#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
65#[non_exhaustive]
66pub enum Region {
67    /// Europe and everywhere else following ETSI EN 300 220, 863-870 MHz.
68    #[cfg(feature = "eu868")]
69    Eu868,
70    /// The United States, Canada, and ITU Region 2, 902-928 MHz.
71    #[cfg(feature = "us915")]
72    Us915,
73    /// The 433 MHz ISM band.
74    #[cfg(feature = "eu433")]
75    Eu433,
76    /// Australia and the countries following it, 915-928 MHz.
77    #[cfg(feature = "au915")]
78    Au915,
79    /// China, 470-510 MHz.
80    #[cfg(feature = "cn470")]
81    Cn470,
82    /// Asia and the Pacific, 923 MHz.
83    #[cfg(feature = "as923")]
84    As923,
85    /// South Korea, 920-923 MHz.
86    #[cfg(feature = "kr920")]
87    Kr920,
88    /// India, 865-867 MHz.
89    #[cfg(feature = "in865")]
90    In865,
91    /// Russia, 864-870 MHz.
92    #[cfg(feature = "ru864")]
93    Ru864,
94}
95
96impl Region {
97    /// Returns the channel plan this region names.
98    ///
99    /// # Returns
100    ///
101    /// The plan, whose tables come straight from RP002-1.0.5.
102    pub const fn plan(self) -> &'static ChannelPlan<'static> {
103        match self {
104            #[cfg(feature = "eu868")]
105            Region::Eu868 => &EU868,
106            #[cfg(feature = "us915")]
107            Region::Us915 => &US915,
108            #[cfg(feature = "eu433")]
109            Region::Eu433 => &EU433,
110            #[cfg(feature = "au915")]
111            Region::Au915 => &AU915,
112            #[cfg(feature = "cn470")]
113            Region::Cn470 => &CN470,
114            #[cfg(feature = "as923")]
115            Region::As923 => &AS923,
116            #[cfg(feature = "kr920")]
117            Region::Kr920 => &KR920,
118            #[cfg(feature = "in865")]
119            Region::In865 => &IN865,
120            #[cfg(feature = "ru864")]
121            Region::Ru864 => &RU864,
122        }
123    }
124
125    /// Returns the specification's name for this region's band.
126    ///
127    /// # Returns
128    ///
129    /// The band name, such as `"EU863-870"`.
130    pub const fn name(self) -> &'static str {
131        self.plan().name
132    }
133
134    /// Returns the short code this region is configured by.
135    ///
136    /// A deployment is set up as `EU868` or `US915`; the band name the
137    /// specification uses, such as `EU863-870`, is what [`name`](Self::name)
138    /// reports. Both identify the same plan.
139    ///
140    /// # Returns
141    ///
142    /// The short code, such as `"EU868"`.
143    ///
144    /// # Examples
145    ///
146    /// ```
147    /// # #[cfg(feature = "eu868")] {
148    /// use pamoja_lora::region::Region;
149    ///
150    /// assert_eq!(Region::Eu868.code(), "EU868");
151    /// assert_eq!(Region::Eu868.name(), "EU863-870");
152    /// # }
153    /// ```
154    pub const fn code(self) -> &'static str {
155        match self {
156            #[cfg(feature = "eu868")]
157            Region::Eu868 => "EU868",
158            #[cfg(feature = "us915")]
159            Region::Us915 => "US915",
160            #[cfg(feature = "eu433")]
161            Region::Eu433 => "EU433",
162            #[cfg(feature = "au915")]
163            Region::Au915 => "AU915",
164            #[cfg(feature = "cn470")]
165            Region::Cn470 => "CN470",
166            #[cfg(feature = "as923")]
167            Region::As923 => "AS923",
168            #[cfg(feature = "kr920")]
169            Region::Kr920 => "KR920",
170            #[cfg(feature = "in865")]
171            Region::In865 => "IN865",
172            #[cfg(feature = "ru864")]
173            Region::Ru864 => "RU864",
174        }
175    }
176
177    /// Returns the region a short code names.
178    ///
179    /// The comparison ignores case, and the specification's band name is
180    /// accepted as well, so a plan read back from a device's configuration
181    /// resolves whichever form it was written in.
182    ///
183    /// # Arguments
184    ///
185    /// * `code` - the short code or band name, such as `"EU868"`.
186    ///
187    /// # Returns
188    ///
189    /// The region, or `None` if no region in this build goes by that name.
190    ///
191    /// # Examples
192    ///
193    /// ```
194    /// # #[cfg(feature = "us915")] {
195    /// use pamoja_lora::region::Region;
196    ///
197    /// assert_eq!(Region::from_code("us915"), Some(Region::Us915));
198    /// assert_eq!(Region::from_code("US902-928"), Some(Region::Us915));
199    /// assert_eq!(Region::from_code("Atlantis"), None);
200    /// # }
201    /// ```
202    pub fn from_code(code: &str) -> Option<Self> {
203        Self::all().iter().copied().find(|region| {
204            code.eq_ignore_ascii_case(region.code()) || code.eq_ignore_ascii_case(region.name())
205        })
206    }
207
208    /// Returns every region this build carries.
209    ///
210    /// A build that selects only its own region gets a one-element slice, which
211    /// is the point of the per-region features.
212    ///
213    /// # Returns
214    ///
215    /// The compiled-in regions.
216    pub const fn all() -> &'static [Region] {
217        &[
218            #[cfg(feature = "eu868")]
219            Region::Eu868,
220            #[cfg(feature = "us915")]
221            Region::Us915,
222            #[cfg(feature = "eu433")]
223            Region::Eu433,
224            #[cfg(feature = "au915")]
225            Region::Au915,
226            #[cfg(feature = "cn470")]
227            Region::Cn470,
228            #[cfg(feature = "as923")]
229            Region::As923,
230            #[cfg(feature = "kr920")]
231            Region::Kr920,
232            #[cfg(feature = "in865")]
233            Region::In865,
234            #[cfg(feature = "ru864")]
235            Region::Ru864,
236        ]
237    }
238}
239
240/// One of the channel plans the CN470-510 band is divided into.
241///
242/// [`Region::Cn470`] names the first. A device joining over the air can start from any of the
243/// four RP002-1.0.5 plans, since they share their join channels and the channel that answers
244/// decides the plan; a personalized device, or one on a network still running the 96-channel
245/// plan, is set up on the one it belongs to.
246///
247/// # Examples
248///
249/// ```
250/// use pamoja_lora::region::{Cn470Plan, Region};
251///
252/// assert!(core::ptr::eq(Region::Cn470.plan(), Cn470Plan::Antenna20MhzA.plan()));
253/// assert_eq!(Cn470Plan::Channels96.plan().default_channel_count(), 96);
254/// assert_eq!(Cn470Plan::Antenna26MhzB.plan().rx2(), (502_500_000, 1));
255/// ```
256#[cfg(feature = "cn470")]
257#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
258pub enum Cn470Plan {
259    /// A 20 MHz antenna, type A: uplink from 470.3 and 503.5 MHz, downlink from 483.9 and
260    /// 490.3 MHz, RP002-1.0.5 section 3.9.2.1.
261    Antenna20MhzA,
262    /// A 20 MHz antenna, type B: uplink and downlink from 476.9 and 496.9 MHz.
263    Antenna20MhzB,
264    /// A 26 MHz antenna, type A: 48 uplink channels from 470.3 MHz and 24 downlink channels
265    /// from 490.1 MHz, RP002-1.0.5 section 3.9.2.2.
266    Antenna26MhzA,
267    /// A 26 MHz antenna, type B: 48 uplink channels from 480.3 MHz and 24 downlink channels
268    /// from 500.1 MHz.
269    Antenna26MhzB,
270    /// The 96-channel plan RP002-1.0.5 replaced, from the LoRaWAN 1.0.3 Regional Parameters
271    /// revision A: 96 uplink channels from 470.3 MHz and 48 downlink channels from 500.3 MHz.
272    Channels96,
273}
274
275#[cfg(feature = "cn470")]
276impl Cn470Plan {
277    /// Returns the channel plan.
278    ///
279    /// # Returns
280    ///
281    /// The plan.
282    pub const fn plan(self) -> &'static ChannelPlan<'static> {
283        match self {
284            Cn470Plan::Antenna20MhzA => &CN470,
285            Cn470Plan::Antenna20MhzB => &CN470_20B,
286            Cn470Plan::Antenna26MhzA => &CN470_26A,
287            Cn470Plan::Antenna26MhzB => &CN470_26B,
288            Cn470Plan::Channels96 => &CN470_96,
289        }
290    }
291
292    /// Returns every CN470-510 plan.
293    ///
294    /// # Returns
295    ///
296    /// The five plans, the four RP002-1.0.5 ones first.
297    pub const fn all() -> &'static [Cn470Plan] {
298        &[
299            Cn470Plan::Antenna20MhzA,
300            Cn470Plan::Antenna20MhzB,
301            Cn470Plan::Antenna26MhzA,
302            Cn470Plan::Antenna26MhzB,
303            Cn470Plan::Channels96,
304        ]
305    }
306}
307
308// EU863-870, RP002-1.0.5 section 3.4.
309
310/// RP002-1.0.5 Table 10: EU863-870 TX data rate.
311#[cfg(feature = "eu868")]
312static EU868_DATA_RATES: [Option<DataRate>; 14] = [
313    Some(DataRate::lora(12, 125_000, 250)),
314    Some(DataRate::lora(11, 125_000, 440)),
315    Some(DataRate::lora(10, 125_000, 980)),
316    Some(DataRate::lora(9, 125_000, 1_760)),
317    Some(DataRate::lora(8, 125_000, 3_125)),
318    Some(DataRate::lora(7, 125_000, 5_470)),
319    Some(DataRate::lora(7, 250_000, 11_000)),
320    Some(DataRate::fsk(50_000)),
321    Some(DataRate::lr_fhss(1, 3, 137_000, 162)),
322    Some(DataRate::lr_fhss(2, 3, 137_000, 325)),
323    Some(DataRate::lr_fhss(1, 3, 336_000, 162)),
324    Some(DataRate::lr_fhss(2, 3, 336_000, 325)),
325    Some(DataRate::lora(6, 125_000, 9_375)),
326    Some(DataRate::lora(5, 125_000, 15_625)),
327];
328
329/// RP002-1.0.5 Table 15: EU863-870 maximum payload size (repeater compatible).
330#[cfg(feature = "eu868")]
331static EU868_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 14] = [
332    Some(MaxPayload::new(59, 51)),
333    Some(MaxPayload::new(59, 51)),
334    Some(MaxPayload::new(59, 51)),
335    Some(MaxPayload::new(123, 115)),
336    Some(MaxPayload::new(230, 222)),
337    Some(MaxPayload::new(230, 222)),
338    Some(MaxPayload::new(230, 222)),
339    Some(MaxPayload::new(230, 222)),
340    Some(MaxPayload::new(58, 50)),
341    Some(MaxPayload::new(123, 115)),
342    Some(MaxPayload::new(58, 50)),
343    Some(MaxPayload::new(123, 115)),
344    Some(MaxPayload::new(230, 222)),
345    Some(MaxPayload::new(230, 222)),
346];
347
348/// RP002-1.0.5 Table 16: EU863-870 maximum payload size (not repeater compatible).
349#[cfg(feature = "eu868")]
350static EU868_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 14] = [
351    Some(MaxPayload::new(59, 51)),
352    Some(MaxPayload::new(59, 51)),
353    Some(MaxPayload::new(59, 51)),
354    Some(MaxPayload::new(123, 115)),
355    Some(MaxPayload::new(250, 242)),
356    Some(MaxPayload::new(250, 242)),
357    Some(MaxPayload::new(250, 242)),
358    Some(MaxPayload::new(250, 242)),
359    Some(MaxPayload::new(58, 50)),
360    Some(MaxPayload::new(123, 115)),
361    Some(MaxPayload::new(58, 50)),
362    Some(MaxPayload::new(123, 115)),
363    Some(MaxPayload::new(250, 242)),
364    Some(MaxPayload::new(250, 242)),
365];
366
367/// RP002-1.0.5 Table 17: EU863-870 downlink RX1 data rate mapping.
368#[cfg(feature = "eu868")]
369static EU868_RX1: [&[u8]; 14] = [
370    &[0, 0, 0, 0, 0, 0],
371    &[1, 0, 0, 0, 0, 0],
372    &[2, 1, 0, 0, 0, 0],
373    &[3, 2, 1, 0, 0, 0],
374    &[4, 3, 2, 1, 0, 0],
375    &[5, 4, 3, 2, 1, 0],
376    &[6, 5, 4, 3, 2, 1],
377    &[7, 6, 5, 4, 3, 2],
378    &[1, 0, 0, 0, 0, 0],
379    &[2, 1, 0, 0, 0, 0],
380    &[1, 0, 0, 0, 0, 0],
381    &[2, 1, 0, 0, 0, 0],
382    &[12, 5, 4, 3, 2, 1],
383    &[13, 12, 5, 4, 3, 2],
384];
385
386/// RP002-1.0.5 Table 12: EU863-870 data rate back-off.
387#[cfg(feature = "eu868")]
388static EU868_BACKOFF: [Option<u8>; 14] = [
389    None,
390    Some(0),
391    Some(1),
392    Some(2),
393    Some(3),
394    Some(4),
395    Some(5),
396    Some(6),
397    Some(0),
398    Some(8),
399    Some(0),
400    Some(10),
401    Some(5),
402    Some(12),
403];
404
405/// RP002-1.0.5 Table 8 and Table 9: the three default and join channels.
406#[cfg(feature = "eu868")]
407static EU868_CHANNELS: [ChannelBlock; 1] = [ChannelBlock::new(868_100_000, 200_000, 3, 0, 5)];
408
409/// The ETSI sub-bands the default channels fall in.
410///
411/// EN 300 220 divides the band, and the 868.0-868.6 MHz sub-band carrying the
412/// three mandatory channels is limited to 1%. The RX2 downlink frequency sits in
413/// the 869.4-869.65 MHz sub-band, which allows 10% at a higher ceiling.
414#[cfg(feature = "eu868")]
415static EU868_SUB_BANDS: [SubBand; 2] = [
416    SubBand::new(868_000_000, 868_600_000, 10, 16),
417    SubBand::new(869_400_000, 869_650_000, 100, 27),
418];
419
420/// RP002-1.0.5 table 18: SF9 and SF7 at 125 kHz.
421#[cfg(feature = "eu868")]
422static EU868_RELAY: [RelayChannel; 2] = [
423    RelayChannel::new(865_100_000, 865_300_000, 3),
424    RelayChannel::new(865_500_000, 865_900_000, 5),
425];
426
427/// The EU863-870 channel plan, RP002-1.0.5 section 3.4.
428#[cfg(feature = "eu868")]
429pub static EU868: ChannelPlan<'static> = ChannelPlan {
430    name: "EU863-870",
431    uplink_data_rates: &EU868_DATA_RATES,
432    downlink_data_rates: &EU868_DATA_RATES,
433    max_payload_repeater: &EU868_MAX_PAYLOAD_REPEATER,
434    max_payload_direct: &EU868_MAX_PAYLOAD_DIRECT,
435    downlink_max_payload_repeater: &EU868_MAX_PAYLOAD_REPEATER,
436    downlink_max_payload_direct: &EU868_MAX_PAYLOAD_DIRECT,
437    max_payload_dwell_limited: None,
438    join_channels: &EU868_CHANNELS,
439    default_channels: &EU868_CHANNELS,
440    sub_bands: &EU868_SUB_BANDS,
441    default_max_eirp_dbm: 16,
442    tx_power_step_db: 2,
443    max_tx_power_index: 7,
444    rx1_data_rate_offsets: &EU868_RX1,
445    rx1_data_rate_offsets_dwell_limited: None,
446    max_rx1_data_rate_offset: 5,
447    rx2_frequency_hz: 869_525_000,
448    rx2_data_rate: 0,
449    data_rate_backoff: &EU868_BACKOFF,
450    beacon: Beacon {
451        data_rate: 3,
452        frequency_hz: 869_525_000,
453        ping_slot_frequency_hz: 869_525_000,
454    },
455    relay_channels: &EU868_RELAY,
456    has_dwell_time_limit: false,
457    kind: PlanKind::Dynamic {
458        channel_list: Some(FixedChannelList::Mhz800),
459    },
460    tx_param_setup: false,
461    mask_controls: MaskControl::DYNAMIC,
462    downlink_channels: &[],
463    join_sequence: JoinSequence::Random,
464    power_reference: PowerReference::Eirp,
465    join_plans: &[],
466};
467
468// US902-928, RP002-1.0.5 section 3.5.
469
470/// RP002-1.0.5 Table 19: US902-928 uplink data rates.
471#[cfg(feature = "us915")]
472static US915_UPLINK_DATA_RATES: [Option<DataRate>; 9] = [
473    Some(DataRate::lora(10, 125_000, 980)),
474    Some(DataRate::lora(9, 125_000, 1_760)),
475    Some(DataRate::lora(8, 125_000, 3_125)),
476    Some(DataRate::lora(7, 125_000, 5_470)),
477    Some(DataRate::lora(8, 500_000, 12_500)),
478    Some(DataRate::lr_fhss(1, 3, 1_523_000, 162)),
479    Some(DataRate::lr_fhss(2, 3, 1_523_000, 325)),
480    Some(DataRate::lora(6, 125_000, 9_375)),
481    Some(DataRate::lora(5, 125_000, 15_625)),
482];
483
484/// RP002-1.0.5 Table 20: US902-928 downlink data rates.
485#[cfg(feature = "us915")]
486static US915_DOWNLINK_DATA_RATES: [Option<DataRate>; 15] = [
487    Some(DataRate::lora(5, 500_000, 62_500)),
488    None,
489    None,
490    None,
491    None,
492    None,
493    None,
494    None,
495    Some(DataRate::lora(12, 500_000, 980)),
496    Some(DataRate::lora(11, 500_000, 1_760)),
497    Some(DataRate::lora(10, 500_000, 3_900)),
498    Some(DataRate::lora(9, 500_000, 7_000)),
499    Some(DataRate::lora(8, 500_000, 12_500)),
500    Some(DataRate::lora(7, 500_000, 21_900)),
501    Some(DataRate::lora(6, 500_000, 37_500)),
502];
503
504/// RP002-1.0.5 Table 24: US902-928 uplink maximum payload (repeater compatible).
505#[cfg(feature = "us915")]
506static US915_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 9] = [
507    Some(MaxPayload::new(19, 11)),
508    Some(MaxPayload::new(61, 53)),
509    Some(MaxPayload::new(133, 125)),
510    Some(MaxPayload::new(230, 222)),
511    Some(MaxPayload::new(230, 222)),
512    Some(MaxPayload::new(58, 50)),
513    Some(MaxPayload::new(133, 125)),
514    Some(MaxPayload::new(230, 222)),
515    Some(MaxPayload::new(230, 222)),
516];
517
518/// RP002-1.0.5 Table 25: US902-928 uplink maximum payload (not repeater compatible).
519#[cfg(feature = "us915")]
520static US915_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 9] = [
521    Some(MaxPayload::new(19, 11)),
522    Some(MaxPayload::new(61, 53)),
523    Some(MaxPayload::new(133, 125)),
524    Some(MaxPayload::new(250, 242)),
525    Some(MaxPayload::new(250, 242)),
526    Some(MaxPayload::new(58, 50)),
527    Some(MaxPayload::new(133, 125)),
528    Some(MaxPayload::new(250, 242)),
529    Some(MaxPayload::new(250, 242)),
530];
531
532/// RP002-1.0.5 Table 24: US902-928 downlink maximum payload (repeater compatible).
533#[cfg(feature = "us915")]
534static US915_DOWNLINK_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 15] = [
535    Some(MaxPayload::new(230, 222)),
536    None,
537    None,
538    None,
539    None,
540    None,
541    None,
542    None,
543    Some(MaxPayload::new(61, 53)),
544    Some(MaxPayload::new(137, 129)),
545    Some(MaxPayload::new(230, 222)),
546    Some(MaxPayload::new(230, 222)),
547    Some(MaxPayload::new(230, 222)),
548    Some(MaxPayload::new(230, 222)),
549    Some(MaxPayload::new(230, 222)),
550];
551
552/// RP002-1.0.5 Table 25: US902-928 downlink maximum payload (not repeater compatible).
553#[cfg(feature = "us915")]
554static US915_DOWNLINK_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 15] = [
555    Some(MaxPayload::new(250, 242)),
556    None,
557    None,
558    None,
559    None,
560    None,
561    None,
562    None,
563    Some(MaxPayload::new(61, 53)),
564    Some(MaxPayload::new(137, 129)),
565    Some(MaxPayload::new(250, 242)),
566    Some(MaxPayload::new(250, 242)),
567    Some(MaxPayload::new(250, 242)),
568    Some(MaxPayload::new(250, 242)),
569    Some(MaxPayload::new(250, 242)),
570];
571
572/// RP002-1.0.5 Table 26: US902-928 downlink RX1 data rate mapping.
573#[cfg(feature = "us915")]
574static US915_RX1: [&[u8]; 9] = [
575    &[10, 9, 8, 8],
576    &[11, 10, 9, 8],
577    &[12, 11, 10, 9],
578    &[13, 12, 11, 10],
579    &[13, 13, 12, 11],
580    &[10, 9, 8, 8],
581    &[11, 10, 9, 8],
582    &[14, 13, 12, 11],
583    &[0, 14, 13, 12],
584];
585
586/// RP002-1.0.5 Table 21: US902-928 uplink data rate back-off.
587#[cfg(feature = "us915")]
588static US915_BACKOFF: [Option<u8>; 9] = [
589    None,
590    Some(0),
591    Some(1),
592    Some(2),
593    Some(3),
594    Some(0),
595    Some(5),
596    Some(3),
597    Some(7),
598];
599
600/// The 64 125 kHz channels and the 8 500 kHz channels, RP002-1.0.5 section 3.5.2.
601#[cfg(feature = "us915")]
602static US915_CHANNELS: [ChannelBlock; 2] = [
603    ChannelBlock::new(902_300_000, 200_000, 64, 0, 3),
604    ChannelBlock::new(903_000_000, 1_600_000, 8, 4, 4),
605];
606
607/// The join channels: a random 125 kHz channel at DR0 and a 500 kHz one at DR4.
608#[cfg(feature = "us915")]
609static US915_JOIN_CHANNELS: [ChannelBlock; 2] = [
610    ChannelBlock::new(902_300_000, 200_000, 64, 0, 0),
611    ChannelBlock::new(903_000_000, 1_600_000, 8, 4, 4),
612];
613
614/// The eight 500 kHz downstream channels, RP002-1.0.5 sections 3.5.2 and 3.8.2, which
615/// US902-928 and AU915-928 share.
616#[cfg(any(feature = "us915", feature = "au915"))]
617static DOWNSTREAM_923: [ChannelBlock; 1] = [ChannelBlock::new(923_300_000, 600_000, 8, 8, 13)];
618
619/// RP002-1.0.5 table 23 and table 43: the `ChMaskCntl` values of US902-928 and AU915-928.
620#[cfg(any(feature = "us915", feature = "au915"))]
621const MASK_CONTROLS_900: [MaskControl; 8] = [
622    MaskControl::Group(0),
623    MaskControl::Group(1),
624    MaskControl::Group(2),
625    MaskControl::Group(3),
626    MaskControl::Group(4),
627    MaskControl::PairedBanks,
628    MaskControl::All {
629        on: true,
630        then_group: Some(4),
631    },
632    MaskControl::All {
633        on: false,
634        then_group: Some(4),
635    },
636];
637
638/// RP002-1.0.5 table 28: SF10 at 500 kHz, downlink DR10.
639#[cfg(feature = "us915")]
640static US915_RELAY: [RelayChannel; 2] = [
641    RelayChannel::new(916_700_000, 918_300_000, 10),
642    RelayChannel::new(919_900_000, 921_500_000, 10),
643];
644
645/// The US902-928 channel plan, RP002-1.0.5 section 3.5.
646///
647/// The FCC constrains this band by dwell time rather than duty cycle, so the
648/// plan publishes no sub-band duty limit and
649/// [`duty_cycle_permille`](ChannelPlan::duty_cycle_permille) reports `None`.
650///
651/// Its power indexes count down from 30 dBm of conducted power, table 22, rather than from a
652/// radiated ceiling. The hopping, digital transmission and hybrid limits RP002-1.0.5 summarizes
653/// in section 3.5.2 depend on how a device is certified, which a plan does not know, so they
654/// are left to the device's own power range.
655#[cfg(feature = "us915")]
656pub static US915: ChannelPlan<'static> = ChannelPlan {
657    name: "US902-928",
658    uplink_data_rates: &US915_UPLINK_DATA_RATES,
659    downlink_data_rates: &US915_DOWNLINK_DATA_RATES,
660    max_payload_repeater: &US915_MAX_PAYLOAD_REPEATER,
661    max_payload_direct: &US915_MAX_PAYLOAD_DIRECT,
662    downlink_max_payload_repeater: &US915_DOWNLINK_MAX_PAYLOAD_REPEATER,
663    downlink_max_payload_direct: &US915_DOWNLINK_MAX_PAYLOAD_DIRECT,
664    max_payload_dwell_limited: None,
665    join_channels: &US915_JOIN_CHANNELS,
666    default_channels: &US915_CHANNELS,
667    sub_bands: &[],
668    default_max_eirp_dbm: 30,
669    tx_power_step_db: 2,
670    max_tx_power_index: 14,
671    rx1_data_rate_offsets: &US915_RX1,
672    rx1_data_rate_offsets_dwell_limited: None,
673    max_rx1_data_rate_offset: 3,
674    rx2_frequency_hz: 923_300_000,
675    rx2_data_rate: 8,
676    data_rate_backoff: &US915_BACKOFF,
677    beacon: Beacon {
678        data_rate: 8,
679        frequency_hz: 923_300_000,
680        ping_slot_frequency_hz: 923_300_000,
681    },
682    relay_channels: &US915_RELAY,
683    has_dwell_time_limit: true,
684    kind: PlanKind::Fixed,
685    tx_param_setup: false,
686    mask_controls: MASK_CONTROLS_900,
687    downlink_channels: &DOWNSTREAM_923,
688    join_sequence: JoinSequence::OctetPasses,
689    power_reference: PowerReference::Conducted {
690        gain_allowance_db: 6,
691    },
692    join_plans: &[],
693};
694
695// EU433, RP002-1.0.5 section 3.7.
696
697/// RP002-1.0.5 Table 30: EU433 data rate and TXPower.
698#[cfg(feature = "eu433")]
699static EU433_DATA_RATES: [Option<DataRate>; 14] = [
700    Some(DataRate::lora(12, 125_000, 250)),
701    Some(DataRate::lora(11, 125_000, 440)),
702    Some(DataRate::lora(10, 125_000, 980)),
703    Some(DataRate::lora(9, 125_000, 1_760)),
704    Some(DataRate::lora(8, 125_000, 3_125)),
705    Some(DataRate::lora(7, 125_000, 5_470)),
706    Some(DataRate::lora(7, 250_000, 11_000)),
707    Some(DataRate::fsk(50_000)),
708    None,
709    None,
710    None,
711    None,
712    Some(DataRate::lora(6, 125_000, 9_375)),
713    Some(DataRate::lora(5, 125_000, 15_625)),
714];
715
716/// RP002-1.0.5 Table 36: EU433 maximum payload size (repeater compatible).
717#[cfg(feature = "eu433")]
718static EU433_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 14] = [
719    Some(MaxPayload::new(59, 51)),
720    Some(MaxPayload::new(59, 51)),
721    Some(MaxPayload::new(59, 51)),
722    Some(MaxPayload::new(123, 115)),
723    Some(MaxPayload::new(230, 222)),
724    Some(MaxPayload::new(230, 222)),
725    Some(MaxPayload::new(230, 222)),
726    Some(MaxPayload::new(230, 222)),
727    None,
728    None,
729    None,
730    None,
731    Some(MaxPayload::new(230, 222)),
732    Some(MaxPayload::new(230, 222)),
733];
734
735/// RP002-1.0.5 Table 37: EU433 maximum payload size (not repeater compatible).
736#[cfg(feature = "eu433")]
737static EU433_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 14] = [
738    Some(MaxPayload::new(59, 51)),
739    Some(MaxPayload::new(59, 51)),
740    Some(MaxPayload::new(59, 51)),
741    Some(MaxPayload::new(123, 115)),
742    Some(MaxPayload::new(250, 242)),
743    Some(MaxPayload::new(250, 242)),
744    Some(MaxPayload::new(250, 242)),
745    Some(MaxPayload::new(250, 242)),
746    None,
747    None,
748    None,
749    None,
750    Some(MaxPayload::new(250, 242)),
751    Some(MaxPayload::new(250, 242)),
752];
753
754/// RP002-1.0.5 Table 38: EU433 downlink RX1 data rate mapping.
755///
756/// DR8 through DR11 are reserved in this region, so their rows carry the DR0
757/// fallback rather than a mapping the specification does not define.
758#[cfg(feature = "eu433")]
759static EU433_RX1: [&[u8]; 14] = [
760    &[0, 0, 0, 0, 0, 0],
761    &[1, 0, 0, 0, 0, 0],
762    &[2, 1, 0, 0, 0, 0],
763    &[3, 2, 1, 0, 0, 0],
764    &[4, 3, 2, 1, 0, 0],
765    &[5, 4, 3, 2, 1, 0],
766    &[6, 5, 4, 3, 2, 1],
767    &[7, 6, 5, 4, 3, 2],
768    &[0, 0, 0, 0, 0, 0],
769    &[0, 0, 0, 0, 0, 0],
770    &[0, 0, 0, 0, 0, 0],
771    &[0, 0, 0, 0, 0, 0],
772    &[12, 5, 4, 3, 2, 1],
773    &[13, 12, 5, 4, 3, 2],
774];
775
776/// RP002-1.0.5 Table 32: EU433 data rate back-off.
777#[cfg(feature = "eu433")]
778static EU433_BACKOFF: [Option<u8>; 14] = [
779    None,
780    Some(0),
781    Some(1),
782    Some(2),
783    Some(3),
784    Some(4),
785    Some(5),
786    Some(6),
787    None,
788    None,
789    None,
790    None,
791    Some(5),
792    Some(12),
793];
794
795/// RP002-1.0.5 Table 29: the three default and join channels.
796#[cfg(feature = "eu433")]
797static EU433_CHANNELS: [ChannelBlock; 1] = [ChannelBlock::new(433_175_000, 200_000, 3, 0, 5)];
798
799/// The whole EU433 band carries one limit: below 12 dBm EIRP and under 10% duty.
800#[cfg(feature = "eu433")]
801static EU433_SUB_BANDS: [SubBand; 1] = [SubBand::new(433_050_000, 434_790_000, 100, 12)];
802
803/// The EU433 channel plan, RP002-1.0.5 section 3.7.
804#[cfg(feature = "eu433")]
805pub static EU433: ChannelPlan<'static> = ChannelPlan {
806    name: "EU433",
807    uplink_data_rates: &EU433_DATA_RATES,
808    downlink_data_rates: &EU433_DATA_RATES,
809    max_payload_repeater: &EU433_MAX_PAYLOAD_REPEATER,
810    max_payload_direct: &EU433_MAX_PAYLOAD_DIRECT,
811    downlink_max_payload_repeater: &EU433_MAX_PAYLOAD_REPEATER,
812    downlink_max_payload_direct: &EU433_MAX_PAYLOAD_DIRECT,
813    max_payload_dwell_limited: None,
814    join_channels: &EU433_CHANNELS,
815    default_channels: &EU433_CHANNELS,
816    sub_bands: &EU433_SUB_BANDS,
817    default_max_eirp_dbm: 12,
818    tx_power_step_db: 2,
819    max_tx_power_index: 5,
820    rx1_data_rate_offsets: &EU433_RX1,
821    rx1_data_rate_offsets_dwell_limited: None,
822    max_rx1_data_rate_offset: 5,
823    rx2_frequency_hz: 434_665_000,
824    rx2_data_rate: 0,
825    data_rate_backoff: &EU433_BACKOFF,
826    beacon: Beacon {
827        data_rate: 3,
828        frequency_hz: 434_665_000,
829        ping_slot_frequency_hz: 434_665_000,
830    },
831    relay_channels: &[],
832    has_dwell_time_limit: false,
833    kind: PlanKind::Dynamic { channel_list: None },
834    tx_param_setup: false,
835    mask_controls: MaskControl::DYNAMIC,
836    downlink_channels: &[],
837    join_sequence: JoinSequence::Random,
838    power_reference: PowerReference::Eirp,
839    join_plans: &[],
840};
841
842// AU915-928, RP002-1.0.5 section 3.8.
843
844/// RP002-1.0.5 Table 39: AU915-928 uplink data rates.
845#[cfg(feature = "au915")]
846static AU915_UPLINK_DATA_RATES: [Option<DataRate>; 11] = [
847    Some(DataRate::lora(12, 125_000, 250)),
848    Some(DataRate::lora(11, 125_000, 440)),
849    Some(DataRate::lora(10, 125_000, 980)),
850    Some(DataRate::lora(9, 125_000, 1_760)),
851    Some(DataRate::lora(8, 125_000, 3_125)),
852    Some(DataRate::lora(7, 125_000, 5_470)),
853    Some(DataRate::lora(8, 500_000, 12_500)),
854    Some(DataRate::lr_fhss(1, 3, 1_523_000, 162)),
855    None,
856    Some(DataRate::lora(6, 125_000, 9_375)),
857    Some(DataRate::lora(5, 125_000, 15_625)),
858];
859
860/// RP002-1.0.5 Table 40: AU915-928 downlink data rates.
861#[cfg(feature = "au915")]
862static AU915_DOWNLINK_DATA_RATES: [Option<DataRate>; 15] = [
863    Some(DataRate::lora(5, 500_000, 62_500)),
864    None,
865    None,
866    None,
867    None,
868    None,
869    None,
870    None,
871    Some(DataRate::lora(12, 500_000, 980)),
872    Some(DataRate::lora(11, 500_000, 1_760)),
873    Some(DataRate::lora(10, 500_000, 3_900)),
874    Some(DataRate::lora(9, 500_000, 7_000)),
875    Some(DataRate::lora(8, 500_000, 12_500)),
876    Some(DataRate::lora(7, 500_000, 21_900)),
877    Some(DataRate::lora(6, 500_000, 37_500)),
878];
879
880/// RP002-1.0.5 Table 44: AU915-928 uplink maximum payload, no dwell limit.
881#[cfg(feature = "au915")]
882static AU915_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 11] = [
883    Some(MaxPayload::new(59, 51)),
884    Some(MaxPayload::new(59, 51)),
885    Some(MaxPayload::new(59, 51)),
886    Some(MaxPayload::new(123, 115)),
887    Some(MaxPayload::new(230, 222)),
888    Some(MaxPayload::new(230, 222)),
889    Some(MaxPayload::new(230, 222)),
890    Some(MaxPayload::new(58, 50)),
891    None,
892    Some(MaxPayload::new(230, 222)),
893    Some(MaxPayload::new(230, 222)),
894];
895
896/// RP002-1.0.5 Table 45: AU915-928 uplink maximum payload, no dwell limit.
897#[cfg(feature = "au915")]
898static AU915_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 11] = [
899    Some(MaxPayload::new(59, 51)),
900    Some(MaxPayload::new(59, 51)),
901    Some(MaxPayload::new(59, 51)),
902    Some(MaxPayload::new(123, 115)),
903    Some(MaxPayload::new(250, 242)),
904    Some(MaxPayload::new(250, 242)),
905    Some(MaxPayload::new(250, 242)),
906    Some(MaxPayload::new(58, 50)),
907    None,
908    Some(MaxPayload::new(250, 242)),
909    Some(MaxPayload::new(250, 242)),
910];
911
912/// RP002-1.0.5 Table 44: AU915-928 uplink maximum payload under a 400 ms dwell.
913///
914/// The two slowest data rates carry nothing at all inside 400 ms, which is why
915/// a device boots assuming the limit applies until told otherwise.
916#[cfg(feature = "au915")]
917static AU915_MAX_PAYLOAD_DWELL: [Option<MaxPayload>; 11] = [
918    None,
919    None,
920    Some(MaxPayload::new(19, 11)),
921    Some(MaxPayload::new(61, 53)),
922    Some(MaxPayload::new(133, 125)),
923    Some(MaxPayload::new(230, 222)),
924    Some(MaxPayload::new(230, 222)),
925    Some(MaxPayload::new(58, 50)),
926    None,
927    Some(MaxPayload::new(230, 222)),
928    Some(MaxPayload::new(230, 222)),
929];
930
931/// RP002-1.0.5 Table 44: AU915-928 downlink maximum payload (repeater compatible).
932#[cfg(feature = "au915")]
933static AU915_DOWNLINK_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 15] = [
934    Some(MaxPayload::new(230, 222)),
935    None,
936    None,
937    None,
938    None,
939    None,
940    None,
941    None,
942    Some(MaxPayload::new(61, 53)),
943    Some(MaxPayload::new(137, 129)),
944    Some(MaxPayload::new(230, 222)),
945    Some(MaxPayload::new(230, 222)),
946    Some(MaxPayload::new(230, 222)),
947    Some(MaxPayload::new(230, 222)),
948    Some(MaxPayload::new(230, 222)),
949];
950
951/// RP002-1.0.5 Table 45: AU915-928 downlink maximum payload (not repeater compatible).
952#[cfg(feature = "au915")]
953static AU915_DOWNLINK_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 15] = [
954    Some(MaxPayload::new(250, 242)),
955    None,
956    None,
957    None,
958    None,
959    None,
960    None,
961    None,
962    Some(MaxPayload::new(61, 53)),
963    Some(MaxPayload::new(137, 129)),
964    Some(MaxPayload::new(250, 242)),
965    Some(MaxPayload::new(250, 242)),
966    Some(MaxPayload::new(250, 242)),
967    Some(MaxPayload::new(250, 242)),
968    Some(MaxPayload::new(250, 242)),
969];
970
971/// RP002-1.0.5 Table 46: AU915-928 downlink RX1 data rate mapping.
972#[cfg(feature = "au915")]
973static AU915_RX1: [&[u8]; 11] = [
974    &[8, 8, 8, 8, 8, 8],
975    &[9, 8, 8, 8, 8, 8],
976    &[10, 9, 8, 8, 8, 8],
977    &[11, 10, 9, 8, 8, 8],
978    &[12, 11, 10, 9, 8, 8],
979    &[13, 12, 11, 10, 9, 8],
980    &[13, 13, 12, 11, 10, 9],
981    &[9, 8, 8, 8, 8, 8],
982    &[8, 8, 8, 8, 8, 8],
983    &[14, 13, 12, 11, 10, 9],
984    &[0, 14, 13, 12, 11, 10],
985];
986
987/// RP002-1.0.5 Table 41: AU915-928 uplink data rate back-off, no dwell limit.
988#[cfg(feature = "au915")]
989static AU915_BACKOFF: [Option<u8>; 11] = [
990    None,
991    Some(0),
992    Some(1),
993    Some(2),
994    Some(3),
995    Some(4),
996    Some(5),
997    Some(0),
998    None,
999    Some(5),
1000    Some(9),
1001];
1002
1003/// The 64 125 kHz uplink channels and the 8 500 kHz ones, section 3.8.2.
1004#[cfg(feature = "au915")]
1005static AU915_CHANNELS: [ChannelBlock; 2] = [
1006    ChannelBlock::new(915_200_000, 200_000, 64, 0, 5),
1007    ChannelBlock::new(915_900_000, 1_600_000, 8, 6, 7),
1008];
1009
1010/// The join channels: a random 125 kHz channel at DR2, which fits inside the 400 ms dwell
1011/// time a device assumes until told otherwise, and a 500 kHz one at DR6, section 3.8.2.
1012#[cfg(feature = "au915")]
1013static AU915_JOIN_CHANNELS: [ChannelBlock; 2] = [
1014    ChannelBlock::new(915_200_000, 200_000, 64, 2, 2),
1015    ChannelBlock::new(915_900_000, 1_600_000, 8, 6, 6),
1016];
1017
1018/// RP002-1.0.5 table 48: SF10 at 500 kHz, downlink DR10.
1019#[cfg(feature = "au915")]
1020static AU915_RELAY: [RelayChannel; 2] = [
1021    RelayChannel::new(916_700_000, 918_300_000, 10),
1022    RelayChannel::new(919_900_000, 921_500_000, 10),
1023];
1024
1025/// The AU915-928 channel plan, RP002-1.0.5 section 3.8.
1026///
1027/// Australia limits transmissions by dwell time rather than duty cycle, so
1028/// [`duty_cycle_permille`](ChannelPlan::duty_cycle_permille) reports nothing and
1029/// the dwell-limited payload table is the one that matters until the network
1030/// says otherwise.
1031#[cfg(feature = "au915")]
1032pub static AU915: ChannelPlan<'static> = ChannelPlan {
1033    name: "AU915-928",
1034    uplink_data_rates: &AU915_UPLINK_DATA_RATES,
1035    downlink_data_rates: &AU915_DOWNLINK_DATA_RATES,
1036    max_payload_repeater: &AU915_MAX_PAYLOAD_REPEATER,
1037    max_payload_direct: &AU915_MAX_PAYLOAD_DIRECT,
1038    downlink_max_payload_repeater: &AU915_DOWNLINK_MAX_PAYLOAD_REPEATER,
1039    downlink_max_payload_direct: &AU915_DOWNLINK_MAX_PAYLOAD_DIRECT,
1040    max_payload_dwell_limited: Some(&AU915_MAX_PAYLOAD_DWELL),
1041    join_channels: &AU915_JOIN_CHANNELS,
1042    default_channels: &AU915_CHANNELS,
1043    sub_bands: &[],
1044    default_max_eirp_dbm: 30,
1045    tx_power_step_db: 2,
1046    max_tx_power_index: 14,
1047    rx1_data_rate_offsets: &AU915_RX1,
1048    rx1_data_rate_offsets_dwell_limited: None,
1049    max_rx1_data_rate_offset: 5,
1050    rx2_frequency_hz: 923_300_000,
1051    rx2_data_rate: 8,
1052    data_rate_backoff: &AU915_BACKOFF,
1053    beacon: Beacon {
1054        data_rate: 8,
1055        frequency_hz: 923_300_000,
1056        ping_slot_frequency_hz: 923_300_000,
1057    },
1058    relay_channels: &AU915_RELAY,
1059    has_dwell_time_limit: true,
1060    kind: PlanKind::Fixed,
1061    tx_param_setup: true,
1062    mask_controls: MASK_CONTROLS_900,
1063    downlink_channels: &DOWNSTREAM_923,
1064    join_sequence: JoinSequence::OctetPasses,
1065    power_reference: PowerReference::Eirp,
1066    join_plans: &[],
1067};
1068
1069// CN470-510, RP002-1.0.5 section 3.9.
1070
1071/// RP002-1.0.5 Table 50: CN470-510 data rate and TXPower.
1072#[cfg(feature = "cn470")]
1073static CN470_DATA_RATES: [Option<DataRate>; 8] = [
1074    Some(DataRate::lora(12, 125_000, 250)),
1075    Some(DataRate::lora(11, 125_000, 440)),
1076    Some(DataRate::lora(10, 125_000, 980)),
1077    Some(DataRate::lora(9, 125_000, 1_760)),
1078    Some(DataRate::lora(8, 125_000, 3_125)),
1079    Some(DataRate::lora(7, 125_000, 5_470)),
1080    Some(DataRate::lora(7, 500_000, 21_900)),
1081    Some(DataRate::fsk(50_000)),
1082];
1083
1084/// RP002-1.0.5 Table 54: CN470-510 maximum payload size (repeater compatible).
1085///
1086/// DR0 carries nothing: at SF12 the one-second transmission limit this band
1087/// works under leaves no room for a frame.
1088#[cfg(feature = "cn470")]
1089static CN470_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 8] = [
1090    None,
1091    Some(MaxPayload::new(31, 23)),
1092    Some(MaxPayload::new(94, 86)),
1093    Some(MaxPayload::new(192, 184)),
1094    Some(MaxPayload::new(230, 222)),
1095    Some(MaxPayload::new(230, 222)),
1096    Some(MaxPayload::new(230, 222)),
1097    Some(MaxPayload::new(230, 222)),
1098];
1099
1100/// RP002-1.0.5 Table 55: CN470-510 maximum payload size (not repeater compatible).
1101#[cfg(feature = "cn470")]
1102static CN470_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 8] = [
1103    None,
1104    Some(MaxPayload::new(31, 23)),
1105    Some(MaxPayload::new(94, 86)),
1106    Some(MaxPayload::new(192, 184)),
1107    Some(MaxPayload::new(250, 242)),
1108    Some(MaxPayload::new(250, 242)),
1109    Some(MaxPayload::new(250, 242)),
1110    Some(MaxPayload::new(250, 242)),
1111];
1112
1113/// RP002-1.0.5 Table 56: CN470-510 downlink RX1 data rate mapping.
1114#[cfg(feature = "cn470")]
1115static CN470_RX1: [&[u8]; 8] = [
1116    &[0, 0, 0, 0, 0, 0],
1117    &[1, 1, 1, 1, 1, 1],
1118    &[2, 1, 1, 1, 1, 1],
1119    &[3, 2, 1, 1, 1, 1],
1120    &[4, 3, 2, 1, 1, 1],
1121    &[5, 4, 3, 2, 1, 1],
1122    &[6, 5, 4, 3, 2, 1],
1123    &[7, 6, 5, 4, 3, 2],
1124];
1125
1126/// RP002-1.0.5 Table 51: CN470-510 data rate back-off.
1127#[cfg(feature = "cn470")]
1128static CN470_BACKOFF: [Option<u8>; 8] = [
1129    None,
1130    Some(0),
1131    Some(1),
1132    Some(2),
1133    Some(3),
1134    Some(4),
1135    Some(5),
1136    Some(6),
1137];
1138
1139/// RP002-1.0.5 table 52: the `ChMaskCntl` values of the 20 MHz antenna plans.
1140#[cfg(feature = "cn470")]
1141const CN470_MASK_CONTROLS_20: [MaskControl; 8] = [
1142    MaskControl::Group(0),
1143    MaskControl::Group(1),
1144    MaskControl::Group(2),
1145    MaskControl::Group(3),
1146    MaskControl::Reserved,
1147    MaskControl::Reserved,
1148    MaskControl::All {
1149        on: true,
1150        then_group: None,
1151    },
1152    MaskControl::All {
1153        on: false,
1154        then_group: None,
1155    },
1156];
1157
1158/// RP002-1.0.5 table 53: the `ChMaskCntl` values of the 26 MHz antenna plans.
1159#[cfg(feature = "cn470")]
1160const CN470_MASK_CONTROLS_26: [MaskControl; 8] = [
1161    MaskControl::Group(0),
1162    MaskControl::Group(1),
1163    MaskControl::Group(2),
1164    MaskControl::All {
1165        on: true,
1166        then_group: None,
1167    },
1168    MaskControl::All {
1169        on: false,
1170        then_group: None,
1171    },
1172    MaskControl::Reserved,
1173    MaskControl::Reserved,
1174    MaskControl::Reserved,
1175];
1176
1177/// The uplink groups of the 20 MHz antenna's plan A, section 3.9.2.1: channels 0 to 31 from
1178/// 470.3 MHz and 32 to 63 from 503.5 MHz.
1179#[cfg(feature = "cn470")]
1180static CN470_20A_UPLINK: [ChannelBlock; 2] = [
1181    ChannelBlock::new(470_300_000, 200_000, 32, 0, 5),
1182    ChannelBlock::new(503_500_000, 200_000, 32, 0, 5),
1183];
1184
1185/// The downlink groups of the 20 MHz antenna's plan A: channels 0 to 31 from 483.9 MHz and 32
1186/// to 63 from 490.3 MHz, each answering the uplink channel of the same number.
1187#[cfg(feature = "cn470")]
1188static CN470_20A_DOWNLINK: [ChannelBlock; 2] = [
1189    ChannelBlock::new(483_900_000, 200_000, 32, 0, 5),
1190    ChannelBlock::new(490_300_000, 200_000, 32, 0, 5),
1191];
1192
1193/// The groups of the 20 MHz antenna's plan B, section 3.9.2.1, which uplink and downlink
1194/// share: channels 0 to 31 from 476.9 MHz and 32 to 63 from 496.9 MHz.
1195#[cfg(feature = "cn470")]
1196static CN470_20B_CHANNELS: [ChannelBlock; 2] = [
1197    ChannelBlock::new(476_900_000, 200_000, 32, 0, 5),
1198    ChannelBlock::new(496_900_000, 200_000, 32, 0, 5),
1199];
1200
1201/// The 48 uplink channels of the 26 MHz antenna's plan A, section 3.9.2.2, from 470.3 MHz.
1202#[cfg(feature = "cn470")]
1203static CN470_26A_UPLINK: [ChannelBlock; 1] = [ChannelBlock::new(470_300_000, 200_000, 48, 0, 5)];
1204
1205/// The 24 downlink channels of the 26 MHz antenna's plan A, from 490.1 MHz.
1206#[cfg(feature = "cn470")]
1207static CN470_26A_DOWNLINK: [ChannelBlock; 1] = [ChannelBlock::new(490_100_000, 200_000, 24, 0, 5)];
1208
1209/// The 48 uplink channels of the 26 MHz antenna's plan B, section 3.9.2.2, from 480.3 MHz.
1210#[cfg(feature = "cn470")]
1211static CN470_26B_UPLINK: [ChannelBlock; 1] = [ChannelBlock::new(480_300_000, 200_000, 48, 0, 5)];
1212
1213/// The 24 downlink channels of the 26 MHz antenna's plan B, from 500.1 MHz.
1214#[cfg(feature = "cn470")]
1215static CN470_26B_DOWNLINK: [ChannelBlock; 1] = [ChannelBlock::new(500_100_000, 200_000, 24, 0, 5)];
1216
1217/// The twenty common join channels of RP002-1.0.5 table 49, in the table's order.
1218#[cfg(feature = "cn470")]
1219const CN470_JOIN_CHANNELS: [ChannelBlock; 5] = [
1220    ChannelBlock::new(470_900_000, 1_600_000, 4, 0, 5),
1221    ChannelBlock::new(504_100_000, 1_600_000, 4, 0, 5),
1222    ChannelBlock::new(479_900_000, 20_000_000, 2, 0, 5),
1223    ChannelBlock::new(470_300_000, 2_000_000, 5, 0, 5),
1224    ChannelBlock::new(480_300_000, 2_000_000, 5, 0, 5),
1225];
1226
1227/// Which plan each common join channel puts a device on, RP002-1.0.5 table 49, where its join
1228/// accept arrives, the table's DL column, and where the second receive window listens once
1229/// joined, tables 57 and 58 and section 3.9.7.2.
1230#[cfg(feature = "cn470")]
1231static CN470_JOIN_PLANS: [JoinPlan<'static>; 5] = [
1232    JoinPlan::new(
1233        CN470_JOIN_CHANNELS[0],
1234        (484_500_000, 1_600_000),
1235        (485_300_000, 1_600_000),
1236        &CN470,
1237    ),
1238    JoinPlan::new(
1239        CN470_JOIN_CHANNELS[1],
1240        (490_900_000, 1_600_000),
1241        (491_700_000, 1_600_000),
1242        &CN470,
1243    ),
1244    JoinPlan::new(
1245        CN470_JOIN_CHANNELS[2],
1246        (479_900_000, 20_000_000),
1247        (478_300_000, 20_000_000),
1248        &CN470_20B,
1249    ),
1250    JoinPlan::new(
1251        CN470_JOIN_CHANNELS[3],
1252        (492_500_000, 0),
1253        (492_500_000, 0),
1254        &CN470_26A,
1255    ),
1256    JoinPlan::new(
1257        CN470_JOIN_CHANNELS[4],
1258        (502_500_000, 0),
1259        (502_500_000, 0),
1260        &CN470_26B,
1261    ),
1262];
1263
1264/// RP002-1.0.5 table 64: SF9 and SF7 at 125 kHz, the same for every CN470-510 plan.
1265#[cfg(feature = "cn470")]
1266static CN470_RELAY: [RelayChannel; 2] = [
1267    RelayChannel::new(472_100_000, 485_300_000, 3),
1268    RelayChannel::new(494_900_000, 505_500_000, 5),
1269];
1270
1271/// The CN470-510 channel plan for a 20 MHz antenna, type A, RP002-1.0.5 section 3.9.
1272///
1273/// RP002-1.0.5 divides the band into four plans, for 20 MHz and 26 MHz antennas, each with a
1274/// type A and B, and marks them experimental pending regulatory approval. A device joining
1275/// over the air scans the twenty common join channels every plan shares and follows the plan
1276/// the channel that answered belongs to, so any of the four serves to join with. A
1277/// personalized device is set up on one; the second receive window here is the personalized
1278/// default, 486.9 MHz, which a join replaces with the one its join channel names.
1279///
1280/// The beacon hops over the downlink channels, and the frequency given is the first of them.
1281/// Transmissions in this band are limited to one second on one channel at a time, with
1282/// listen-before-talk rather than a duty cycle.
1283#[cfg(feature = "cn470")]
1284pub static CN470: ChannelPlan<'static> = ChannelPlan {
1285    name: "CN470-510",
1286    uplink_data_rates: &CN470_DATA_RATES,
1287    downlink_data_rates: &CN470_DATA_RATES,
1288    max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1289    max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1290    downlink_max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1291    downlink_max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1292    max_payload_dwell_limited: None,
1293    join_channels: &CN470_JOIN_CHANNELS,
1294    default_channels: &CN470_20A_UPLINK,
1295    sub_bands: &[],
1296    default_max_eirp_dbm: 19,
1297    tx_power_step_db: 2,
1298    max_tx_power_index: 7,
1299    rx1_data_rate_offsets: &CN470_RX1,
1300    rx1_data_rate_offsets_dwell_limited: None,
1301    max_rx1_data_rate_offset: 5,
1302    rx2_frequency_hz: 486_900_000,
1303    rx2_data_rate: 1,
1304    data_rate_backoff: &CN470_BACKOFF,
1305    beacon: Beacon {
1306        data_rate: 2,
1307        frequency_hz: 483_900_000,
1308        ping_slot_frequency_hz: 483_900_000,
1309    },
1310    relay_channels: &CN470_RELAY,
1311    has_dwell_time_limit: false,
1312    kind: PlanKind::Fixed,
1313    tx_param_setup: false,
1314    mask_controls: CN470_MASK_CONTROLS_20,
1315    downlink_channels: &CN470_20A_DOWNLINK,
1316    join_sequence: JoinSequence::Random,
1317    power_reference: PowerReference::Eirp,
1318    join_plans: &CN470_JOIN_PLANS,
1319};
1320
1321/// The CN470-510 channel plan for a 20 MHz antenna, type B, RP002-1.0.5 section 3.9.
1322///
1323/// Uplink and downlink share the same 64 channels. The second receive window of a personalized
1324/// device is 498.3 MHz, section 3.9.7.1, and the beacon goes out on channel 23 or 55 by the
1325/// join channel, tables 62 and 63; the frequency given is channel 23's.
1326#[cfg(feature = "cn470")]
1327pub static CN470_20B: ChannelPlan<'static> = ChannelPlan {
1328    name: "CN470-510",
1329    uplink_data_rates: &CN470_DATA_RATES,
1330    downlink_data_rates: &CN470_DATA_RATES,
1331    max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1332    max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1333    downlink_max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1334    downlink_max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1335    max_payload_dwell_limited: None,
1336    join_channels: &CN470_JOIN_CHANNELS,
1337    default_channels: &CN470_20B_CHANNELS,
1338    sub_bands: &[],
1339    default_max_eirp_dbm: 19,
1340    tx_power_step_db: 2,
1341    max_tx_power_index: 7,
1342    rx1_data_rate_offsets: &CN470_RX1,
1343    rx1_data_rate_offsets_dwell_limited: None,
1344    max_rx1_data_rate_offset: 5,
1345    rx2_frequency_hz: 498_300_000,
1346    rx2_data_rate: 1,
1347    data_rate_backoff: &CN470_BACKOFF,
1348    beacon: Beacon {
1349        data_rate: 2,
1350        frequency_hz: 481_500_000,
1351        ping_slot_frequency_hz: 476_900_000,
1352    },
1353    relay_channels: &CN470_RELAY,
1354    has_dwell_time_limit: false,
1355    kind: PlanKind::Fixed,
1356    tx_param_setup: false,
1357    mask_controls: CN470_MASK_CONTROLS_20,
1358    downlink_channels: &CN470_20B_CHANNELS,
1359    join_sequence: JoinSequence::Random,
1360    power_reference: PowerReference::Eirp,
1361    join_plans: &CN470_JOIN_PLANS,
1362};
1363
1364/// The CN470-510 channel plan for a 26 MHz antenna, type A, RP002-1.0.5 section 3.9.
1365///
1366/// Its 48 uplink channels answer on 24 downlink channels, channel `n` on downlink channel `n`
1367/// modulo 24, section 3.9.7.2. The second receive window listens on 492.5 MHz and the beacon
1368/// on 494.9 MHz, section 3.9.8.2.
1369#[cfg(feature = "cn470")]
1370pub static CN470_26A: ChannelPlan<'static> = ChannelPlan {
1371    name: "CN470-510",
1372    uplink_data_rates: &CN470_DATA_RATES,
1373    downlink_data_rates: &CN470_DATA_RATES,
1374    max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1375    max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1376    downlink_max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1377    downlink_max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1378    max_payload_dwell_limited: None,
1379    join_channels: &CN470_JOIN_CHANNELS,
1380    default_channels: &CN470_26A_UPLINK,
1381    sub_bands: &[],
1382    default_max_eirp_dbm: 19,
1383    tx_power_step_db: 2,
1384    max_tx_power_index: 7,
1385    rx1_data_rate_offsets: &CN470_RX1,
1386    rx1_data_rate_offsets_dwell_limited: None,
1387    max_rx1_data_rate_offset: 5,
1388    rx2_frequency_hz: 492_500_000,
1389    rx2_data_rate: 1,
1390    data_rate_backoff: &CN470_BACKOFF,
1391    beacon: Beacon {
1392        data_rate: 2,
1393        frequency_hz: 494_900_000,
1394        ping_slot_frequency_hz: 494_900_000,
1395    },
1396    relay_channels: &CN470_RELAY,
1397    has_dwell_time_limit: false,
1398    kind: PlanKind::Fixed,
1399    tx_param_setup: false,
1400    mask_controls: CN470_MASK_CONTROLS_26,
1401    downlink_channels: &CN470_26A_DOWNLINK,
1402    join_sequence: JoinSequence::Random,
1403    power_reference: PowerReference::Eirp,
1404    join_plans: &CN470_JOIN_PLANS,
1405};
1406
1407/// The CN470-510 channel plan for a 26 MHz antenna, type B, RP002-1.0.5 section 3.9.
1408///
1409/// As type A, from 480.3 MHz up and 500.1 MHz down, with the second receive window on 502.5
1410/// MHz and the beacon on 504.9 MHz.
1411#[cfg(feature = "cn470")]
1412pub static CN470_26B: ChannelPlan<'static> = ChannelPlan {
1413    name: "CN470-510",
1414    uplink_data_rates: &CN470_DATA_RATES,
1415    downlink_data_rates: &CN470_DATA_RATES,
1416    max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1417    max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1418    downlink_max_payload_repeater: &CN470_MAX_PAYLOAD_REPEATER,
1419    downlink_max_payload_direct: &CN470_MAX_PAYLOAD_DIRECT,
1420    max_payload_dwell_limited: None,
1421    join_channels: &CN470_JOIN_CHANNELS,
1422    default_channels: &CN470_26B_UPLINK,
1423    sub_bands: &[],
1424    default_max_eirp_dbm: 19,
1425    tx_power_step_db: 2,
1426    max_tx_power_index: 7,
1427    rx1_data_rate_offsets: &CN470_RX1,
1428    rx1_data_rate_offsets_dwell_limited: None,
1429    max_rx1_data_rate_offset: 5,
1430    rx2_frequency_hz: 502_500_000,
1431    rx2_data_rate: 1,
1432    data_rate_backoff: &CN470_BACKOFF,
1433    beacon: Beacon {
1434        data_rate: 2,
1435        frequency_hz: 504_900_000,
1436        ping_slot_frequency_hz: 504_900_000,
1437    },
1438    relay_channels: &CN470_RELAY,
1439    has_dwell_time_limit: false,
1440    kind: PlanKind::Fixed,
1441    tx_param_setup: false,
1442    mask_controls: CN470_MASK_CONTROLS_26,
1443    downlink_channels: &CN470_26B_DOWNLINK,
1444    join_sequence: JoinSequence::Random,
1445    power_reference: PowerReference::Eirp,
1446    join_plans: &CN470_JOIN_PLANS,
1447};
1448
1449// CN470-510 with 96 channels, LoRaWAN 1.0.3 Regional Parameters revision A section 2.7.
1450
1451/// Revision A table 42: the 96-channel plan's data rates, SF12 to SF7 at 125 kHz.
1452#[cfg(feature = "cn470")]
1453static CN470_96_DATA_RATES: [Option<DataRate>; 6] = [
1454    Some(DataRate::lora(12, 125_000, 250)),
1455    Some(DataRate::lora(11, 125_000, 440)),
1456    Some(DataRate::lora(10, 125_000, 980)),
1457    Some(DataRate::lora(9, 125_000, 1_760)),
1458    Some(DataRate::lora(8, 125_000, 3_125)),
1459    Some(DataRate::lora(7, 125_000, 5_470)),
1460];
1461
1462/// Revision A table 44: the 96-channel plan's maximum payload (repeater compatible).
1463#[cfg(feature = "cn470")]
1464static CN470_96_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 6] = [
1465    Some(MaxPayload::new(59, 51)),
1466    Some(MaxPayload::new(59, 51)),
1467    Some(MaxPayload::new(59, 51)),
1468    Some(MaxPayload::new(123, 115)),
1469    Some(MaxPayload::new(230, 222)),
1470    Some(MaxPayload::new(230, 222)),
1471];
1472
1473/// Revision A table 45: the 96-channel plan's maximum payload (not repeater compatible).
1474#[cfg(feature = "cn470")]
1475static CN470_96_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 6] = [
1476    Some(MaxPayload::new(59, 51)),
1477    Some(MaxPayload::new(59, 51)),
1478    Some(MaxPayload::new(59, 51)),
1479    Some(MaxPayload::new(123, 115)),
1480    Some(MaxPayload::new(250, 242)),
1481    Some(MaxPayload::new(250, 242)),
1482];
1483
1484/// Revision A table 46: the 96-channel plan's downlink RX1 data rate mapping.
1485#[cfg(feature = "cn470")]
1486static CN470_96_RX1: [&[u8]; 6] = [
1487    &[0, 0, 0, 0, 0, 0],
1488    &[1, 0, 0, 0, 0, 0],
1489    &[2, 1, 0, 0, 0, 0],
1490    &[3, 2, 1, 0, 0, 0],
1491    &[4, 3, 2, 1, 0, 0],
1492    &[5, 4, 3, 2, 1, 0],
1493];
1494
1495/// The 96-channel plan steps down one data rate at a time; revision A publishes no other
1496/// back-off table.
1497#[cfg(feature = "cn470")]
1498static CN470_96_BACKOFF: [Option<u8>; 6] = [None, Some(0), Some(1), Some(2), Some(3), Some(4)];
1499
1500/// The 96 uplink channels, 470.3 to 489.3 MHz, revision A section 2.7.2.
1501#[cfg(feature = "cn470")]
1502static CN470_96_UPLINK: [ChannelBlock; 1] = [ChannelBlock::new(470_300_000, 200_000, 96, 0, 5)];
1503
1504/// The 48 downlink channels, 500.3 to 509.7 MHz, answering uplink channel `n` on downlink
1505/// channel `n` modulo 48, revision A section 2.7.7.
1506#[cfg(feature = "cn470")]
1507static CN470_96_DOWNLINK: [ChannelBlock; 1] = [ChannelBlock::new(500_300_000, 200_000, 48, 0, 5)];
1508
1509/// Revision A table 43: the 96-channel plan's `ChMaskCntl` values.
1510#[cfg(feature = "cn470")]
1511const CN470_96_MASK_CONTROLS: [MaskControl; 8] = [
1512    MaskControl::Group(0),
1513    MaskControl::Group(1),
1514    MaskControl::Group(2),
1515    MaskControl::Group(3),
1516    MaskControl::Group(4),
1517    MaskControl::Group(5),
1518    MaskControl::All {
1519        on: true,
1520        then_group: None,
1521    },
1522    MaskControl::Reserved,
1523];
1524
1525/// The 96-channel CN470-510 plan of the LoRaWAN 1.0.3 Regional Parameters, revision A.
1526///
1527/// RP002-1.0.5 replaced it with the four antenna plans, and notes that this one "is still in
1528/// widespread use". A device joins on any of its 96 uplink channels from DR5 down to DR0, and
1529/// the second receive window listens on 505.3 MHz at DR0. The beacon hops over 508.3 to 509.7
1530/// MHz, and the frequency given is the first.
1531#[cfg(feature = "cn470")]
1532pub static CN470_96: ChannelPlan<'static> = ChannelPlan {
1533    name: "CN470-510",
1534    uplink_data_rates: &CN470_96_DATA_RATES,
1535    downlink_data_rates: &CN470_96_DATA_RATES,
1536    max_payload_repeater: &CN470_96_MAX_PAYLOAD_REPEATER,
1537    max_payload_direct: &CN470_96_MAX_PAYLOAD_DIRECT,
1538    downlink_max_payload_repeater: &CN470_96_MAX_PAYLOAD_REPEATER,
1539    downlink_max_payload_direct: &CN470_96_MAX_PAYLOAD_DIRECT,
1540    max_payload_dwell_limited: None,
1541    join_channels: &CN470_96_UPLINK,
1542    default_channels: &CN470_96_UPLINK,
1543    sub_bands: &[],
1544    default_max_eirp_dbm: 19,
1545    tx_power_step_db: 2,
1546    max_tx_power_index: 7,
1547    rx1_data_rate_offsets: &CN470_96_RX1,
1548    rx1_data_rate_offsets_dwell_limited: None,
1549    max_rx1_data_rate_offset: 5,
1550    rx2_frequency_hz: 505_300_000,
1551    rx2_data_rate: 0,
1552    data_rate_backoff: &CN470_96_BACKOFF,
1553    beacon: Beacon {
1554        data_rate: 2,
1555        frequency_hz: 508_300_000,
1556        ping_slot_frequency_hz: 508_300_000,
1557    },
1558    relay_channels: &[],
1559    has_dwell_time_limit: false,
1560    kind: PlanKind::Fixed,
1561    tx_param_setup: false,
1562    mask_controls: CN470_96_MASK_CONTROLS,
1563    downlink_channels: &CN470_96_DOWNLINK,
1564    join_sequence: JoinSequence::Random,
1565    power_reference: PowerReference::Eirp,
1566    join_plans: &[],
1567};
1568
1569// AS923, RP002-1.0.5 section 3.10.
1570
1571/// RP002-1.0.5 Table 67: AS923 data rate.
1572#[cfg(feature = "as923")]
1573static AS923_DATA_RATES: [Option<DataRate>; 14] = [
1574    Some(DataRate::lora(12, 125_000, 250)),
1575    Some(DataRate::lora(11, 125_000, 440)),
1576    Some(DataRate::lora(10, 125_000, 980)),
1577    Some(DataRate::lora(9, 125_000, 1_760)),
1578    Some(DataRate::lora(8, 125_000, 3_125)),
1579    Some(DataRate::lora(7, 125_000, 5_470)),
1580    Some(DataRate::lora(7, 250_000, 11_000)),
1581    Some(DataRate::fsk(50_000)),
1582    None,
1583    None,
1584    None,
1585    None,
1586    Some(DataRate::lora(6, 125_000, 9_375)),
1587    Some(DataRate::lora(5, 125_000, 15_625)),
1588];
1589
1590/// RP002-1.0.5 Table 72: AS923 maximum payload size (repeater compatible).
1591#[cfg(feature = "as923")]
1592static AS923_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 14] = [
1593    Some(MaxPayload::new(59, 51)),
1594    Some(MaxPayload::new(59, 51)),
1595    Some(MaxPayload::new(123, 115)),
1596    Some(MaxPayload::new(123, 115)),
1597    Some(MaxPayload::new(230, 222)),
1598    Some(MaxPayload::new(230, 222)),
1599    Some(MaxPayload::new(230, 222)),
1600    Some(MaxPayload::new(230, 222)),
1601    None,
1602    None,
1603    None,
1604    None,
1605    Some(MaxPayload::new(230, 222)),
1606    Some(MaxPayload::new(230, 222)),
1607];
1608
1609/// RP002-1.0.5 Table 73: AS923 maximum payload size (not repeater compatible).
1610#[cfg(feature = "as923")]
1611static AS923_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 14] = [
1612    Some(MaxPayload::new(59, 51)),
1613    Some(MaxPayload::new(59, 51)),
1614    Some(MaxPayload::new(123, 115)),
1615    Some(MaxPayload::new(123, 115)),
1616    Some(MaxPayload::new(250, 242)),
1617    Some(MaxPayload::new(250, 242)),
1618    Some(MaxPayload::new(250, 242)),
1619    Some(MaxPayload::new(250, 242)),
1620    None,
1621    None,
1622    None,
1623    None,
1624    Some(MaxPayload::new(250, 242)),
1625    Some(MaxPayload::new(250, 242)),
1626];
1627
1628/// RP002-1.0.5 Table 74: AS923 RX1 mapping with no downlink dwell limit.
1629#[cfg(feature = "as923")]
1630static AS923_RX1: [&[u8]; 14] = [
1631    &[0, 0, 0, 0, 0, 0, 1, 2],
1632    &[1, 0, 0, 0, 0, 0, 2, 3],
1633    &[2, 1, 0, 0, 0, 0, 3, 4],
1634    &[3, 2, 1, 0, 0, 0, 4, 5],
1635    &[4, 3, 2, 1, 0, 0, 5, 6],
1636    &[5, 4, 3, 2, 1, 0, 6, 7],
1637    &[6, 5, 4, 3, 2, 1, 7, 7],
1638    &[7, 6, 5, 4, 3, 2, 7, 7],
1639    &[0, 0, 0, 0, 0, 0, 1, 2],
1640    &[0, 0, 0, 0, 0, 0, 1, 2],
1641    &[0, 0, 0, 0, 0, 0, 1, 2],
1642    &[0, 0, 0, 0, 0, 0, 1, 2],
1643    &[12, 5, 4, 3, 2, 1, 13, 13],
1644    &[13, 12, 5, 4, 3, 2, 13, 13],
1645];
1646
1647/// RP002-1.0.5 Table 75: AS923 RX1 mapping under a downlink dwell limit.
1648#[cfg(feature = "as923")]
1649static AS923_RX1_DWELL: [&[u8]; 14] = [
1650    &[2, 2, 2, 2, 2, 2, 2, 2],
1651    &[2, 2, 2, 2, 2, 2, 2, 3],
1652    &[2, 2, 2, 2, 2, 2, 3, 4],
1653    &[3, 2, 2, 2, 2, 2, 4, 5],
1654    &[4, 3, 2, 2, 2, 2, 5, 6],
1655    &[5, 4, 3, 2, 2, 2, 6, 7],
1656    &[6, 5, 4, 3, 2, 2, 7, 7],
1657    &[7, 6, 5, 4, 3, 2, 7, 7],
1658    &[2, 2, 2, 2, 2, 2, 2, 2],
1659    &[2, 2, 2, 2, 2, 2, 2, 2],
1660    &[2, 2, 2, 2, 2, 2, 2, 2],
1661    &[2, 2, 2, 2, 2, 2, 2, 2],
1662    &[12, 5, 4, 3, 2, 2, 13, 13],
1663    &[13, 12, 5, 4, 3, 2, 13, 13],
1664];
1665
1666/// RP002-1.0.5 Table 69: AS923 data rate back-off.
1667#[cfg(feature = "as923")]
1668static AS923_BACKOFF: [Option<u8>; 14] = [
1669    None,
1670    Some(0),
1671    Some(1),
1672    Some(2),
1673    Some(3),
1674    Some(4),
1675    Some(5),
1676    Some(6),
1677    None,
1678    None,
1679    None,
1680    None,
1681    Some(5),
1682    Some(12),
1683];
1684
1685/// RP002-1.0.5 Table 72, the dwell time column: the payload under a 400 ms dwell limit.
1686///
1687/// The table carries both columns; the plan keeps the one with the limit here, repeater
1688/// compatible as the AU915-928 plan's is. DR0 and DR1 carry nothing inside 400 ms, and
1689/// RP002-1.0.5 raised DR2 from 59 to 123 bytes without the limit, which is the other column.
1690#[cfg(feature = "as923")]
1691static AS923_MAX_PAYLOAD_DWELL: [Option<MaxPayload>; 14] = [
1692    None,
1693    None,
1694    Some(MaxPayload::new(19, 11)),
1695    Some(MaxPayload::new(61, 53)),
1696    Some(MaxPayload::new(133, 125)),
1697    Some(MaxPayload::new(230, 222)),
1698    Some(MaxPayload::new(230, 222)),
1699    Some(MaxPayload::new(230, 222)),
1700    None,
1701    None,
1702    None,
1703    None,
1704    Some(MaxPayload::new(230, 222)),
1705    Some(MaxPayload::new(230, 222)),
1706];
1707
1708/// RP002-1.0.5 Table 65: the two default channels, at the AS923-1 offset of zero.
1709#[cfg(feature = "as923")]
1710static AS923_CHANNELS: [ChannelBlock; 1] = [ChannelBlock::new(923_200_000, 200_000, 2, 0, 5)];
1711
1712/// RP002-1.0.5 Table 66: the same two channels for a join, at DR2 to DR5 only, which keeps a
1713/// join request inside a 400 ms dwell limit before the network has said whether one applies.
1714#[cfg(feature = "as923")]
1715static AS923_JOIN_CHANNELS: [ChannelBlock; 1] = [ChannelBlock::new(923_200_000, 200_000, 2, 2, 5)];
1716
1717/// The AS923 band is duty-cycle limited to 1% on its default channels.
1718#[cfg(feature = "as923")]
1719static AS923_SUB_BANDS: [SubBand; 1] = [SubBand::new(923_000_000, 923_500_000, 10, 16)];
1720
1721/// RP002-1.0.5 table 76: SF9 at 125 kHz, AS923-1 with no frequency offset.
1722#[cfg(feature = "as923")]
1723static AS923_RELAY: [RelayChannel; 1] = [RelayChannel::new(923_600_000, 923_800_000, 3)];
1724
1725/// The AS923 channel plan, RP002-1.0.5 section 3.10.
1726///
1727/// AS923 is four plans rather than one: every frequency here is the AS923-1
1728/// value, and AS923-2, AS923-3, and AS923-4 shift each of them by a fixed
1729/// `AS923_FREQ_OFFSET_HZ`. Everything that is not a frequency is common to all
1730/// four, so a deployment on another group copies this plan and adds its offset
1731/// to the channel, RX2, and beacon frequencies.
1732///
1733/// Japan reaches this band through ARIB STD-T108, which imposes a listen-before-
1734/// talk obligation this plan does not model.
1735#[cfg(feature = "as923")]
1736pub static AS923: ChannelPlan<'static> = ChannelPlan {
1737    name: "AS923",
1738    uplink_data_rates: &AS923_DATA_RATES,
1739    downlink_data_rates: &AS923_DATA_RATES,
1740    max_payload_repeater: &AS923_MAX_PAYLOAD_REPEATER,
1741    max_payload_direct: &AS923_MAX_PAYLOAD_DIRECT,
1742    downlink_max_payload_repeater: &AS923_MAX_PAYLOAD_REPEATER,
1743    downlink_max_payload_direct: &AS923_MAX_PAYLOAD_DIRECT,
1744    max_payload_dwell_limited: Some(&AS923_MAX_PAYLOAD_DWELL),
1745    join_channels: &AS923_JOIN_CHANNELS,
1746    default_channels: &AS923_CHANNELS,
1747    sub_bands: &AS923_SUB_BANDS,
1748    default_max_eirp_dbm: 16,
1749    tx_power_step_db: 2,
1750    max_tx_power_index: 7,
1751    rx1_data_rate_offsets: &AS923_RX1,
1752    rx1_data_rate_offsets_dwell_limited: Some(&AS923_RX1_DWELL),
1753    max_rx1_data_rate_offset: 7,
1754    rx2_frequency_hz: 923_200_000,
1755    rx2_data_rate: 2,
1756    data_rate_backoff: &AS923_BACKOFF,
1757    beacon: Beacon {
1758        data_rate: 3,
1759        frequency_hz: 923_400_000,
1760        ping_slot_frequency_hz: 923_400_000,
1761    },
1762    relay_channels: &AS923_RELAY,
1763    has_dwell_time_limit: true,
1764    kind: PlanKind::Dynamic {
1765        channel_list: Some(FixedChannelList::Mhz900),
1766    },
1767    tx_param_setup: true,
1768    mask_controls: MaskControl::DYNAMIC,
1769    downlink_channels: &[],
1770    join_sequence: JoinSequence::Random,
1771    power_reference: PowerReference::Eirp,
1772    join_plans: &[],
1773};
1774
1775// KR920-923, RP002-1.0.5 section 3.11.
1776
1777/// RP002-1.0.5 Table 80: KR920-923 TX data rate.
1778#[cfg(feature = "kr920")]
1779static KR920_DATA_RATES: [Option<DataRate>; 14] = [
1780    Some(DataRate::lora(12, 125_000, 250)),
1781    Some(DataRate::lora(11, 125_000, 440)),
1782    Some(DataRate::lora(10, 125_000, 980)),
1783    Some(DataRate::lora(9, 125_000, 1_760)),
1784    Some(DataRate::lora(8, 125_000, 3_125)),
1785    Some(DataRate::lora(7, 125_000, 5_470)),
1786    None,
1787    None,
1788    None,
1789    None,
1790    None,
1791    None,
1792    Some(DataRate::lora(6, 125_000, 9_375)),
1793    Some(DataRate::lora(5, 125_000, 15_625)),
1794];
1795
1796/// RP002-1.0.5 Table 85: KR920-923 maximum payload size (repeater compatible).
1797#[cfg(feature = "kr920")]
1798static KR920_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 14] = [
1799    Some(MaxPayload::new(59, 51)),
1800    Some(MaxPayload::new(59, 51)),
1801    Some(MaxPayload::new(59, 51)),
1802    Some(MaxPayload::new(123, 115)),
1803    Some(MaxPayload::new(230, 222)),
1804    Some(MaxPayload::new(230, 222)),
1805    None,
1806    None,
1807    None,
1808    None,
1809    None,
1810    None,
1811    Some(MaxPayload::new(230, 222)),
1812    Some(MaxPayload::new(230, 222)),
1813];
1814
1815/// RP002-1.0.5 Table 86: KR920-923 maximum payload size (not repeater compatible).
1816#[cfg(feature = "kr920")]
1817static KR920_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 14] = [
1818    Some(MaxPayload::new(59, 51)),
1819    Some(MaxPayload::new(59, 51)),
1820    Some(MaxPayload::new(59, 51)),
1821    Some(MaxPayload::new(123, 115)),
1822    Some(MaxPayload::new(250, 242)),
1823    Some(MaxPayload::new(250, 242)),
1824    None,
1825    None,
1826    None,
1827    None,
1828    None,
1829    None,
1830    Some(MaxPayload::new(250, 242)),
1831    Some(MaxPayload::new(250, 242)),
1832];
1833
1834/// RP002-1.0.5 Table 87: KR920-923 downlink RX1 data rate mapping.
1835#[cfg(feature = "kr920")]
1836static KR920_RX1: [&[u8]; 14] = [
1837    &[0, 0, 0, 0, 0, 0],
1838    &[1, 0, 0, 0, 0, 0],
1839    &[2, 1, 0, 0, 0, 0],
1840    &[3, 2, 1, 0, 0, 0],
1841    &[4, 3, 2, 1, 0, 0],
1842    &[5, 4, 3, 2, 1, 0],
1843    &[0, 0, 0, 0, 0, 0],
1844    &[0, 0, 0, 0, 0, 0],
1845    &[0, 0, 0, 0, 0, 0],
1846    &[0, 0, 0, 0, 0, 0],
1847    &[0, 0, 0, 0, 0, 0],
1848    &[0, 0, 0, 0, 0, 0],
1849    &[12, 5, 4, 3, 2, 1],
1850    &[13, 12, 5, 4, 3, 2],
1851];
1852
1853/// RP002-1.0.5 Table 82: KR920-923 data rate back-off.
1854#[cfg(feature = "kr920")]
1855static KR920_BACKOFF: [Option<u8>; 14] = [
1856    None,
1857    Some(0),
1858    Some(1),
1859    Some(2),
1860    Some(3),
1861    Some(4),
1862    None,
1863    None,
1864    None,
1865    None,
1866    None,
1867    None,
1868    Some(5),
1869    Some(12),
1870];
1871
1872/// RP002-1.0.5 Tables 78 and 79: the three default and join channels.
1873#[cfg(feature = "kr920")]
1874static KR920_CHANNELS: [ChannelBlock; 1] = [ChannelBlock::new(922_100_000, 200_000, 3, 0, 5)];
1875
1876/// RP002-1.0.5 Table 77: the band's power ceiling steps at 922.1 MHz.
1877///
1878/// Korea publishes no duty cycle for this band; the two sub-bands differ only in
1879/// how much power they allow, so the limit reported here is the ceiling.
1880#[cfg(feature = "kr920")]
1881static KR920_SUB_BANDS: [SubBand; 2] = [
1882    SubBand::new(920_900_000, 921_900_000, 1000, 10),
1883    SubBand::new(922_100_000, 923_300_000, 1000, 14),
1884];
1885
1886/// RP002-1.0.5 table 88: SF9 and SF7 at 125 kHz, the second acknowledged on its own frequency.
1887#[cfg(feature = "kr920")]
1888static KR920_RELAY: [RelayChannel; 2] = [
1889    RelayChannel::new(922_700_000, 922_900_000, 3),
1890    RelayChannel::new(923_100_000, 923_100_000, 5),
1891];
1892
1893/// The KR920-923 channel plan, RP002-1.0.5 section 3.11.
1894#[cfg(feature = "kr920")]
1895pub static KR920: ChannelPlan<'static> = ChannelPlan {
1896    name: "KR920-923",
1897    uplink_data_rates: &KR920_DATA_RATES,
1898    downlink_data_rates: &KR920_DATA_RATES,
1899    max_payload_repeater: &KR920_MAX_PAYLOAD_REPEATER,
1900    max_payload_direct: &KR920_MAX_PAYLOAD_DIRECT,
1901    downlink_max_payload_repeater: &KR920_MAX_PAYLOAD_REPEATER,
1902    downlink_max_payload_direct: &KR920_MAX_PAYLOAD_DIRECT,
1903    max_payload_dwell_limited: None,
1904    join_channels: &KR920_CHANNELS,
1905    default_channels: &KR920_CHANNELS,
1906    sub_bands: &KR920_SUB_BANDS,
1907    default_max_eirp_dbm: 14,
1908    tx_power_step_db: 2,
1909    max_tx_power_index: 7,
1910    rx1_data_rate_offsets: &KR920_RX1,
1911    rx1_data_rate_offsets_dwell_limited: None,
1912    max_rx1_data_rate_offset: 5,
1913    rx2_frequency_hz: 921_900_000,
1914    rx2_data_rate: 0,
1915    data_rate_backoff: &KR920_BACKOFF,
1916    beacon: Beacon {
1917        data_rate: 3,
1918        frequency_hz: 923_100_000,
1919        ping_slot_frequency_hz: 923_100_000,
1920    },
1921    relay_channels: &KR920_RELAY,
1922    has_dwell_time_limit: false,
1923    kind: PlanKind::Dynamic {
1924        channel_list: Some(FixedChannelList::Mhz900),
1925    },
1926    tx_param_setup: false,
1927    mask_controls: MaskControl::DYNAMIC,
1928    downlink_channels: &[],
1929    join_sequence: JoinSequence::Random,
1930    power_reference: PowerReference::Eirp,
1931    join_plans: &[],
1932};
1933
1934// IN865, RP002-1.0.5 section 3.12.
1935
1936/// RP002-1.0.5 Table 91: IN865 TX data rate.
1937#[cfg(feature = "in865")]
1938static IN865_DATA_RATES: [Option<DataRate>; 14] = [
1939    Some(DataRate::lora(12, 125_000, 250)),
1940    Some(DataRate::lora(11, 125_000, 440)),
1941    Some(DataRate::lora(10, 125_000, 980)),
1942    Some(DataRate::lora(9, 125_000, 1_760)),
1943    Some(DataRate::lora(8, 125_000, 3_125)),
1944    Some(DataRate::lora(7, 125_000, 5_470)),
1945    None,
1946    Some(DataRate::fsk(50_000)),
1947    None,
1948    None,
1949    None,
1950    None,
1951    Some(DataRate::lora(6, 125_000, 9_375)),
1952    Some(DataRate::lora(5, 125_000, 15_625)),
1953];
1954
1955/// RP002-1.0.5 Table 96: IN865 maximum payload size (repeater compatible).
1956#[cfg(feature = "in865")]
1957static IN865_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 14] = [
1958    Some(MaxPayload::new(59, 51)),
1959    Some(MaxPayload::new(59, 51)),
1960    Some(MaxPayload::new(59, 51)),
1961    Some(MaxPayload::new(123, 115)),
1962    Some(MaxPayload::new(230, 222)),
1963    Some(MaxPayload::new(230, 222)),
1964    None,
1965    Some(MaxPayload::new(230, 222)),
1966    None,
1967    None,
1968    None,
1969    None,
1970    Some(MaxPayload::new(230, 222)),
1971    Some(MaxPayload::new(230, 222)),
1972];
1973
1974/// RP002-1.0.5 Table 97: IN865 maximum payload size (not repeater compatible).
1975#[cfg(feature = "in865")]
1976static IN865_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 14] = [
1977    Some(MaxPayload::new(59, 51)),
1978    Some(MaxPayload::new(59, 51)),
1979    Some(MaxPayload::new(59, 51)),
1980    Some(MaxPayload::new(123, 115)),
1981    Some(MaxPayload::new(250, 242)),
1982    Some(MaxPayload::new(250, 242)),
1983    None,
1984    Some(MaxPayload::new(250, 242)),
1985    None,
1986    None,
1987    None,
1988    None,
1989    Some(MaxPayload::new(250, 242)),
1990    Some(MaxPayload::new(250, 242)),
1991];
1992
1993/// RP002-1.0.5 Table 98: IN865 downlink RX1 data rate mapping.
1994///
1995/// India is one of the regions that allows all eight RX1 data-rate offsets.
1996#[cfg(feature = "in865")]
1997static IN865_RX1: [&[u8]; 14] = [
1998    &[0, 0, 0, 0, 0, 0, 1, 2],
1999    &[1, 0, 0, 0, 0, 0, 2, 3],
2000    &[2, 1, 0, 0, 0, 0, 3, 4],
2001    &[3, 2, 1, 0, 0, 0, 4, 5],
2002    &[4, 3, 2, 1, 0, 0, 5, 5],
2003    &[5, 4, 3, 2, 1, 0, 5, 7],
2004    &[0, 0, 0, 0, 0, 0, 1, 2],
2005    &[7, 5, 5, 4, 3, 2, 7, 7],
2006    &[0, 0, 0, 0, 0, 0, 1, 2],
2007    &[0, 0, 0, 0, 0, 0, 1, 2],
2008    &[0, 0, 0, 0, 0, 0, 1, 2],
2009    &[0, 0, 0, 0, 0, 0, 1, 2],
2010    &[12, 5, 4, 3, 2, 1, 13, 13],
2011    &[13, 12, 5, 4, 3, 2, 13, 13],
2012];
2013
2014/// RP002-1.0.5 Table 93: IN865 data rate back-off.
2015#[cfg(feature = "in865")]
2016static IN865_BACKOFF: [Option<u8>; 14] = [
2017    None,
2018    Some(0),
2019    Some(1),
2020    Some(2),
2021    Some(3),
2022    Some(4),
2023    None,
2024    Some(5),
2025    None,
2026    None,
2027    None,
2028    None,
2029    Some(5),
2030    Some(12),
2031];
2032
2033/// RP002-1.0.5 Tables 89 and 90: the three default and join channels.
2034///
2035/// These are not evenly spaced, so each is its own single-channel block.
2036#[cfg(feature = "in865")]
2037static IN865_CHANNELS: [ChannelBlock; 3] = [
2038    ChannelBlock::new(865_062_500, 0, 1, 0, 5),
2039    ChannelBlock::new(865_402_500, 0, 1, 0, 5),
2040    ChannelBlock::new(865_985_000, 0, 1, 0, 5),
2041];
2042
2043/// RP002-1.0.5 table 99: SF9 and SF7 at 125 kHz.
2044#[cfg(feature = "in865")]
2045static IN865_RELAY: [RelayChannel; 2] = [
2046    RelayChannel::new(866_000_000, 866_200_000, 3),
2047    RelayChannel::new(866_700_000, 866_900_000, 5),
2048];
2049
2050/// The IN865 channel plan, RP002-1.0.5 section 3.12.
2051///
2052/// The published ceiling is 29.2 dBm EIRP, reported here as the whole decibel
2053/// below it so a caller reading this as a limit is never over the real one.
2054#[cfg(feature = "in865")]
2055pub static IN865: ChannelPlan<'static> = ChannelPlan {
2056    name: "IN865",
2057    uplink_data_rates: &IN865_DATA_RATES,
2058    downlink_data_rates: &IN865_DATA_RATES,
2059    max_payload_repeater: &IN865_MAX_PAYLOAD_REPEATER,
2060    max_payload_direct: &IN865_MAX_PAYLOAD_DIRECT,
2061    downlink_max_payload_repeater: &IN865_MAX_PAYLOAD_REPEATER,
2062    downlink_max_payload_direct: &IN865_MAX_PAYLOAD_DIRECT,
2063    max_payload_dwell_limited: None,
2064    join_channels: &IN865_CHANNELS,
2065    default_channels: &IN865_CHANNELS,
2066    sub_bands: &[],
2067    default_max_eirp_dbm: 29,
2068    tx_power_step_db: 2,
2069    max_tx_power_index: 10,
2070    rx1_data_rate_offsets: &IN865_RX1,
2071    rx1_data_rate_offsets_dwell_limited: None,
2072    max_rx1_data_rate_offset: 7,
2073    rx2_frequency_hz: 866_550_000,
2074    rx2_data_rate: 2,
2075    data_rate_backoff: &IN865_BACKOFF,
2076    beacon: Beacon {
2077        data_rate: 4,
2078        frequency_hz: 866_550_000,
2079        ping_slot_frequency_hz: 866_550_000,
2080    },
2081    relay_channels: &IN865_RELAY,
2082    has_dwell_time_limit: false,
2083    kind: PlanKind::Dynamic {
2084        channel_list: Some(FixedChannelList::Mhz800),
2085    },
2086    tx_param_setup: false,
2087    mask_controls: MaskControl::DYNAMIC,
2088    downlink_channels: &[],
2089    join_sequence: JoinSequence::Random,
2090    power_reference: PowerReference::Eirp,
2091    join_plans: &[],
2092};
2093
2094// RU864-870, RP002-1.0.5 section 3.13.
2095
2096/// RP002-1.0.5 Table 102: RU864-870 TX data rate.
2097#[cfg(feature = "ru864")]
2098static RU864_DATA_RATES: [Option<DataRate>; 14] = [
2099    Some(DataRate::lora(12, 125_000, 250)),
2100    Some(DataRate::lora(11, 125_000, 440)),
2101    Some(DataRate::lora(10, 125_000, 980)),
2102    Some(DataRate::lora(9, 125_000, 1_760)),
2103    Some(DataRate::lora(8, 125_000, 3_125)),
2104    Some(DataRate::lora(7, 125_000, 5_470)),
2105    Some(DataRate::lora(7, 250_000, 11_000)),
2106    Some(DataRate::fsk(50_000)),
2107    None,
2108    None,
2109    None,
2110    None,
2111    Some(DataRate::lora(6, 125_000, 9_375)),
2112    Some(DataRate::lora(5, 125_000, 15_625)),
2113];
2114
2115/// RP002-1.0.5 Table 107: RU864-870 maximum payload size (repeater compatible).
2116#[cfg(feature = "ru864")]
2117static RU864_MAX_PAYLOAD_REPEATER: [Option<MaxPayload>; 14] = [
2118    Some(MaxPayload::new(59, 51)),
2119    Some(MaxPayload::new(59, 51)),
2120    Some(MaxPayload::new(59, 51)),
2121    Some(MaxPayload::new(123, 115)),
2122    Some(MaxPayload::new(230, 222)),
2123    Some(MaxPayload::new(230, 222)),
2124    Some(MaxPayload::new(230, 222)),
2125    Some(MaxPayload::new(230, 222)),
2126    None,
2127    None,
2128    None,
2129    None,
2130    Some(MaxPayload::new(230, 222)),
2131    Some(MaxPayload::new(230, 222)),
2132];
2133
2134/// RP002-1.0.5 Table 108: RU864-870 maximum payload size (not repeater compatible).
2135#[cfg(feature = "ru864")]
2136static RU864_MAX_PAYLOAD_DIRECT: [Option<MaxPayload>; 14] = [
2137    Some(MaxPayload::new(59, 51)),
2138    Some(MaxPayload::new(59, 51)),
2139    Some(MaxPayload::new(59, 51)),
2140    Some(MaxPayload::new(123, 115)),
2141    Some(MaxPayload::new(250, 242)),
2142    Some(MaxPayload::new(250, 242)),
2143    Some(MaxPayload::new(250, 242)),
2144    Some(MaxPayload::new(250, 242)),
2145    None,
2146    None,
2147    None,
2148    None,
2149    Some(MaxPayload::new(250, 242)),
2150    Some(MaxPayload::new(250, 242)),
2151];
2152
2153/// RP002-1.0.5 Table 109: RU864-870 downlink RX1 data rate mapping.
2154#[cfg(feature = "ru864")]
2155static RU864_RX1: [&[u8]; 14] = [
2156    &[0, 0, 0, 0, 0, 0],
2157    &[1, 0, 0, 0, 0, 0],
2158    &[2, 1, 0, 0, 0, 0],
2159    &[3, 2, 1, 0, 0, 0],
2160    &[4, 3, 2, 1, 0, 0],
2161    &[5, 4, 3, 2, 1, 0],
2162    &[6, 5, 4, 3, 2, 1],
2163    &[7, 6, 5, 4, 3, 2],
2164    &[0, 0, 0, 0, 0, 0],
2165    &[0, 0, 0, 0, 0, 0],
2166    &[0, 0, 0, 0, 0, 0],
2167    &[0, 0, 0, 0, 0, 0],
2168    &[12, 5, 4, 3, 2, 1],
2169    &[13, 12, 5, 4, 3, 2],
2170];
2171
2172/// RP002-1.0.5 Table 104: RU864-870 data rate back-off.
2173#[cfg(feature = "ru864")]
2174static RU864_BACKOFF: [Option<u8>; 14] = [
2175    None,
2176    Some(0),
2177    Some(1),
2178    Some(2),
2179    Some(3),
2180    Some(4),
2181    Some(5),
2182    Some(6),
2183    None,
2184    None,
2185    None,
2186    None,
2187    Some(5),
2188    Some(12),
2189];
2190
2191/// RP002-1.0.5 Tables 100 and 101: the two default and join channels.
2192#[cfg(feature = "ru864")]
2193static RU864_CHANNELS: [ChannelBlock; 1] = [ChannelBlock::new(868_900_000, 200_000, 2, 0, 5)];
2194
2195/// The Russian band carries a 1% duty cycle on its default channels.
2196#[cfg(feature = "ru864")]
2197static RU864_SUB_BANDS: [SubBand; 1] = [SubBand::new(868_700_000, 869_200_000, 10, 16)];
2198
2199/// RP002-1.0.5 table 110: SF9 and SF7 at 125 kHz.
2200#[cfg(feature = "ru864")]
2201static RU864_RELAY: [RelayChannel; 2] = [
2202    RelayChannel::new(866_100_000, 866_300_000, 3),
2203    RelayChannel::new(866_500_000, 866_900_000, 5),
2204];
2205
2206/// The RU864-870 channel plan, RP002-1.0.5 section 3.13.
2207#[cfg(feature = "ru864")]
2208pub static RU864: ChannelPlan<'static> = ChannelPlan {
2209    name: "RU864-870",
2210    uplink_data_rates: &RU864_DATA_RATES,
2211    downlink_data_rates: &RU864_DATA_RATES,
2212    max_payload_repeater: &RU864_MAX_PAYLOAD_REPEATER,
2213    max_payload_direct: &RU864_MAX_PAYLOAD_DIRECT,
2214    downlink_max_payload_repeater: &RU864_MAX_PAYLOAD_REPEATER,
2215    downlink_max_payload_direct: &RU864_MAX_PAYLOAD_DIRECT,
2216    max_payload_dwell_limited: None,
2217    join_channels: &RU864_CHANNELS,
2218    default_channels: &RU864_CHANNELS,
2219    sub_bands: &RU864_SUB_BANDS,
2220    default_max_eirp_dbm: 16,
2221    tx_power_step_db: 2,
2222    max_tx_power_index: 7,
2223    rx1_data_rate_offsets: &RU864_RX1,
2224    rx1_data_rate_offsets_dwell_limited: None,
2225    max_rx1_data_rate_offset: 5,
2226    rx2_frequency_hz: 869_100_000,
2227    rx2_data_rate: 0,
2228    data_rate_backoff: &RU864_BACKOFF,
2229    beacon: Beacon {
2230        data_rate: 3,
2231        frequency_hz: 869_100_000,
2232        ping_slot_frequency_hz: 868_900_000,
2233    },
2234    relay_channels: &RU864_RELAY,
2235    has_dwell_time_limit: false,
2236    kind: PlanKind::Dynamic {
2237        channel_list: Some(FixedChannelList::Mhz800),
2238    },
2239    tx_param_setup: false,
2240    mask_controls: MaskControl::DYNAMIC,
2241    downlink_channels: &[],
2242    join_sequence: JoinSequence::Random,
2243    power_reference: PowerReference::Eirp,
2244    join_plans: &[],
2245};