1use super::spi;
13
14pub const EXTERNAL_MEMORY_BASE: u16 = 0x0000;
16
17pub const RX_BUFFER_BASE: u16 = 0x4000;
19
20pub const TX_TOP_A_BASE: u16 = 0x5200;
22
23pub const TX_TOP_B_BASE: u16 = 0x5400;
25
26pub const COMMON_BASE: u16 = 0x5600;
28
29pub const GPIO_BASE: u16 = 0x5640;
31
32pub const MBIST_BASE: u16 = 0x56c0;
34
35pub const RADIO_FE_BASE: u16 = 0x5700;
37
38pub const AGC_MCU_BASE: u16 = 0x5780;
40
41pub const CLK_CTRL_BASE: u16 = 0x57c0;
43
44pub const RX_TOP_BASE: u16 = 0x5800;
46
47pub const RX_TOP_LORA_SERVICE_FSK_BASE: u16 = 0x5b00;
49
50pub const CAPTURE_RAM_BASE: u16 = 0x6000;
52
53pub const ARB_MCU_BASE: u16 = 0x6080;
55
56pub const TIMESTAMP_BASE: u16 = 0x6100;
58
59pub const OTP_BASE: u16 = 0x6180;
61
62#[derive(Clone, Copy, Debug, PartialEq, Eq)]
64pub struct Register {
65 pub address: u16,
67 pub offset: u8,
69 pub width: u8,
71 pub read_only: bool,
73}
74
75impl Register {
76 #[must_use]
89 pub const fn new(address: u16, offset: u8, width: u8, read_only: bool) -> Register {
90 Register {
91 address,
92 offset,
93 width,
94 read_only,
95 }
96 }
97
98 #[must_use]
116 pub const fn is_whole_byte(&self) -> bool {
117 self.offset == 0 && self.width == 8
118 }
119
120 #[must_use]
130 pub const fn decode(&self, byte: u8) -> u8 {
131 spi::field(byte, self.offset, self.width)
132 }
133
134 #[must_use]
145 pub const fn encode(&self, byte: u8, value: u8) -> u8 {
146 spi::with_field(byte, self.offset, self.width, value)
147 }
148}
149
150pub const COMMON_PAGE: Register = Register::new(COMMON_BASE, 0, 2, false);
152
153pub const COMMON_VERSION: Register = Register::new(COMMON_BASE + 6, 0, 8, true);
156
157pub const AGC_MCU_CLEAR: Register = Register::new(AGC_MCU_BASE, 2, 1, false);
159
160pub const AGC_MCU_HOST_PROG: Register = Register::new(AGC_MCU_BASE, 1, 1, false);
162
163pub const AGC_MCU_CLK_EN: Register = Register::new(AGC_MCU_BASE, 4, 1, false);
165
166pub const AGC_MCU_PARITY_ERROR: Register = Register::new(AGC_MCU_BASE, 0, 1, true);
168
169pub const ARB_MCU_CLEAR: Register = Register::new(ARB_MCU_BASE, 2, 1, false);
171
172pub const ARB_MCU_HOST_PROG: Register = Register::new(ARB_MCU_BASE, 1, 1, false);
174
175pub const ARB_MCU_CLK_EN: Register = Register::new(ARB_MCU_BASE, 5, 1, false);
177
178pub const ARB_MCU_PARITY_ERROR: Register = Register::new(ARB_MCU_BASE, 0, 1, true);
180
181pub const COMMON_CLK32_RIF_CTRL: Register = Register::new(COMMON_BASE + 1, 4, 1, false);
186
187pub const COMMON_HOST_RADIO_CTRL: Register = Register::new(COMMON_BASE + 1, 3, 1, false);
190
191pub const RF_EN_A_RADIO_EN: Register = Register::new(AGC_MCU_BASE + 3, 2, 1, false);
193
194pub const RF_EN_A_RADIO_RST: Register = Register::new(AGC_MCU_BASE + 3, 3, 1, false);
196
197pub const RF_EN_B_RADIO_EN: Register = Register::new(AGC_MCU_BASE + 4, 2, 1, false);
199
200pub const RF_EN_B_RADIO_RST: Register = Register::new(AGC_MCU_BASE + 4, 3, 1, false);
202
203pub const OTP_BYTE_ADDR: Register = Register::new(OTP_BASE, 0, 8, false);
205
206pub const OTP_RD_DATA: Register = Register::new(OTP_BASE + 1, 0, 8, true);
208
209pub const OTP_FSM_READY: Register = Register::new(OTP_BASE + 2, 0, 1, true);
211
212pub const OTP_CHECKSUM_STATUS: Register = Register::new(OTP_BASE + 2, 4, 4, true);
214
215pub const RX_BUFFER_NB_BYTES_MSB: Register = Register::new(RX_TOP_BASE + 200, 0, 5, true);
220
221pub const RX_BUFFER_NB_BYTES_LSB: Register = Register::new(RX_TOP_BASE + 201, 0, 8, true);
223
224pub const RX_RADIO_SELECT: Register = Register::new(RX_TOP_BASE + 16, 0, 8, false);
226
227pub const RX_RSSI_FILTER_ALPHA: Register = Register::new(RX_TOP_BASE + 17, 3, 5, false);
229
230pub const RX_RSSI_DEFAULT: Register = Register::new(RX_TOP_BASE + 18, 0, 8, false);
232
233pub const RX_GAIN_THRESHOLD_HIGH: Register = Register::new(RX_TOP_BASE + 19, 0, 8, false);
235
236pub const RX_GAIN_THRESHOLD_LOW: Register = Register::new(RX_TOP_BASE + 20, 0, 8, false);
238
239pub const RX_GAIN_MAX_ATTENUATION: Register = Register::new(RX_TOP_BASE + 21, 4, 4, false);
241
242pub const RX_GAIN_MIN_ATTENUATION: Register = Register::new(RX_TOP_BASE + 21, 0, 4, false);
244
245pub const RX_GAIN_AUTOMATIC: Register = Register::new(RX_TOP_BASE + 23, 0, 2, false);
247
248pub const RX_CHANNEL_GAIN: Register = Register::new(RX_TOP_BASE + 25, 0, 4, false);
250
251pub const RX_CHANNEL_GAIN_VALID: Register = Register::new(RX_TOP_BASE + 25, 4, 1, false);
253
254pub const RX_CORRELATOR_CLOCK_ENABLE: Register = Register::new(RX_TOP_BASE + 32, 0, 8, false);
256
257pub const RX_CORRELATOR_SF_ENABLE: Register = Register::new(RX_TOP_BASE + 34, 0, 8, false);
259
260pub const RX_CORRELATOR_FIRST_EDGE: Register = Register::new(RX_TOP_BASE + 35, 0, 8, false);
262
263pub const RX_CORRELATOR_CLEAR: Register = Register::new(RX_TOP_BASE + 36, 0, 8, false);
265
266pub const RX_DC_NOTCH_ENABLE: Register = Register::new(RX_TOP_BASE + 96, 0, 1, false);
268
269pub const RX_FORCE_DEFAULT_FILTER: Register = Register::new(RX_TOP_BASE + 117, 3, 1, false);
271
272pub const RX_GAIN_TARGET_LEVEL: Register = Register::new(RX_TOP_BASE + 120, 6, 2, false);
274
275pub const RX_GAIN_DROP_COMPENSATION: Register = Register::new(RX_TOP_BASE + 120, 4, 1, false);
277
278pub const RX_PREAMBLE_SYMBOLS_LSB: Register = Register::new(RX_TOP_BASE + 131, 0, 8, false);
280
281pub const RX_PREAMBLE_SYMBOLS_MSB: Register = Register::new(RX_TOP_BASE + 132, 0, 8, false);
283
284pub const RX_DFT_PEAK_MODE: Register = Register::new(RX_TOP_BASE + 135, 4, 2, false);
286
287pub const RX_SYNC_SF5_PEAK1: Register = Register::new(RX_TOP_BASE + 138, 0, 5, false);
289
290pub const RX_SYNC_SF5_PEAK2: Register = Register::new(RX_TOP_BASE + 139, 0, 5, false);
292
293pub const RX_SYNC_SF6_PEAK1: Register = Register::new(RX_TOP_BASE + 140, 0, 5, false);
295
296pub const RX_SYNC_SF6_PEAK2: Register = Register::new(RX_TOP_BASE + 141, 0, 5, false);
298
299pub const RX_SYNC_SF7_TO_SF12_PEAK1: Register = Register::new(RX_TOP_BASE + 142, 0, 5, false);
302
303pub const RX_SYNC_SF7_TO_SF12_PEAK2: Register = Register::new(RX_TOP_BASE + 143, 0, 5, false);
305
306pub const RX_FINE_TIMING_GAIN_AUTO: Register = Register::new(RX_TOP_BASE + 146, 6, 2, false);
308
309pub const RX_FINE_TIMING_GAIN_PAYLOAD: Register = Register::new(RX_TOP_BASE + 146, 3, 3, false);
311
312pub const RX_FINE_TIMING_INTEGRATE_SF11: Register = Register::new(RX_TOP_BASE + 150, 4, 2, false);
314
315pub const RX_FINE_TIMING_INTEGRATE_SF12: Register = Register::new(RX_TOP_BASE + 150, 6, 2, false);
317
318pub const RX_TIMING_ROUNDING: Register = Register::new(RX_TOP_BASE + 153, 6, 1, false);
320
321pub const RX_TIMING_MODE: Register = Register::new(RX_TOP_BASE + 153, 0, 2, false);
323
324pub const RX_TIMING_GAIN_AUTO: Register = Register::new(RX_TOP_BASE + 154, 6, 2, false);
326
327pub const RX_TIMING_GAIN_PAYLOAD: Register = Register::new(RX_TOP_BASE + 154, 3, 3, false);
329
330pub const RX_TIMING_GAIN_PREAMBLE: Register = Register::new(RX_TOP_BASE + 154, 0, 3, false);
332
333pub const RX_TIMING_INTEGRAL_AUTO: Register = Register::new(RX_TOP_BASE + 155, 6, 2, false);
335
336pub const RX_TIMING_INTEGRAL_PAYLOAD: Register = Register::new(RX_TOP_BASE + 155, 3, 3, false);
338
339pub const RX_TIMING_INTEGRAL_PREAMBLE: Register = Register::new(RX_TOP_BASE + 155, 0, 3, false);
341
342pub const RX_TIMING_INTEGRATE_SF11: Register = Register::new(RX_TOP_BASE + 158, 4, 2, false);
344
345pub const RX_TIMING_INTEGRATE_SF12: Register = Register::new(RX_TOP_BASE + 158, 6, 2, false);
347
348pub const RX_DRIFT_MANTISSA_MSB: Register = Register::new(RX_TOP_BASE + 160, 0, 4, false);
353
354pub const RX_DRIFT_MANTISSA_LSB: Register = Register::new(RX_TOP_BASE + 161, 0, 8, false);
356
357pub const RX_DRIFT_EXPONENT: Register = Register::new(RX_TOP_BASE + 162, 0, 3, false);
359
360pub const RX_DRIFT_INVERT_SYMBOL_TIME: Register = Register::new(RX_TOP_BASE + 163, 2, 1, false);
362
363pub const RX_FREQUENCY_SYNC_THRESHOLD: Register = Register::new(RX_TOP_BASE + 171, 0, 4, false);
365
366pub const RX_MODEM_SYNC_DELTA_MSB: Register = Register::new(RX_TOP_BASE + 183, 0, 3, false);
368
369pub const RX_MODEM_SYNC_DELTA_LSB: Register = Register::new(RX_TOP_BASE + 184, 0, 8, false);
371
372pub const MODEM_ENABLE_FULL: Register = Register::new(OTP_BASE + 8, 0, 8, false);
374
375pub const MODEM_ENABLE_LIMITED: Register = Register::new(OTP_BASE + 9, 0, 8, false);
377
378pub const COMMON_GLOBAL_ENABLE: Register = Register::new(COMMON_BASE + 5, 3, 1, false);
380
381pub const COMMON_FSK_MODEM_ENABLE: Register = Register::new(COMMON_BASE + 5, 2, 1, false);
383
384pub const COMMON_MULTI_MODEM_ENABLE: Register = Register::new(COMMON_BASE + 5, 1, 1, false);
386
387pub const COMMON_SERVICE_MODEM_ENABLE: Register = Register::new(COMMON_BASE + 5, 0, 1, false);
389
390pub const SERVICE_FREQUENCY_MSB: Register =
392 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE, 0, 5, false);
393
394pub const SERVICE_FREQUENCY_LSB: Register =
396 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 1, 0, 8, false);
397
398pub const SERVICE_RADIO_SELECT: Register =
400 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 2, 0, 1, false);
401
402pub const SERVICE_SYNC_PEAK1: Register =
404 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 46, 0, 5, false);
405
406pub const SERVICE_SYNC_PEAK2: Register =
408 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 47, 0, 5, false);
409
410pub const FSK_FREQUENCY_MSB: Register =
412 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 80, 0, 5, false);
413
414pub const FSK_FREQUENCY_LSB: Register =
416 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 81, 0, 8, false);
417
418pub const FSK_RADIO_SELECT: Register =
420 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 84, 1, 1, false);
421pub const FSK_PATTERN_SIZE: Register =
423 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 83, 3, 3, false);
424
425pub const FSK_BANDWIDTH_EXPONENT: Register =
427 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 83, 0, 3, false);
428
429pub const FSK_ADDRESS_COMPARISON: Register =
431 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 83, 6, 2, false);
432
433pub const FSK_PACKET_MODE: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 82, 0, 1, false);
435
436pub const FSK_CRC_ENABLE: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 82, 1, 1, false);
438
439pub const FSK_DCFREE_ENCODING: Register =
441 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 82, 2, 2, false);
442
443pub const FSK_CRC_IBM: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 82, 4, 1, false);
445
446pub const FSK_INVERT_RX: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 84, 0, 1, false);
448
449pub const FSK_INVERT_IQ: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 84, 3, 1, false);
451
452pub const FSK_AUTO_AFC: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 84, 2, 1, false);
454
455pub const FSK_RSSI_LENGTH: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 85, 5, 3, false);
457
458pub const FSK_ERROR_TOLERANCE: Register =
460 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 85, 0, 5, false);
461
462pub const FSK_NODE_ADDRESS: Register =
464 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 86, 0, 8, false);
465
466pub const FSK_BROADCAST_ADDRESS: Register =
468 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 87, 0, 8, false);
469
470pub const FSK_PAYLOAD_LENGTH: Register =
472 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 88, 0, 8, false);
473
474pub const FSK_TIMEOUT_MSB: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 89, 0, 2, false);
476
477pub const FSK_TIMEOUT_LSB: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 90, 0, 8, false);
479
480pub const FSK_BITRATE_MSB: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 91, 0, 8, false);
482
483pub const FSK_BITRATE_LSB: Register = Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 92, 0, 8, false);
485
486pub const FSK_SYNC_WORD_BYTES: u8 = 8;
488
489#[must_use]
510pub const fn fsk_sync_word(byte: u8) -> Register {
511 let byte = if byte >= FSK_SYNC_WORD_BYTES {
512 FSK_SYNC_WORD_BYTES - 1
513 } else {
514 byte
515 } as u16;
516 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 100 - byte, 0, 8, false)
517}
518
519pub const SERVICE_DC_NOTCH_ENABLE: Register =
521 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 3, 0, 1, false);
522
523pub const SERVICE_FORCE_DEFAULT_FIR: Register =
525 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 24, 3, 1, false);
526
527pub const SERVICE_DAGC_IN_COMP: Register =
529 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 25, 6, 1, false);
530
531pub const SERVICE_DAGC_TARGET_LEVEL: Register =
533 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 27, 6, 2, false);
534
535pub const SERVICE_DAGC_GAIN_DROP_COMP: Register =
537 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 27, 4, 1, false);
538
539pub const SERVICE_BANDWIDTH: Register =
541 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 33, 4, 4, false);
542
543pub const SERVICE_SPREADING_FACTOR: Register =
545 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 33, 0, 4, false);
546
547pub const SERVICE_PPM_OFFSET: Register =
549 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 34, 4, 2, false);
550
551pub const SERVICE_MODEM_ENABLE: Register =
553 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 34, 3, 1, false);
554
555pub const SERVICE_CODING_RATE: Register =
557 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 34, 0, 3, false);
558
559pub const SERVICE_FINE_SYNC: Register =
561 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 35, 5, 1, false);
562
563pub const SERVICE_MODEM_START: Register =
565 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 35, 4, 1, false);
566
567pub const SERVICE_CAD_RX_TX: Register =
569 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 35, 2, 2, false);
570
571pub const SERVICE_IMPLICIT_HEADER: Register =
573 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 35, 1, 1, false);
574
575pub const SERVICE_CRC_ENABLE: Register =
577 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 35, 0, 1, false);
578
579pub const SERVICE_PAYLOAD_LENGTH: Register =
581 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 36, 0, 8, false);
582
583pub const SERVICE_PREAMBLE_LSB: Register =
585 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 39, 0, 8, false);
586
587pub const SERVICE_PREAMBLE_MSB: Register =
589 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 40, 0, 8, false);
590
591pub const SERVICE_DFT_PEAK_MODE: Register =
593 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 42, 4, 2, false);
594
595pub const SERVICE_TIMING_GAIN_AUTOMATIC: Register =
597 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 50, 6, 2, false);
598
599pub const SERVICE_TIMING_GAIN_PREAMBLE: Register =
601 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 50, 0, 3, false);
602
603pub const SERVICE_TIMING_GAIN_INTEGRAL: Register =
605 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 51, 6, 2, false);
606
607pub const SERVICE_TIMING_GAIN_PAYLOAD: Register =
609 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 51, 3, 3, false);
610
611pub const SERVICE_DRIFT_MANTISSA_MSB: Register =
613 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 54, 0, 4, false);
614
615pub const SERVICE_DRIFT_MANTISSA_LSB: Register =
617 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 55, 0, 8, false);
618
619pub const SERVICE_DRIFT_EXPONENT: Register =
621 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 56, 0, 3, false);
622
623pub const SERVICE_DRIFT_INVERT_SYMBOL_TIME: Register =
625 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 57, 2, 1, false);
626
627pub const SERVICE_DETECT_PEAK_COUNT: Register =
629 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 64, 0, 3, false);
630
631pub const SERVICE_DETECT_PEAK_COUNT2: Register =
633 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 64, 4, 3, false);
634
635pub const SERVICE_DETECT_USE_GAIN_SYMBOL: Register =
637 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 66, 7, 1, false);
638
639pub const SERVICE_DETECT_PEAK_TO_NOISE: Register =
641 Register::new(RX_TOP_LORA_SERVICE_FSK_BASE + 66, 0, 7, false);
642
643#[derive(Clone, Copy, Debug, PartialEq, Eq)]
645pub struct Correlator {
646 pub accumulated_ratio: Register,
648 pub peak_ratio: Register,
650 pub peaks: Register,
652 pub second_peaks: Register,
654}
655
656#[must_use]
681pub const fn channel_frequency(channel: u8) -> [Register; 2] {
682 let channel = if channel > 7 { 7 } else { channel } as u16;
683 [
684 Register::new(RX_TOP_BASE + channel * 2, 0, 5, false),
685 Register::new(RX_TOP_BASE + channel * 2 + 1, 0, 8, false),
686 ]
687}
688
689#[must_use]
711pub const fn correlator(spreading_factor: u8) -> Correlator {
712 let spreading_factor = if spreading_factor < 5 {
713 5
714 } else if spreading_factor > 12 {
715 12
716 } else {
717 spreading_factor
718 };
719 let base = RX_TOP_BASE + 38 + (spreading_factor as u16 - 5) * 7;
720 Correlator {
721 accumulated_ratio: Register::new(base, 0, 7, false),
722 peak_ratio: Register::new(base + 2, 0, 7, false),
723 peaks: Register::new(base + 4, 3, 3, false),
724 second_peaks: Register::new(base + 5, 2, 3, false),
725 }
726}
727
728#[derive(Clone, Copy, Debug, PartialEq, Eq)]
733pub enum Bank {
734 Demodulation,
736 Timestamping,
738}
739
740#[must_use]
767pub const fn frequency_tracking(bank: Bank, spreading_factor: u8) -> Register {
768 let spreading_factor = if spreading_factor < 5 {
769 5
770 } else if spreading_factor > 12 {
771 12
772 } else {
773 spreading_factor
774 };
775 let base = match bank {
776 Bank::Demodulation => RX_TOP_BASE + 165,
777 Bank::Timestamping => RX_TOP_BASE + 167,
778 };
779 let address = if spreading_factor <= 8 {
780 base
781 } else {
782 base + 1
783 };
784 Register::new(address, ((spreading_factor - 5) % 4) * 2, 2, false)
785}
786
787#[must_use]
808pub const fn drift_correction(spreading_factor: u8) -> Register {
809 let spreading_factor = if spreading_factor < 5 {
810 5
811 } else if spreading_factor > 12 {
812 12
813 } else {
814 spreading_factor
815 };
816 let address = if spreading_factor <= 8 {
817 RX_TOP_BASE + 185
818 } else {
819 RX_TOP_BASE + 186
820 };
821 Register::new(address, ((spreading_factor - 5) % 4) * 2, 2, false)
822}
823
824#[must_use]
849pub const fn channel_sync_offset(channel: u8) -> Register {
850 let channel = if channel > 7 { 7 } else { channel };
851 let address = ARB_MCU_BASE + 29 + (channel / 2) as u16;
852 let offset = if channel % 2 == 0 { 0 } else { 4 };
853 Register::new(address, offset, 4, false)
854}
855
856pub const AGC_MCU_STATUS: Register = Register::new(AGC_MCU_BASE + 1, 0, 8, true);
861
862pub const ARB_MCU_STATUS: Register = Register::new(ARB_MCU_BASE + 1, 0, 8, true);
864
865pub const CLOCK_RADIO_A_SELECT: Register = Register::new(CLK_CTRL_BASE, 0, 1, false);
867
868pub const CLOCK_RADIO_B_SELECT: Register = Register::new(CLK_CTRL_BASE, 1, 1, false);
870
871pub const CLOCK_DIVIDER_ENABLE: Register = Register::new(CLK_CTRL_BASE, 2, 1, false);
873
874#[must_use]
898pub const fn agc_mailbox_write(mailbox: u8) -> Register {
899 let mailbox = if mailbox > 3 { 3 } else { mailbox } as u16;
900 Register::new(AGC_MCU_BASE + 12 - mailbox, 0, 8, false)
901}
902
903#[must_use]
925pub const fn agc_mailbox_read(mailbox: u8) -> Register {
926 let mailbox = if mailbox > 3 { 3 } else { mailbox } as u16;
927 Register::new(AGC_MCU_BASE + 16 - mailbox, 0, 8, true)
928}
929
930#[must_use]
950pub const fn arbiter_config(register: u8) -> Register {
951 let register = if register > 3 { 3 } else { register } as u16;
952 Register::new(ARB_MCU_BASE + 9 + register, 0, 8, false)
953}
954
955#[must_use]
975pub const fn arbiter_status(register: u8) -> Register {
976 let register = if register > 15 { 15 } else { register } as u16;
977 Register::new(ARB_MCU_BASE + 13 + register, 0, 8, true)
978}
979
980pub const TIMESTAMP_PPS_ENABLE: Register = Register::new(TIMESTAMP_BASE, 0, 1, false);
982
983pub const TIMESTAMP_PPS_POLARITY: Register = Register::new(TIMESTAMP_BASE, 1, 1, false);
985
986#[cfg(test)]
987mod tests {
988 use super::*;
989
990 #[test]
993 fn the_blocks_are_where_the_chip_puts_them() {
994 assert_eq!(EXTERNAL_MEMORY_BASE, 0x0000);
995 assert_eq!(RX_BUFFER_BASE, 0x4000);
996 assert_eq!(TX_TOP_A_BASE, 0x5200);
997 assert_eq!(TX_TOP_B_BASE, 0x5400);
998 assert_eq!(COMMON_BASE, 0x5600);
999 assert_eq!(GPIO_BASE, 0x5640);
1000 assert_eq!(MBIST_BASE, 0x56c0);
1001 assert_eq!(RADIO_FE_BASE, 0x5700);
1002 assert_eq!(AGC_MCU_BASE, 0x5780);
1003 assert_eq!(CLK_CTRL_BASE, 0x57c0);
1004 assert_eq!(RX_TOP_BASE, 0x5800);
1005 assert_eq!(RX_TOP_LORA_SERVICE_FSK_BASE, 0x5b00);
1006 assert_eq!(CAPTURE_RAM_BASE, 0x6000);
1007 assert_eq!(ARB_MCU_BASE, 0x6080);
1008 assert_eq!(TIMESTAMP_BASE, 0x6100);
1009 assert_eq!(OTP_BASE, 0x6180);
1010 }
1011
1012 #[test]
1013 fn the_registers_sit_where_the_table_puts_them() {
1014 assert_eq!(COMMON_PAGE, Register::new(0x5600, 0, 2, false));
1015 assert_eq!(COMMON_VERSION, Register::new(0x5606, 0, 8, true));
1016 assert_eq!(OTP_BYTE_ADDR, Register::new(0x6180, 0, 8, false));
1017 assert_eq!(OTP_RD_DATA, Register::new(0x6181, 0, 8, true));
1018 assert_eq!(OTP_FSM_READY, Register::new(0x6182, 0, 1, true));
1019 assert_eq!(OTP_CHECKSUM_STATUS, Register::new(0x6182, 4, 4, true));
1020 }
1021
1022 #[test]
1023 fn the_two_microcontrollers_share_one_control_byte_each() {
1024 for register in [
1026 AGC_MCU_CLK_EN,
1027 AGC_MCU_CLEAR,
1028 AGC_MCU_HOST_PROG,
1029 AGC_MCU_PARITY_ERROR,
1030 ] {
1031 assert_eq!(register.address, AGC_MCU_BASE);
1032 assert_eq!(register.width, 1);
1033 }
1034 for register in [
1035 ARB_MCU_CLK_EN,
1036 ARB_MCU_CLEAR,
1037 ARB_MCU_HOST_PROG,
1038 ARB_MCU_PARITY_ERROR,
1039 ] {
1040 assert_eq!(register.address, ARB_MCU_BASE);
1041 assert_eq!(register.width, 1);
1042 }
1043
1044 for register in [
1046 AGC_MCU_PARITY_ERROR,
1047 ARB_MCU_PARITY_ERROR,
1048 COMMON_VERSION,
1049 OTP_RD_DATA,
1050 OTP_FSM_READY,
1051 OTP_CHECKSUM_STATUS,
1052 ] {
1053 assert!(register.read_only, "{register:?} is reported, not set");
1054 }
1055
1056 for register in [
1058 AGC_MCU_HOST_PROG,
1059 ARB_MCU_HOST_PROG,
1060 COMMON_PAGE,
1061 OTP_BYTE_ADDR,
1062 ] {
1063 assert!(!register.read_only, "{register:?} is set by the host");
1064 }
1065 }
1066
1067 #[test]
1068 fn the_front_end_controls_sit_where_the_table_puts_them() {
1069 assert_eq!(COMMON_CLK32_RIF_CTRL, Register::new(0x5601, 4, 1, false));
1070 assert_eq!(COMMON_HOST_RADIO_CTRL, Register::new(0x5601, 3, 1, false));
1071 assert_eq!(RF_EN_A_RADIO_EN, Register::new(0x5783, 2, 1, false));
1072 assert_eq!(RF_EN_A_RADIO_RST, Register::new(0x5783, 3, 1, false));
1073 assert_eq!(RF_EN_B_RADIO_EN, Register::new(0x5784, 2, 1, false));
1074 assert_eq!(RF_EN_B_RADIO_RST, Register::new(0x5784, 3, 1, false));
1075
1076 assert_eq!(RF_EN_B_RADIO_EN.address - RF_EN_A_RADIO_EN.address, 1);
1078 assert_ne!(RF_EN_A_RADIO_RST, RF_EN_B_RADIO_RST);
1079
1080 let byte = RF_EN_A_RADIO_EN.encode(0, 1);
1082 let byte = RF_EN_A_RADIO_RST.encode(byte, 1);
1083 assert_eq!(
1084 RF_EN_A_RADIO_EN.decode(byte),
1085 1,
1086 "the front end stayed powered"
1087 );
1088 assert_eq!(RF_EN_A_RADIO_RST.decode(byte), 1);
1089 }
1090
1091 #[test]
1092 fn a_narrow_register_leaves_its_neighbors_alone() {
1093 let byte = AGC_MCU_CLK_EN.encode(0x00, 1);
1095 assert_eq!(AGC_MCU_CLK_EN.decode(byte), 1);
1096
1097 let byte = AGC_MCU_HOST_PROG.encode(byte, 1);
1098 assert_eq!(AGC_MCU_HOST_PROG.decode(byte), 1);
1099 assert_eq!(AGC_MCU_CLK_EN.decode(byte), 1, "the clock stayed on");
1100
1101 let byte = AGC_MCU_HOST_PROG.encode(byte, 0);
1102 assert_eq!(AGC_MCU_HOST_PROG.decode(byte), 0);
1103 assert_eq!(
1104 AGC_MCU_CLK_EN.decode(byte),
1105 1,
1106 "and stayed on after release"
1107 );
1108 }
1109
1110 #[test]
1111 fn a_whole_byte_needs_no_read_first() {
1112 assert!(COMMON_VERSION.is_whole_byte());
1113 assert!(OTP_BYTE_ADDR.is_whole_byte());
1114 assert!(!COMMON_PAGE.is_whole_byte());
1115 assert!(!AGC_MCU_CLEAR.is_whole_byte());
1116
1117 let status = 0b1010_0001;
1119 assert_eq!(OTP_FSM_READY.decode(status), 1);
1120 assert_eq!(OTP_CHECKSUM_STATUS.decode(status), 0b1010);
1121 }
1122}