1use embedded_hal::delay::DelayNs;
16use embedded_hal::digital::{self, OutputPin};
17use embedded_hal::spi::{Operation, SpiDevice};
18
19use super::channel;
20use super::chip::{self, Model};
21use super::firmware::{self, LoadError, Mcu};
22use super::lbt;
23use super::mcu;
24use super::register::{self, Register};
25use super::spi as frame;
26use super::sx1250;
27use super::timestamp;
28use super::tx::{self, Chain, FrontEnd, Trigger, TxStatus};
29
30pub const RESET_HOLD_US: u32 = 100_000;
35
36pub const RADIO_RESET_HOLD_US: u32 = 500_000;
38
39pub const RADIO_RESET_SETTLE_US: u32 = 10_000;
41
42pub const MCU_POLL_US: u32 = 1_000;
44
45pub const MCU_ATTEMPTS: u32 = 1_000;
50
51pub const RADIO_CALIBRATE_US: u32 = 10_000;
53
54pub const ABORT_POLLS: u32 = 1_000;
57
58const fn lbt_chain_bit(chain: Chain) -> u8 {
59 match chain {
60 Chain::A => 0,
61 Chain::B => 1,
62 }
63}
64
65#[derive(Debug)]
67pub enum ConcentratorError<E> {
68 Spi(E),
70 Pin(digital::ErrorKind),
72 NotAnswering {
75 version: u8,
77 },
78 UnknownModel {
80 byte: u8,
82 },
83 Firmware(LoadError),
85 Overrun {
87 waiting: u16,
89 },
90 FrontEndMode {
92 wanted: u8,
94 read: u8,
96 },
97 ImageCalibration,
99 UnsupportedBand {
101 hertz: u32,
103 },
104 ChannelOutOfReach {
107 offset_hz: i32,
109 },
110 ServiceRate {
112 spreading_factor: u8,
114 bandwidth_hz: u32,
116 },
117 FskChannel {
119 bitrate: u32,
121 sync_word_len: u8,
123 },
124 Transmit(tx::TransmitError),
126 Stalled {
128 wanted: u8,
130 reading: u8,
132 },
133 WrongFirmware {
135 wanted: u8,
137 running: u8,
139 },
140}
141
142impl<E: core::fmt::Debug> core::error::Error for ConcentratorError<E> {}
143
144impl<E: core::fmt::Debug> core::fmt::Display for ConcentratorError<E> {
145 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
146 match self {
147 ConcentratorError::Spi(error) => write!(f, "the SPI device failed: {error:?}"),
148 ConcentratorError::Pin(kind) => write!(f, "the reset line failed: {kind:?}"),
149 ConcentratorError::NotAnswering { version } => write!(
150 f,
151 "the version register read {version:#04x} rather than {:#04x}, so no concentrator is answering",
152 chip::EXPECTED_VERSION
153 ),
154 ConcentratorError::UnknownModel { byte } => {
155 write!(f, "part number {byte:#04x} is not one this crate drives")
156 }
157 ConcentratorError::Firmware(error) => error.fmt(f),
158 ConcentratorError::Overrun { waiting } => write!(
159 f,
160 "the receive buffer holds {waiting} bytes, which is more than there is room for"
161 ),
162 ConcentratorError::FrontEndMode { wanted, read } => write!(
163 f,
164 "the front end reports mode {read} rather than {wanted}, so it never settled"
165 ),
166 ConcentratorError::ImageCalibration => {
167 f.write_str("the front end refused its own image calibration")
168 }
169 ConcentratorError::UnsupportedBand { hertz } => write!(
170 f,
171 "{hertz} Hz is outside every band a front end calibrates over"
172 ),
173 ConcentratorError::ChannelOutOfReach { offset_hz } => write!(
174 f,
175 "a channel {offset_hz} Hz from the carrier is outside the {} Hz a radio hears",
176 channel::RX_BANDWIDTH_HZ
177 ),
178 ConcentratorError::ServiceRate {
179 spreading_factor,
180 bandwidth_hz,
181 } => write!(
182 f,
183 "the service channel cannot run spreading factor {spreading_factor} at {bandwidth_hz} Hz"
184 ),
185 ConcentratorError::FskChannel {
186 bitrate,
187 sync_word_len,
188 } => write!(
189 f,
190 "the FSK channel cannot run {bitrate} bits a second with a {sync_word_len} byte sync word"
191 ),
192 ConcentratorError::Transmit(error) => error.fmt(f),
193 ConcentratorError::Stalled { wanted, reading } => write!(
194 f,
195 "a microcontroller stopped at {reading} rather than reaching {wanted}"
196 ),
197 ConcentratorError::WrongFirmware { wanted, running } => write!(
198 f,
199 "a microcontroller is running firmware {running} rather than {wanted}"
200 ),
201 }
202 }
203}
204
205fn pin<P: digital::Error, E>(error: P) -> ConcentratorError<E> {
207 ConcentratorError::Pin(error.kind())
208}
209
210pub struct Sx1302<SPI, RESET, D> {
212 spi: SPI,
213 reset: RESET,
214 delay: D,
215}
216
217impl<SPI, RESET, D> Sx1302<SPI, RESET, D> {
218 pub const fn new(spi: SPI, reset: RESET, delay: D) -> Sx1302<SPI, RESET, D> {
230 Sx1302 { spi, reset, delay }
231 }
232
233 pub fn release(self) -> (SPI, RESET, D) {
239 (self.spi, self.reset, self.delay)
240 }
241}
242
243impl<SPI, RESET, D> Sx1302<SPI, RESET, D>
244where
245 SPI: SpiDevice,
246 RESET: OutputPin,
247 D: DelayNs,
248{
249 pub fn reset(&mut self) -> Result<(), ConcentratorError<SPI::Error>> {
262 self.reset.set_high().map_err(pin)?;
263 self.delay.delay_us(RESET_HOLD_US);
264 self.reset.set_low().map_err(pin)?;
265 self.delay.delay_us(RESET_HOLD_US);
266 Ok(())
267 }
268
269 pub fn version(&mut self) -> Result<u8, ConcentratorError<SPI::Error>> {
280 self.read_register(register::COMMON_VERSION)
281 }
282
283 pub fn check(&mut self) -> Result<(), ConcentratorError<SPI::Error>> {
294 let version = self.version()?;
295 if chip::answers(version) {
296 Ok(())
297 } else {
298 Err(ConcentratorError::NotAnswering { version })
299 }
300 }
301
302 pub fn identify(&mut self) -> Result<Model, ConcentratorError<SPI::Error>> {
312 let mut answer = 0u8;
313 for step in chip::identify() {
314 match step {
315 chip::Step::Write(register, value) => self.write_register(register, value)?,
316 chip::Step::Read(register) => answer = self.read_register(register)?,
317 }
318 }
319 Ok(Model::of(answer))
320 }
321
322 pub fn reset_front_end(
340 &mut self,
341 chain: Chain,
342 front_end: FrontEnd,
343 ) -> Result<(), ConcentratorError<SPI::Error>> {
344 let (enable, held) = match chain {
345 Chain::A => (register::RF_EN_A_RADIO_EN, register::RF_EN_A_RADIO_RST),
346 Chain::B => (register::RF_EN_B_RADIO_EN, register::RF_EN_B_RADIO_RST),
347 };
348
349 self.write_register(register::COMMON_CLK32_RIF_CTRL, 0)?;
350 self.write_register(enable, 1)?;
351
352 self.write_register(held, 1)?;
353 self.delay.delay_us(RADIO_RESET_HOLD_US);
354 self.write_register(held, 0)?;
355 self.delay.delay_us(RADIO_RESET_SETTLE_US);
356
357 if matches!(front_end, FrontEnd::Sx1250) {
359 self.write_register(held, 1)?;
360 self.delay.delay_us(RADIO_CALIBRATE_US);
361 }
362
363 Ok(())
364 }
365
366 pub fn load_firmware(
387 &mut self,
388 mcu: Mcu,
389 image: &[u8],
390 ) -> Result<(), ConcentratorError<SPI::Error>> {
391 firmware::check_size(image).map_err(ConcentratorError::Firmware)?;
392
393 for step in firmware::steps(mcu) {
394 match step {
395 firmware::Load::Write(register, value) => self.write_register(register, value)?,
396 firmware::Load::WriteFirmware(address) => self.write_memory(address, image)?,
397 firmware::Load::ReadBack(address) => self.verify_memory(address, image)?,
398 firmware::Load::CheckParity(register) => {
399 if self.read_register(register)? != 0 {
400 return Err(ConcentratorError::Firmware(LoadError::ParityFailed));
401 }
402 }
403 }
404 }
405
406 Ok(())
407 }
408
409 pub fn read_register(
423 &mut self,
424 register: Register,
425 ) -> Result<u8, ConcentratorError<SPI::Error>> {
426 let byte = self.read_byte(register.address)?;
427 Ok(register.decode(byte))
428 }
429
430 pub fn write_register(
446 &mut self,
447 register: Register,
448 value: u8,
449 ) -> Result<(), ConcentratorError<SPI::Error>> {
450 let byte = if register.is_whole_byte() {
451 value
452 } else {
453 let held = self.read_byte(register.address)?;
454 register.encode(held, value)
455 };
456 self.write_byte(register.address, byte)
457 }
458
459 pub fn write_memory(
474 &mut self,
475 address: u16,
476 data: &[u8],
477 ) -> Result<(), ConcentratorError<SPI::Error>> {
478 let mut at = address;
479 let mut sent = 0usize;
480 while sent < data.len() {
481 let take = core::cmp::min(data.len() - sent, frame::BURST_CHUNK);
482 let header = frame::burst_write_header(frame::TARGET_CONCENTRATOR, at);
483 self.spi
484 .transaction(&mut [
485 Operation::Write(&header),
486 Operation::Write(&data[sent..sent + take]),
487 ])
488 .map_err(ConcentratorError::Spi)?;
489 at = at.wrapping_add(take as u16);
490 sent += take;
491 }
492 Ok(())
493 }
494
495 pub fn read_memory(
510 &mut self,
511 address: u16,
512 into: &mut [u8],
513 ) -> Result<(), ConcentratorError<SPI::Error>> {
514 self.burst_read(address, into, true)
515 }
516
517 pub fn read_fifo(
536 &mut self,
537 address: u16,
538 into: &mut [u8],
539 ) -> Result<(), ConcentratorError<SPI::Error>> {
540 self.burst_read(address, into, false)
541 }
542
543 pub fn waiting(&mut self) -> Result<u16, ConcentratorError<SPI::Error>> {
556 let first = self.buffer_count()?;
557 let second = self.buffer_count()?;
558 Ok(if second > first { second } else { first })
559 }
560
561 pub fn receive<'a>(
580 &mut self,
581 into: &'a mut [u8],
582 ) -> Result<&'a [u8], ConcentratorError<SPI::Error>> {
583 let waiting = self.waiting()?;
584 let wanted = usize::from(waiting);
585 if wanted == 0 {
586 return Ok(&[]);
587 }
588 if wanted > into.len() {
589 return Err(ConcentratorError::Overrun { waiting });
590 }
591 self.read_fifo(register::RX_BUFFER_BASE, &mut into[..wanted])?;
592 Ok(&into[..wanted])
593 }
594
595 pub fn transmit(
617 &mut self,
618 chain: Chain,
619 transmit: &tx::Transmit<'_>,
620 trigger: Trigger,
621 start_delay: u16,
622 ) -> Result<(), ConcentratorError<SPI::Error>> {
623 for (register, value) in
626 tx::settings(chain, transmit).map_err(ConcentratorError::Transmit)?
627 {
628 self.write_register(register, value)?;
629 }
630
631 self.send(chain, transmit.payload, trigger, start_delay)
632 }
633
634 pub fn send(
656 &mut self,
657 chain: Chain,
658 payload: &[u8],
659 trigger: Trigger,
660 start_delay: u16,
661 ) -> Result<(), ConcentratorError<SPI::Error>> {
662 for step in tx::steps(chain, trigger, start_delay) {
663 match step {
664 tx::Send::SetStartDelay(delay) => {
665 let bytes = tx::start_delay_bytes(delay);
666 self.write_register(chain.start_delay_msb(), bytes[0])?;
667 self.write_register(chain.start_delay_lsb(), bytes[1])?;
668 }
669 tx::Send::OpenBuffer(register) => self.write_register(register, 1)?,
670 tx::Send::WritePayload(address) => self.write_memory(address, payload)?,
671 tx::Send::CloseBuffer(register) => self.write_register(register, 0)?,
672 tx::Send::SetTimerTrigger(value) => {
673 for (index, byte) in tx::trigger_bytes(value).into_iter().enumerate() {
674 self.write_register(chain.timer_byte(index as u8), byte)?;
675 }
676 }
677 tx::Send::ResetTrigger(register) => self.write_register(register, 0)?,
678 tx::Send::ArmTrigger(register) => self.write_register(register, 1)?,
679 }
680 }
681 Ok(())
682 }
683
684 pub fn checked_transmission(
705 &mut self,
706 chain: Chain,
707 ) -> Result<bool, ConcentratorError<SPI::Error>> {
708 let mut status = 0;
709 let mut started = false;
710 for _ in 0..lbt::OUTCOME_POLLS {
711 status = self.read_register(register::AGC_MCU_STATUS)?;
712 if lbt::started(status, chain) {
713 started = true;
714 break;
715 }
716 self.delay.delay_us(MCU_POLL_US);
717 }
718 let allowed = started && !lbt::refused(status, chain);
719
720 self.write_register(register::agc_mailbox_write(0), lbt::CLEAR_TRANSMIT_STATUS)?;
721 let mut reading = status;
722 let mut cleared = false;
723 for _ in 0..lbt::OUTCOME_POLLS {
724 reading = self.read_register(register::AGC_MCU_STATUS)?;
725 if reading == 0 {
726 cleared = true;
727 break;
728 }
729 self.delay.delay_us(MCU_POLL_US);
730 }
731 self.write_register(register::agc_mailbox_write(0), lbt::ACKNOWLEDGE_CLEARED)?;
732
733 if !started {
734 return Err(ConcentratorError::Stalled {
735 wanted: 1 << lbt_chain_bit(chain),
736 reading: status,
737 });
738 }
739 if !cleared {
740 return Err(ConcentratorError::Stalled { wanted: 0, reading });
741 }
742 Ok(allowed)
743 }
744
745 pub fn abort(&mut self, chain: Chain) -> Result<(), ConcentratorError<SPI::Error>> {
759 for trigger in [Trigger::Immediate, Trigger::At(0), Trigger::OnGps] {
760 self.write_register(chain.trigger(trigger), 0)?;
761 }
762 let mut reading = 0;
763 for _ in 0..ABORT_POLLS {
764 reading = self.read_register(chain.status())?;
765 if TxStatus::of(reading).is_free() {
766 return Ok(());
767 }
768 self.delay.delay_us(MCU_POLL_US);
769 }
770 Err(ConcentratorError::Stalled {
771 wanted: tx::STATUS_FREE,
772 reading,
773 })
774 }
775
776 pub fn tx_status(&mut self, chain: Chain) -> Result<TxStatus, ConcentratorError<SPI::Error>> {
790 let value = self.read_register(chain.status())?;
791 Ok(TxStatus::of(value))
792 }
793
794 pub fn configure_channels(
813 &mut self,
814 plan: &channel::Plan,
815 ) -> Result<(), ConcentratorError<SPI::Error>> {
816 for listener in &plan.channels {
819 if listener.enabled && !channel::reachable(listener.offset_hz) {
820 return Err(ConcentratorError::ChannelOutOfReach {
821 offset_hz: listener.offset_hz,
822 });
823 }
824 }
825
826 if let Some(service) = plan.service {
829 if !channel::reachable(service.offset_hz) {
830 return Err(ConcentratorError::ChannelOutOfReach {
831 offset_hz: service.offset_hz,
832 });
833 }
834 if !service.supported() {
835 return Err(ConcentratorError::ServiceRate {
836 spreading_factor: service.spreading_factor,
837 bandwidth_hz: service.bandwidth_hz,
838 });
839 }
840 }
841
842 if let Some(fsk) = plan.fsk {
845 if !channel::reachable(fsk.offset_hz) {
846 return Err(ConcentratorError::ChannelOutOfReach {
847 offset_hz: fsk.offset_hz,
848 });
849 }
850 if !fsk.supported() {
851 return Err(ConcentratorError::FskChannel {
852 bitrate: fsk.bitrate,
853 sync_word_len: fsk.sync_word_len,
854 });
855 }
856 }
857
858 for channel::Step::Write(register, value) in channel::steps(plan) {
859 self.write_register(register, value)?;
860 }
861 Ok(())
862 }
863
864 pub fn select_clock(&mut self, chain: Chain) -> Result<(), ConcentratorError<SPI::Error>> {
882 let (a, b) = match chain {
883 Chain::A => (1, 0),
884 Chain::B => (0, 1),
885 };
886 self.write_register(register::CLOCK_RADIO_A_SELECT, a)?;
887 self.write_register(register::CLOCK_RADIO_B_SELECT, b)?;
888 self.write_register(register::CLOCK_DIVIDER_ENABLE, 1)?;
889 self.write_register(register::COMMON_CLK32_RIF_CTRL, 1)
890 }
891
892 pub fn release_front_ends(&mut self) -> Result<(), ConcentratorError<SPI::Error>> {
905 self.write_register(register::COMMON_HOST_RADIO_CTRL, 0)
906 }
907
908 pub fn start_gain_control(
934 &mut self,
935 front_end: FrontEnd,
936 listen_before_talk: bool,
937 ) -> Result<(), ConcentratorError<SPI::Error>> {
938 for step in mcu::start_gain_control(front_end, listen_before_talk) {
939 self.take(step, register::AGC_MCU_STATUS, true)?;
940 }
941 Ok(())
942 }
943
944 pub fn start_arbiter(
965 &mut self,
966 dual_demodulation: u8,
967 ) -> Result<(), ConcentratorError<SPI::Error>> {
968 for step in mcu::start_arbiter(dual_demodulation) {
969 self.take(step, register::ARB_MCU_STATUS, false)?;
970 }
971 Ok(())
972 }
973
974 fn take(
979 &mut self,
980 step: mcu::Step,
981 status: Register,
982 mailboxes: bool,
983 ) -> Result<(), ConcentratorError<SPI::Error>> {
984 match step {
985 mcu::Step::Await(wanted) => self.settle(status, wanted),
986 mcu::Step::Version(wanted) => {
987 let running = if mailboxes {
988 self.read_register(register::agc_mailbox_read(0))?
989 } else {
990 self.read_register(register::arbiter_status(0))?
991 };
992 if running == wanted {
993 Ok(())
994 } else {
995 Err(ConcentratorError::WrongFirmware { wanted, running })
996 }
997 }
998 mcu::Step::Write(index, value) => {
999 let held = if mailboxes {
1000 register::agc_mailbox_write(index)
1001 } else {
1002 register::arbiter_config(index)
1003 };
1004 self.write_register(held, value)
1005 }
1006 mcu::Step::Notify(code) => self.write_register(register::agc_mailbox_write(3), code),
1009 mcu::Step::Verify(mailbox, wanted) => {
1010 let read = self.read_register(register::agc_mailbox_read(mailbox))?;
1011 if read == wanted {
1012 Ok(())
1013 } else {
1014 Err(ConcentratorError::Stalled {
1015 wanted,
1016 reading: read,
1017 })
1018 }
1019 }
1020 }
1021 }
1022
1023 fn settle(
1029 &mut self,
1030 status: Register,
1031 wanted: u8,
1032 ) -> Result<(), ConcentratorError<SPI::Error>> {
1033 let mut reading = 0;
1034 for _ in 0..MCU_ATTEMPTS {
1035 reading = self.read_register(status)?;
1036 if reading == wanted {
1037 return Ok(());
1038 }
1039 self.delay.delay_us(MCU_POLL_US);
1040 }
1041 Err(ConcentratorError::Stalled { wanted, reading })
1042 }
1043
1044 pub fn counter(
1065 &mut self,
1066 counter: &mut timestamp::Counter,
1067 ) -> Result<(u32, u32), ConcentratorError<SPI::Error>> {
1068 let mut bytes = [0u8; timestamp::COUNTERS_LEN];
1069 self.read_memory(timestamp::COUNTERS, &mut bytes)?;
1070
1071 let mut again = [0u8; timestamp::COUNTERS_LEN];
1072 self.read_memory(timestamp::COUNTERS, &mut again)?;
1073
1074 if timestamp::disagrees(&bytes, &again) {
1075 self.read_memory(timestamp::COUNTERS, &mut bytes)?;
1076 }
1077 Ok(counter.read(&bytes))
1078 }
1079
1080 pub fn radio_command(
1100 &mut self,
1101 chain: Chain,
1102 opcode: u8,
1103 data: &[u8],
1104 ) -> Result<(), ConcentratorError<SPI::Error>> {
1105 self.delay.delay_us(sx1250::WAIT_BUSY_US);
1106 let header = sx1250::header(chain, opcode);
1107 self.spi
1108 .transaction(&mut [Operation::Write(&header), Operation::Write(data)])
1109 .map_err(ConcentratorError::Spi)
1110 }
1111
1112 pub fn radio_query(
1128 &mut self,
1129 chain: Chain,
1130 opcode: u8,
1131 into: &mut [u8],
1132 ) -> Result<(), ConcentratorError<SPI::Error>> {
1133 self.delay.delay_us(sx1250::WAIT_BUSY_US);
1134 let header = sx1250::header(chain, opcode);
1135 self.spi
1136 .transaction(&mut [Operation::Write(&header), Operation::Read(into)])
1137 .map_err(ConcentratorError::Spi)
1138 }
1139
1140 pub fn setup_front_end(
1164 &mut self,
1165 chain: Chain,
1166 hertz: u32,
1167 single_input: bool,
1168 ) -> Result<(), ConcentratorError<SPI::Error>> {
1169 for step in sx1250::setup(hertz, single_input) {
1170 match step {
1171 sx1250::Step::Standby(standby) => {
1172 self.radio_command(chain, sx1250::OP_SET_STANDBY, &[standby.value()])?;
1173 }
1174 sx1250::Step::Wait(micros) => self.delay.delay_us(micros),
1175 sx1250::Step::ExpectMode(wanted) => {
1176 let mut status = [0u8; 1];
1177 self.radio_query(chain, sx1250::OP_GET_STATUS, &mut status)?;
1178 let read = sx1250::mode(status[0]);
1179 if read != wanted {
1180 return Err(ConcentratorError::FrontEndMode { wanted, read });
1181 }
1182 }
1183 sx1250::Step::Calibrate(mask) => {
1184 self.radio_command(chain, sx1250::OP_CALIBRATE, &[mask])?;
1185 }
1186 sx1250::Step::Register(address, value) => {
1187 let [high, low] = address.to_be_bytes();
1188 self.radio_command(chain, sx1250::OP_WRITE_REGISTER, &[high, low, value])?;
1189 }
1190 sx1250::Step::ClearOffset(address) => {
1191 let [high, low] = address.to_be_bytes();
1192 self.radio_command(chain, sx1250::OP_WRITE_REGISTER, &[high, low, 0, 0, 0])?;
1193 }
1194 sx1250::Step::Tune(carrier) => {
1195 let bytes = sx1250::frequency_bytes(carrier);
1196 self.radio_command(chain, sx1250::OP_SET_RF_FREQUENCY, &bytes)?;
1197 }
1198 sx1250::Step::ListenContinuously => {
1199 self.radio_command(chain, sx1250::OP_SET_RX, &sx1250::RX_CONTINUOUS)?;
1200 }
1201 }
1202 }
1203 Ok(())
1204 }
1205
1206 pub fn calibrate_front_end(
1228 &mut self,
1229 chain: Chain,
1230 hertz: u32,
1231 ) -> Result<(), ConcentratorError<SPI::Error>> {
1232 let band = sx1250::image_band(hertz).ok_or(ConcentratorError::UnsupportedBand { hertz })?;
1233 self.radio_command(chain, sx1250::OP_CALIBRATE_IMAGE, &band)?;
1234 self.delay.delay_us(sx1250::IMAGE_CALIBRATE_US);
1235
1236 let mut errors = [0u8; 3];
1237 self.radio_query(chain, sx1250::OP_GET_DEVICE_ERRORS, &mut errors)?;
1238 if sx1250::image_failed(errors[2]) {
1239 return Err(ConcentratorError::ImageCalibration);
1240 }
1241 Ok(())
1242 }
1243
1244 fn buffer_count(&mut self) -> Result<u16, ConcentratorError<SPI::Error>> {
1246 let high = self.read_register(register::RX_BUFFER_NB_BYTES_MSB)?;
1247 let low = self.read_register(register::RX_BUFFER_NB_BYTES_LSB)?;
1248 Ok((u16::from(high) << 8) | u16::from(low))
1249 }
1250
1251 fn burst_read(
1253 &mut self,
1254 address: u16,
1255 into: &mut [u8],
1256 advance: bool,
1257 ) -> Result<(), ConcentratorError<SPI::Error>> {
1258 let mut at = address;
1259 let mut read = 0usize;
1260 while read < into.len() {
1261 let take = core::cmp::min(into.len() - read, frame::BURST_CHUNK);
1262 let header = frame::burst_read_header(frame::TARGET_CONCENTRATOR, at);
1263 self.spi
1264 .transaction(&mut [
1265 Operation::Write(&header),
1266 Operation::Read(&mut into[read..read + take]),
1267 ])
1268 .map_err(ConcentratorError::Spi)?;
1269 if advance {
1270 at = at.wrapping_add(take as u16);
1271 }
1272 read += take;
1273 }
1274 Ok(())
1275 }
1276
1277 fn verify_memory(
1282 &mut self,
1283 address: u16,
1284 written: &[u8],
1285 ) -> Result<(), ConcentratorError<SPI::Error>> {
1286 let mut chunk = [0u8; frame::BURST_CHUNK];
1287 let mut at = address;
1288 let mut done = 0usize;
1289
1290 while done < written.len() {
1291 let take = core::cmp::min(written.len() - done, frame::BURST_CHUNK);
1292 self.read_memory(at, &mut chunk[..take])?;
1293
1294 if let Err(LoadError::ReadBackDiffers { at: differs }) =
1295 firmware::compare(&written[done..done + take], &chunk[..take])
1296 {
1297 return Err(ConcentratorError::Firmware(LoadError::ReadBackDiffers {
1298 at: done + differs,
1299 }));
1300 }
1301
1302 at = at.wrapping_add(take as u16);
1303 done += take;
1304 }
1305
1306 Ok(())
1307 }
1308
1309 fn read_byte(&mut self, address: u16) -> Result<u8, ConcentratorError<SPI::Error>> {
1311 let out = frame::read(frame::TARGET_CONCENTRATOR, address);
1312 let mut back = [0u8; frame::READ_LEN];
1313 self.spi
1314 .transfer(&mut back, &out)
1315 .map_err(ConcentratorError::Spi)?;
1316 Ok(frame::read_value(&back).unwrap_or(0))
1317 }
1318
1319 fn write_byte(&mut self, address: u16, value: u8) -> Result<(), ConcentratorError<SPI::Error>> {
1321 self.spi
1322 .write(&frame::write(frame::TARGET_CONCENTRATOR, address, value))
1323 .map_err(ConcentratorError::Spi)
1324 }
1325}
1326
1327#[cfg(test)]
1328mod tests {
1329 use pamoja_hal::script::{DelayLog, PinScript, SpiScript, SpiStep};
1330
1331 use super::*;
1332
1333 fn driven(steps: Vec<SpiStep>) -> Sx1302<SpiScript, PinScript, DelayLog> {
1335 Sx1302::new(SpiScript::new(steps), PinScript::new([]), DelayLog::new())
1336 }
1337
1338 #[test]
1339 fn a_channel_the_radio_cannot_hear_is_refused_before_the_bus_is_touched() {
1340 let mut chip = driven(Vec::new());
1344 let plan = channel::Plan::new(867_800_000, &[1_000_000]);
1345
1346 let refused = chip
1347 .configure_channels(&plan)
1348 .expect_err("a megahertz is past the radio window");
1349 assert!(matches!(
1350 refused,
1351 ConcentratorError::ChannelOutOfReach {
1352 offset_hz: 1_000_000
1353 }
1354 ));
1355 }
1356
1357 fn reads(address: u16, value: u8) -> SpiStep {
1359 let mut reply = [0u8; frame::READ_LEN];
1360 reply[frame::READ_LEN - 1] = value;
1361 SpiStep::transfer(
1362 frame::read(frame::TARGET_CONCENTRATOR, address).to_vec(),
1363 reply.to_vec(),
1364 )
1365 }
1366
1367 fn writes(address: u16, value: u8) -> SpiStep {
1369 SpiStep::write(frame::write(frame::TARGET_CONCENTRATOR, address, value).to_vec())
1370 }
1371
1372 fn fetches(address: u16, reply: Vec<u8>) -> Vec<SpiStep> {
1374 vec![
1375 SpiStep::write(frame::burst_read_header(frame::TARGET_CONCENTRATOR, address).to_vec()),
1376 SpiStep::read(reply),
1377 ]
1378 }
1379
1380 fn sends(address: u16, payload: Vec<u8>) -> Vec<SpiStep> {
1382 vec![
1383 SpiStep::write(frame::burst_write_header(frame::TARGET_CONCENTRATOR, address).to_vec()),
1384 SpiStep::write(payload),
1385 ]
1386 }
1387
1388 #[test]
1389 fn pointing_a_concentrator_at_its_channels_ends_by_switching_them_on() {
1390 let plan = channel::Plan::new(867_500_000, &[-400_000, -200_000, 0]);
1391
1392 let mut steps = Vec::new();
1395 for channel::Step::Write(held, value) in channel::steps(&plan) {
1396 if held.is_whole_byte() {
1397 steps.push(writes(held.address, value));
1398 } else {
1399 steps.push(reads(held.address, 0));
1400 steps.push(writes(held.address, held.encode(0, value)));
1401 }
1402 }
1403
1404 let mut chip = driven(steps);
1406 chip.configure_channels(&plan).expect("the bus answers");
1407
1408 let channel::Step::Write(last, value) =
1409 channel::steps(&plan).last().expect("there are steps");
1410 assert_eq!(last, register::COMMON_GLOBAL_ENABLE);
1411 assert_eq!(value, 0x01);
1412 }
1413
1414 #[test]
1415 fn a_checked_transmission_reports_whether_the_channel_let_it_go() {
1416 let status = register::AGC_MCU_STATUS.address;
1420 let mailbox = register::agc_mailbox_write(0).address;
1421 let mut chip = driven(vec![
1422 reads(status, 0x00),
1423 reads(status, 0x00),
1424 reads(status, 0x01),
1425 writes(mailbox, 0xff),
1426 reads(status, 0x01),
1427 reads(status, 0x00),
1428 writes(mailbox, 0x00),
1429 ]);
1430 assert!(chip
1431 .checked_transmission(Chain::A)
1432 .expect("the bus answers"));
1433
1434 let mut chip = driven(vec![
1436 reads(status, 0x41),
1437 writes(mailbox, 0xff),
1438 reads(status, 0x00),
1439 writes(mailbox, 0x00),
1440 ]);
1441 assert!(!chip
1442 .checked_transmission(Chain::A)
1443 .expect("the bus answers"));
1444
1445 let mut chip = driven(vec![
1447 reads(status, 0x42),
1448 writes(mailbox, 0xff),
1449 reads(status, 0x00),
1450 writes(mailbox, 0x00),
1451 ]);
1452 assert!(chip
1453 .checked_transmission(Chain::B)
1454 .expect("the bus answers"));
1455 }
1456
1457 #[test]
1458 fn a_checked_transmission_that_never_starts_still_clears_its_status() {
1459 let status = register::AGC_MCU_STATUS.address;
1460 let mailbox = register::agc_mailbox_write(0).address;
1461 let mut steps: Vec<SpiStep> = (0..lbt::OUTCOME_POLLS)
1462 .map(|_| reads(status, 0x00))
1463 .collect();
1464 steps.extend([
1465 writes(mailbox, 0xff),
1466 reads(status, 0x00),
1467 writes(mailbox, 0x00),
1468 ]);
1469 let mut chip = driven(steps);
1470 assert!(matches!(
1471 chip.checked_transmission(Chain::A),
1472 Err(ConcentratorError::Stalled {
1473 wanted: 0x01,
1474 reading: 0x00
1475 })
1476 ));
1477 let (spi, _, _) = chip.release();
1478 assert!(
1479 spi.done(),
1480 "the clear and the acknowledgment still went out"
1481 );
1482 }
1483
1484 #[test]
1485 fn aborting_resets_every_trigger_then_waits_for_the_chain() {
1486 let chain = Chain::A;
1489 let mut steps = Vec::new();
1490 for trigger in [Trigger::Immediate, Trigger::At(0), Trigger::OnGps] {
1491 let held = chain.trigger(trigger);
1492 steps.push(reads(held.address, 0x07));
1493 steps.push(writes(held.address, held.encode(0x07, 0)));
1494 }
1495 steps.extend([
1496 reads(chain.status().address, 0x91),
1497 reads(chain.status().address, 0x91),
1498 reads(chain.status().address, tx::STATUS_FREE),
1499 ]);
1500 let mut chip = driven(steps);
1501 chip.abort(chain).expect("the chain comes free");
1502 let (spi, _, _) = chip.release();
1503 assert!(spi.done());
1504 }
1505
1506 #[test]
1507 fn the_counter_is_read_twice_and_kept_from_the_first() {
1508 let mut steps = fetches(0x6101, vec![0, 0, 0, 32, 0, 0, 0, 64]);
1510 steps.extend(fetches(0x6101, vec![0, 0, 0, 32, 0, 0, 0, 64]));
1511 let mut chip = driven(steps);
1512
1513 let mut counter = timestamp::Counter::new();
1514 let (free, pulse) = chip.counter(&mut counter).expect("the bus answers");
1515 assert_eq!((free, pulse), (2, 1));
1516 }
1517
1518 #[test]
1519 fn a_counter_that_stepped_between_readings_is_read_again() {
1520 let mut steps = fetches(0x6101, vec![0, 0, 0, 32, 0, 0, 0, 64]);
1523 steps.extend(fetches(0x6101, vec![0, 0, 0, 32, 1, 0, 0, 0]));
1524 steps.extend(fetches(0x6101, vec![0, 0, 0, 32, 0, 0, 1, 0]));
1525 let mut chip = driven(steps);
1526
1527 let mut counter = timestamp::Counter::new();
1528 let (free, _) = chip.counter(&mut counter).expect("the bus answers");
1529 assert_eq!(free, 8);
1530 }
1531
1532 fn a_front_end_is_told(chain: Chain, opcode: u8, data: Vec<u8>) -> Vec<SpiStep> {
1534 vec![
1535 SpiStep::write(sx1250::header(chain, opcode).to_vec()),
1536 SpiStep::write(data),
1537 ]
1538 }
1539
1540 fn a_front_end_answers(chain: Chain, opcode: u8, reply: Vec<u8>) -> Vec<SpiStep> {
1542 vec![
1543 SpiStep::write(sx1250::header(chain, opcode).to_vec()),
1544 SpiStep::read(reply),
1545 ]
1546 }
1547
1548 #[test]
1549 fn the_clock_moves_to_the_radio_before_anything_is_configured() {
1550 let mut chip = driven(vec![
1553 reads(0x57c0, 0),
1554 writes(0x57c0, 0b0000_0001),
1555 reads(0x57c0, 0b0000_0001),
1556 writes(0x57c0, 0b0000_0001),
1557 reads(0x57c0, 0b0000_0001),
1558 writes(0x57c0, 0b0000_0101),
1559 reads(0x5601, 0),
1560 writes(0x5601, 0b0001_0000),
1561 ]);
1562
1563 chip.select_clock(Chain::A).expect("the bus answers");
1564 }
1565
1566 #[test]
1567 fn the_second_radio_carries_the_clock_when_it_is_asked_to() {
1568 let mut chip = driven(vec![
1569 reads(0x57c0, 0b0000_0001),
1570 writes(0x57c0, 0b0000_0000),
1571 reads(0x57c0, 0),
1572 writes(0x57c0, 0b0000_0010),
1573 reads(0x57c0, 0b0000_0010),
1574 writes(0x57c0, 0b0000_0110),
1575 reads(0x5601, 0),
1576 writes(0x5601, 0b0001_0000),
1577 ]);
1578
1579 chip.select_clock(Chain::B).expect("the bus answers");
1580 }
1581
1582 #[test]
1583 fn a_microcontroller_that_never_answers_is_given_up_on() {
1584 let steps = vec![reads(0x5781, 0x00); MCU_ATTEMPTS as usize];
1587 let mut chip = driven(steps);
1588
1589 match chip.start_gain_control(FrontEnd::Sx1250, false) {
1590 Err(ConcentratorError::Stalled { wanted, reading }) => {
1591 assert_eq!((wanted, reading), (mcu::STATUS_RUNNING, 0x00));
1592 }
1593 other => panic!("a silent microcontroller is reported: {other:?}"),
1594 }
1595 }
1596
1597 #[test]
1598 fn firmware_the_crate_does_not_drive_is_named() {
1599 let mut chip = driven(vec![reads(0x5781, mcu::STATUS_RUNNING), reads(0x5790, 3)]);
1601
1602 match chip.start_gain_control(FrontEnd::Sx1250, false) {
1603 Err(ConcentratorError::WrongFirmware { wanted, running }) => {
1604 assert_eq!((wanted, running), (mcu::AGC_VERSION_SX1250, 3));
1605 }
1606 other => panic!("the version it is running is reported: {other:?}"),
1607 }
1608 }
1609
1610 #[test]
1611 fn the_arbiter_reads_its_version_from_its_own_register() {
1612 let mut chip = driven(vec![reads(0x6081, mcu::STATUS_RUNNING), reads(0x608d, 1)]);
1615
1616 match chip.start_arbiter(0x00) {
1617 Err(ConcentratorError::WrongFirmware { wanted, running }) => {
1618 assert_eq!((wanted, running), (mcu::ARB_VERSION, 1));
1619 }
1620 other => panic!("the arbiter version is read from 0x608d: {other:?}"),
1621 }
1622 }
1623
1624 #[test]
1625 fn bringing_a_front_end_up_tunes_it_and_leaves_it_listening() {
1626 let mut steps = a_front_end_is_told(Chain::A, sx1250::OP_SET_STANDBY, vec![0x00]);
1629 steps.extend(a_front_end_answers(
1630 Chain::A,
1631 sx1250::OP_GET_STATUS,
1632 vec![0x20],
1633 ));
1634 steps.extend(a_front_end_is_told(
1635 Chain::A,
1636 sx1250::OP_CALIBRATE,
1637 vec![0x7f],
1638 ));
1639 steps.extend(a_front_end_is_told(
1640 Chain::A,
1641 sx1250::OP_SET_STANDBY,
1642 vec![0x01],
1643 ));
1644 steps.extend(a_front_end_answers(
1645 Chain::A,
1646 sx1250::OP_GET_STATUS,
1647 vec![0x30],
1648 ));
1649 for (high, low, value) in [
1650 (0x06, 0xa1, 0x01),
1651 (0x06, 0xa2, 0x00),
1652 (0x06, 0xa3, 0x00),
1653 (0x05, 0x82, 0x00),
1654 (0x05, 0x83, 0x00),
1655 (0x05, 0x84, 0x00),
1656 (0x05, 0x85, 0x00),
1657 (0x05, 0x80, 0x00),
1658 (0x08, 0xb6, 0x2a),
1659 ] {
1660 steps.extend(a_front_end_is_told(
1661 Chain::A,
1662 sx1250::OP_WRITE_REGISTER,
1663 vec![high, low, value],
1664 ));
1665 }
1666 steps.extend(a_front_end_is_told(
1667 Chain::A,
1668 sx1250::OP_SET_RF_FREQUENCY,
1669 vec![0x36, 0x41, 0x99, 0x99],
1670 ));
1671 steps.extend(a_front_end_is_told(
1672 Chain::A,
1673 sx1250::OP_WRITE_REGISTER,
1674 vec![0x08, 0x8f, 0x00, 0x00, 0x00],
1675 ));
1676 steps.extend(a_front_end_is_told(
1677 Chain::A,
1678 sx1250::OP_SET_RX,
1679 vec![0xff, 0xff, 0xff],
1680 ));
1681 steps.extend(a_front_end_is_told(
1682 Chain::A,
1683 sx1250::OP_WRITE_REGISTER,
1684 vec![0x05, 0x87, 0x0b],
1685 ));
1686
1687 let mut chip = driven(steps);
1688 chip.setup_front_end(Chain::A, 868_100_000, false)
1689 .expect("the bus answers");
1690 }
1691
1692 #[test]
1693 fn a_front_end_that_never_settles_says_what_it_read() {
1694 let mut steps = a_front_end_is_told(Chain::B, sx1250::OP_SET_STANDBY, vec![0x00]);
1697 steps.extend(a_front_end_answers(
1698 Chain::B,
1699 sx1250::OP_GET_STATUS,
1700 vec![0x00],
1701 ));
1702
1703 let mut chip = driven(steps);
1704 match chip.setup_front_end(Chain::B, 868_100_000, false) {
1705 Err(ConcentratorError::FrontEndMode { wanted, read }) => {
1706 assert_eq!((wanted, read), (0x02, 0x00));
1707 }
1708 other => panic!("a front end that never settles is reported: {other:?}"),
1709 }
1710 }
1711
1712 #[test]
1713 fn a_carrier_outside_every_band_is_refused_before_the_bus() {
1714 let mut chip = driven(vec![]);
1716 match chip.calibrate_front_end(Chain::A, 880_000_000) {
1717 Err(ConcentratorError::UnsupportedBand { hertz }) => assert_eq!(hertz, 880_000_000),
1718 other => panic!("a carrier between the bands is refused: {other:?}"),
1719 }
1720 }
1721
1722 #[test]
1723 fn a_front_end_that_refuses_its_calibration_is_reported() {
1724 let mut steps = a_front_end_is_told(Chain::A, sx1250::OP_CALIBRATE_IMAGE, vec![0xd7, 0xdb]);
1725 steps.extend(a_front_end_answers(
1726 Chain::A,
1727 sx1250::OP_GET_DEVICE_ERRORS,
1728 vec![0x00, 0x00, 0b0001_0000],
1729 ));
1730
1731 let mut chip = driven(steps);
1732 assert!(matches!(
1733 chip.calibrate_front_end(Chain::A, 868_100_000),
1734 Err(ConcentratorError::ImageCalibration)
1735 ));
1736 }
1737
1738 #[test]
1739 fn a_calibrated_front_end_reports_nothing() {
1740 let mut steps = a_front_end_is_told(Chain::A, sx1250::OP_CALIBRATE_IMAGE, vec![0xe1, 0xe9]);
1741 steps.extend(a_front_end_answers(
1742 Chain::A,
1743 sx1250::OP_GET_DEVICE_ERRORS,
1744 vec![0x00, 0x00, 0x00],
1745 ));
1746
1747 let mut chip = driven(steps);
1748 chip.calibrate_front_end(Chain::A, 915_000_000)
1749 .expect("the bus answers");
1750 }
1751
1752 #[test]
1753 fn a_quiet_concentrator_hands_back_nothing() {
1754 let mut chip = driven(vec![
1755 reads(0x58c8, 0),
1756 reads(0x58c9, 0),
1757 reads(0x58c8, 0),
1758 reads(0x58c9, 0),
1759 ]);
1760
1761 let mut buffer = [0u8; 32];
1762 assert!(chip
1763 .receive(&mut buffer)
1764 .expect("the bus answers")
1765 .is_empty());
1766 }
1767
1768 #[test]
1769 fn the_byte_count_is_read_twice_and_the_larger_kept() {
1770 let mut steps = vec![
1773 reads(0x58c8, 0),
1774 reads(0x58c9, 2),
1775 reads(0x58c8, 0),
1776 reads(0x58c9, 5),
1777 ];
1778 steps.extend(fetches(0x4000, vec![1, 2, 3, 4, 5]));
1779 let mut chip = driven(steps);
1780
1781 let mut buffer = [0u8; 32];
1782 let heard = chip.receive(&mut buffer).expect("the bus answers");
1783 assert_eq!(heard, [1, 2, 3, 4, 5]);
1784 }
1785
1786 #[test]
1787 fn more_than_fits_is_refused_before_a_byte_is_read() {
1788 let mut chip = driven(vec![
1791 reads(0x58c8, 0),
1792 reads(0x58c9, 16),
1793 reads(0x58c8, 0),
1794 reads(0x58c9, 16),
1795 ]);
1796
1797 let mut buffer = [0u8; 8];
1798 match chip.receive(&mut buffer) {
1799 Err(ConcentratorError::Overrun { waiting }) => assert_eq!(waiting, 16),
1800 other => panic!("a buffer too small is refused, not filled: {other:?}"),
1801 }
1802 }
1803
1804 #[test]
1805 fn a_fetch_larger_than_one_chunk_reads_the_same_port_again() {
1806 let mut steps = fetches(0x4000, vec![0xa5; frame::BURST_CHUNK]);
1810 steps.extend(fetches(0x4000, vec![0xc0; 100]));
1811 let mut chip = driven(steps);
1812
1813 let mut buffer = [0u8; frame::BURST_CHUNK + 100];
1814 chip.read_fifo(0x4000, &mut buffer)
1815 .expect("the bus answers");
1816 assert_eq!(buffer[0], 0xa5);
1817 assert_eq!(buffer[frame::BURST_CHUNK], 0xc0);
1818 }
1819
1820 #[test]
1821 fn a_packet_the_chain_cannot_describe_never_reaches_the_bus() {
1822 let mut chip = driven(Vec::new());
1826 let request = tx::Transmit {
1827 frequency_hz: 868_100_000,
1828 link: pamoja_lora::LinkSettings::new(7, 62_500),
1829 gain: tx::DEFAULT_GAINS[0],
1830 invert_polarity: true,
1831 public: true,
1832 payload: &[0x01],
1833 };
1834
1835 let refused = chip
1836 .transmit(Chain::A, &request, Trigger::Immediate, 0x0102)
1837 .expect_err("a chain does not transmit at 62500 Hz");
1838 assert!(matches!(
1839 refused,
1840 ConcentratorError::Transmit(tx::TransmitError::Bandwidth { hertz: 62_500 })
1841 ));
1842 }
1843
1844 #[test]
1845 fn a_send_loads_the_payload_before_it_arms_the_trigger() {
1846 let mut steps = vec![
1849 writes(0x5205, 0x01),
1850 writes(0x5206, 0x02),
1851 reads(0x5207, 0),
1852 writes(0x5207, 1),
1853 ];
1854 steps.extend(sends(0x5300, vec![0xde, 0xad]));
1855 steps.extend(vec![
1856 reads(0x5207, 1),
1857 writes(0x5207, 0),
1858 reads(0x5200, 0),
1859 writes(0x5200, 0),
1860 reads(0x5200, 0),
1861 writes(0x5200, 1),
1862 ]);
1863 let mut chip = driven(steps);
1864
1865 chip.send(Chain::A, &[0xde, 0xad], Trigger::Immediate, 0x0102)
1866 .expect("the bus answers");
1867 }
1868
1869 #[test]
1870 fn a_timed_send_counts_down_the_addresses() {
1871 let mut steps = vec![
1875 writes(0x5205, 0x01),
1876 writes(0x5206, 0x02),
1877 reads(0x5207, 0),
1878 writes(0x5207, 1),
1879 ];
1880 steps.extend(sends(0x5300, vec![0x01]));
1881 steps.extend(vec![
1882 reads(0x5207, 1),
1883 writes(0x5207, 0),
1884 writes(0x5204, 0xfe),
1885 writes(0x5203, 0x46),
1886 writes(0x5202, 0xe8),
1887 writes(0x5201, 0x01),
1888 reads(0x5200, 0),
1889 writes(0x5200, 0),
1890 reads(0x5200, 0),
1891 writes(0x5200, 0b10),
1892 ]);
1893 let mut chip = driven(steps);
1894
1895 chip.send(Chain::A, &[0x01], Trigger::At(1_000_000), 0x0102)
1896 .expect("the bus answers");
1897 }
1898
1899 #[test]
1900 fn a_chain_that_will_take_a_packet_reads_free() {
1901 let mut chip = driven(vec![reads(0x5211, tx::STATUS_FREE)]);
1902
1903 let status = chip.tx_status(Chain::A).expect("the bus answers");
1904 assert!(status.is_free(), "{status:?}");
1905 }
1906
1907 #[test]
1908 fn a_concentrator_that_answers_reads_the_documented_version() {
1909 let mut chip = driven(vec![reads(0x5606, chip::EXPECTED_VERSION)]);
1910 assert_eq!(chip.version().expect("the bus answers"), 0x10);
1911 }
1912
1913 #[test]
1914 fn a_board_that_is_not_there_says_what_it_read() {
1915 for absent in [0x00, 0xff] {
1918 let mut chip = driven(vec![reads(0x5606, absent)]);
1919 match chip.check() {
1920 Err(ConcentratorError::NotAnswering { version }) => assert_eq!(version, absent),
1921 other => panic!("a silent board is reported, not accepted: {other:?}"),
1922 }
1923 }
1924
1925 let mut chip = driven(vec![reads(0x5606, chip::EXPECTED_VERSION)]);
1926 assert!(chip.check().is_ok());
1927 }
1928
1929 #[test]
1930 fn identifying_selects_the_byte_then_reads_it() {
1931 let mut chip = driven(vec![
1934 writes(0x6180, chip::MODEL_BYTE_ADDRESS),
1935 reads(0x6181, 0x03),
1936 ]);
1937 assert_eq!(chip.identify().expect("the bus answers"), Model::Sx1303);
1938
1939 let mut chip = driven(vec![
1940 writes(0x6180, chip::MODEL_BYTE_ADDRESS),
1941 reads(0x6181, 0x02),
1942 ]);
1943 assert_eq!(chip.identify().expect("the bus answers"), Model::Sx1302);
1944 }
1945
1946 #[test]
1947 fn a_narrow_register_is_read_before_it_is_written() {
1948 let held = 0b0000_1000; let mut chip = driven(vec![
1952 reads(0x5601, held),
1953 writes(0x5601, held | 0b0001_0000),
1954 ]);
1955
1956 chip.write_register(register::COMMON_CLK32_RIF_CTRL, 1)
1957 .expect("the bus answers");
1958 }
1959
1960 #[test]
1961 fn a_whole_byte_is_written_without_reading_it_first() {
1962 let mut chip = driven(vec![writes(0x6180, 0xd0)]);
1964 chip.write_register(register::OTP_BYTE_ADDR, 0xd0)
1965 .expect("the bus answers");
1966 }
1967
1968 #[test]
1969 fn resetting_a_front_end_clocks_the_chip_from_the_host_first() {
1970 let mut chip = driven(vec![
1973 reads(0x5601, 0),
1974 writes(0x5601, 0),
1975 reads(0x5783, 0),
1976 writes(0x5783, 0b0000_0100),
1977 reads(0x5783, 0b0000_0100),
1978 writes(0x5783, 0b0000_1100),
1979 reads(0x5783, 0b0000_1100),
1980 writes(0x5783, 0b0000_0100),
1981 ]);
1982
1983 chip.reset_front_end(Chain::A, FrontEnd::Sx125x)
1984 .expect("the bus answers");
1985 }
1986
1987 #[test]
1988 fn an_sx1250_is_held_again_while_it_calibrates() {
1989 let mut chip = driven(vec![
1992 reads(0x5601, 0),
1993 writes(0x5601, 0),
1994 reads(0x5784, 0),
1995 writes(0x5784, 0b0000_0100),
1996 reads(0x5784, 0b0000_0100),
1997 writes(0x5784, 0b0000_1100),
1998 reads(0x5784, 0b0000_1100),
1999 writes(0x5784, 0b0000_0100),
2000 reads(0x5784, 0b0000_0100),
2001 writes(0x5784, 0b0000_1100),
2002 ]);
2003
2004 chip.reset_front_end(Chain::B, FrontEnd::Sx1250)
2005 .expect("the bus answers");
2006 }
2007
2008 #[test]
2009 fn an_image_of_the_wrong_size_never_reaches_the_bus() {
2010 let mut chip = driven(vec![]);
2012 match chip.load_firmware(Mcu::Agc, &[0u8; 16]) {
2013 Err(ConcentratorError::Firmware(LoadError::WrongSize { offered })) => {
2014 assert_eq!(offered, 16);
2015 }
2016 other => panic!("a short image is refused before anything is written: {other:?}"),
2017 }
2018 }
2019
2020 #[test]
2021 fn the_reset_line_is_pulsed_and_then_released() {
2022 let mut chip = driven(vec![]);
2023 chip.reset().expect("the line is drivable");
2024
2025 let (_, pins, delay) = chip.release();
2026 assert_eq!(
2027 pins.driven(),
2028 [digital::PinState::High, digital::PinState::Low]
2029 );
2030 assert_eq!(
2031 delay.waits_ns().len(),
2032 2,
2033 "held, then given time to come up"
2034 );
2035 }
2036}