Brak opisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

radio.rs 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. use core::convert::TryInto;
  2. use embedded_hal::blocking::delay::DelayMs;
  3. use embedded_hal::digital::v2::OutputPin;
  4. use embedded_nrf24l01::{Configuration, CrcMode, DataRate, RxMode, StandbyMode, NRF24L01};
  5. use mkl25z4_hal::time::CopyableMonoTimer;
  6. use mkl25z4_hal::NoError;
  7. use protocol::{Packet, Report, Value};
  8. use super::pins::{RadioCe, RadioCs, RadioIrq, RadioPins, RadioPwr, RadioSpi};
  9. use super::sensors::BME280Data;
  10. const DEVICE_ID: u8 = 0x20;
  11. const KEY: [u8; 16] = include!("../../../common/display_key.txt");
  12. pub struct Radio {
  13. nrf24: Option<NRF24L01<NoError, RadioCe, RadioCs, RadioSpi>>,
  14. pwr: RadioPwr,
  15. irq: RadioIrq,
  16. salt: Option<u64>,
  17. time: CopyableMonoTimer,
  18. }
  19. impl Radio {
  20. pub fn init(mut pins: RadioPins, time: CopyableMonoTimer) -> Radio {
  21. pins.pwr.set_low().ok();
  22. let nrf24 = NRF24L01::new(pins.ce, pins.cs, pins.spi).unwrap();
  23. let nrf24 = nrf24.power_down().unwrap();
  24. pins.pwr.set_high().ok();
  25. Radio {
  26. nrf24: Some(nrf24),
  27. pwr: pins.pwr,
  28. irq: pins.irq,
  29. salt: None,
  30. time,
  31. }
  32. }
  33. pub fn enable<'a>(&'a mut self) -> EnabledRadio<'a> {
  34. // Enable supply voltage.
  35. self.pwr.set_low().ok();
  36. self.time.delay_ms(10u8);
  37. // Configure the device.
  38. let nrf24 = self.nrf24.take().unwrap();
  39. let mut nrf24 = StandbyMode::power_up(nrf24).unwrap();
  40. self.time.delay_ms(2u8);
  41. nrf24.set_frequency(0x32).unwrap();
  42. nrf24.set_rf(DataRate::R2Mbps, 3).unwrap();
  43. nrf24.set_crc(Some(CrcMode::OneByte)).unwrap();
  44. nrf24.set_auto_retransmit(250, 1).unwrap();
  45. nrf24.set_auto_ack(&[true; 6]).unwrap();
  46. nrf24
  47. .set_pipes_rx_enable(&[true, true, false, false, false, false])
  48. .unwrap();
  49. nrf24.set_tx_addr(&[0xB3, 0xB3, 0xB3, 0xB3, 0x00]).unwrap();
  50. nrf24
  51. .set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
  52. .unwrap();
  53. nrf24
  54. .set_rx_addr(1, &[0xB3, 0xB3, 0xB3, 0xB3, 0x20])
  55. .unwrap();
  56. nrf24.flush_rx().unwrap();
  57. nrf24.flush_tx().unwrap();
  58. nrf24.set_pipes_rx_lengths(&[Some(32); 6]).unwrap();
  59. EnabledRadio {
  60. radio: self,
  61. nrf24: Some(nrf24),
  62. }
  63. }
  64. }
  65. pub struct EnabledRadio<'a> {
  66. radio: &'a mut Radio,
  67. nrf24: Option<StandbyMode<NRF24L01<NoError, RadioCe, RadioCs, RadioSpi>>>,
  68. }
  69. impl<'a> EnabledRadio<'a> {
  70. // TODO: Use generic "SensorValues" instead of BME280Data, which includes ambient light
  71. // readings
  72. pub fn send_sensor_values(&mut self, values: BME280Data) -> bool {
  73. if self.radio.salt.is_none() {
  74. if !self.fetch_salt() {
  75. return false;
  76. }
  77. }
  78. let mut tx = self.nrf24.take().unwrap().tx().unwrap();
  79. while !tx.can_send().unwrap() {}
  80. let mut payload = [0u8; 32];
  81. let mut report = Report {
  82. count: 3,
  83. values: [Value::Invalid; 8],
  84. };
  85. report.values[0] = Value::Temperature(values.temperature as i16);
  86. report.values[1] = Value::Pressure(values.pressure);
  87. report.values[2] = Value::Humidity(values.humidity as u16);
  88. let packet = Packet::Report(report);
  89. packet.encode_and_encrypt(&KEY, self.radio.salt.unwrap(), &mut payload);
  90. tx.send(&payload).unwrap();
  91. // TODO: Check whether the packet arrived.
  92. self.nrf24 = Some(tx.standby().unwrap());
  93. true
  94. }
  95. fn fetch_salt(&mut self) -> bool {
  96. // Request a device ID.
  97. let mut tx = self.nrf24.take().unwrap().tx().unwrap();
  98. while !tx.can_send().unwrap() {}
  99. let mut payload = [0u8; 32];
  100. let packet = Packet::GetSalt;
  101. packet.encode_and_encrypt(&KEY, DEVICE_ID as u64, &mut payload);
  102. tx.send(&payload).unwrap();
  103. // TODO: Check whether the packet arrived.
  104. // Wait for the initial salt.
  105. let mut salt_received = false;
  106. let mut rx = tx.standby().unwrap().rx().unwrap();
  107. loop {
  108. let packet = match self.receive_packet(&mut rx) {
  109. None => break,
  110. Some(p) => p,
  111. };
  112. match packet {
  113. Packet::Salt(salt) => {
  114. self.radio.salt = Some((salt & 0x7fffffffffffff00) | DEVICE_ID as u64);
  115. salt_received = true;
  116. break;
  117. }
  118. _ => continue,
  119. }
  120. }
  121. self.nrf24 = Some(rx.standby());
  122. salt_received
  123. }
  124. fn receive_packet(
  125. &mut self,
  126. rx: &mut RxMode<NRF24L01<NoError, RadioCe, RadioCs, RadioSpi>>,
  127. ) -> Option<Packet> {
  128. // TODO: Timeout.
  129. loop {
  130. if let Some(_pipe) = rx.can_read().unwrap() {
  131. // Receive a packet.
  132. // TODO: Check pipe?
  133. let payload = rx.read().unwrap();
  134. if payload.len() != 32 {
  135. continue;
  136. }
  137. let mut payload: [u8; 32] = payload[0..32].try_into().unwrap();
  138. let packet = match Packet::decrypt_and_decode(&KEY, &mut payload) {
  139. Ok(p) => p,
  140. Err(_) => continue,
  141. };
  142. return Some(packet);
  143. }
  144. }
  145. }
  146. }
  147. impl<'a> Drop for EnabledRadio<'a> {
  148. fn drop(&mut self) {
  149. let nrf24 = self.nrf24.take().unwrap();
  150. // Disable the chip and remove the supply voltage.
  151. let nrf24 = nrf24.power_down().unwrap();
  152. self.radio.pwr.set_high().ok();
  153. self.radio.nrf24 = Some(nrf24);
  154. }
  155. }