| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- use core::convert::TryInto;
-
- use embedded_hal::blocking::delay::DelayMs;
- use embedded_hal::digital::v2::OutputPin;
- use embedded_nrf24l01::{Configuration, CrcMode, DataRate, RxMode, StandbyMode, NRF24L01};
- use mkl25z4_hal::time::CopyableMonoTimer;
- use mkl25z4_hal::NoError;
- use protocol::{Packet, Report, Value};
-
- use super::pins::{RadioCe, RadioCs, RadioIrq, RadioPins, RadioPwr, RadioSpi};
- use super::sensors::BME280Data;
-
- const DEVICE_ID: u8 = 0x20;
- const KEY: [u8; 16] = include!("../../../common/display_key.txt");
-
- pub struct Radio {
- nrf24: Option<NRF24L01<NoError, RadioCe, RadioCs, RadioSpi>>,
- pwr: RadioPwr,
- irq: RadioIrq,
- salt: Option<u64>,
- time: CopyableMonoTimer,
- }
-
- impl Radio {
- pub fn init(mut pins: RadioPins, time: CopyableMonoTimer) -> Radio {
- pins.pwr.set_low().ok();
- let nrf24 = NRF24L01::new(pins.ce, pins.cs, pins.spi).unwrap();
- let nrf24 = nrf24.power_down().unwrap();
- pins.pwr.set_high().ok();
- Radio {
- nrf24: Some(nrf24),
- pwr: pins.pwr,
- irq: pins.irq,
- salt: None,
- time,
- }
- }
-
- pub fn enable<'a>(&'a mut self) -> EnabledRadio<'a> {
- // Enable supply voltage.
- self.pwr.set_low().ok();
- self.time.delay_ms(10u8);
-
- // Configure the device.
- let nrf24 = self.nrf24.take().unwrap();
- let mut nrf24 = StandbyMode::power_up(nrf24).unwrap();
- self.time.delay_ms(2u8);
- nrf24.set_frequency(0x32).unwrap();
- nrf24.set_rf(DataRate::R2Mbps, 3).unwrap();
- nrf24.set_crc(Some(CrcMode::OneByte)).unwrap();
- nrf24.set_auto_retransmit(250, 1).unwrap();
- nrf24.set_auto_ack(&[true; 6]).unwrap();
- nrf24
- .set_pipes_rx_enable(&[true, true, false, false, false, false])
- .unwrap();
- nrf24.set_tx_addr(&[0xB3, 0xB3, 0xB3, 0xB3, 0x00]).unwrap();
- nrf24
- .set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
- .unwrap();
- nrf24
- .set_rx_addr(1, &[0xB3, 0xB3, 0xB3, 0xB3, 0x20])
- .unwrap();
- nrf24.flush_rx().unwrap();
- nrf24.flush_tx().unwrap();
- nrf24.set_pipes_rx_lengths(&[Some(32); 6]).unwrap();
-
- EnabledRadio {
- radio: self,
- nrf24: Some(nrf24),
- }
- }
- }
-
- pub struct EnabledRadio<'a> {
- radio: &'a mut Radio,
- nrf24: Option<StandbyMode<NRF24L01<NoError, RadioCe, RadioCs, RadioSpi>>>,
- }
-
- impl<'a> EnabledRadio<'a> {
- // TODO: Use generic "SensorValues" instead of BME280Data, which includes ambient light
- // readings
- pub fn send_sensor_values(&mut self, values: BME280Data) -> bool {
- if self.radio.salt.is_none() {
- if !self.fetch_salt() {
- return false;
- }
- }
-
- let mut tx = self.nrf24.take().unwrap().tx().unwrap();
- while !tx.can_send().unwrap() {}
- let mut payload = [0u8; 32];
- let mut report = Report {
- count: 3,
- values: [Value::Invalid; 8],
- };
- report.values[0] = Value::Temperature(values.temperature as i16);
- report.values[1] = Value::Pressure(values.pressure);
- report.values[2] = Value::Humidity(values.humidity as u16);
- let packet = Packet::Report(report);
- packet.encode_and_encrypt(&KEY, self.radio.salt.unwrap(), &mut payload);
- tx.send(&payload).unwrap();
- // TODO: Check whether the packet arrived.
-
- self.nrf24 = Some(tx.standby().unwrap());
- true
- }
-
- fn fetch_salt(&mut self) -> bool {
- // Request a device ID.
- let mut tx = self.nrf24.take().unwrap().tx().unwrap();
- while !tx.can_send().unwrap() {}
- let mut payload = [0u8; 32];
- let packet = Packet::GetSalt;
- packet.encode_and_encrypt(&KEY, DEVICE_ID as u64, &mut payload);
- tx.send(&payload).unwrap();
- // TODO: Check whether the packet arrived.
-
- // Wait for the initial salt.
- let mut salt_received = false;
- let mut rx = tx.standby().unwrap().rx().unwrap();
- loop {
- let packet = match self.receive_packet(&mut rx) {
- None => break,
- Some(p) => p,
- };
-
- match packet {
- Packet::Salt(salt) => {
- self.radio.salt = Some((salt & 0x7fffffffffffff00) | DEVICE_ID as u64);
- salt_received = true;
- break;
- }
- _ => continue,
- }
- }
-
- self.nrf24 = Some(rx.standby());
- salt_received
- }
-
- fn receive_packet(
- &mut self,
- rx: &mut RxMode<NRF24L01<NoError, RadioCe, RadioCs, RadioSpi>>,
- ) -> Option<Packet> {
- // TODO: Timeout.
- loop {
- if let Some(_pipe) = rx.can_read().unwrap() {
- // Receive a packet.
- // TODO: Check pipe?
- let payload = rx.read().unwrap();
- if payload.len() != 32 {
- continue;
- }
- let mut payload: [u8; 32] = payload[0..32].try_into().unwrap();
-
- let packet = match Packet::decrypt_and_decode(&KEY, &mut payload) {
- Ok(p) => p,
- Err(_) => continue,
- };
-
- return Some(packet);
- }
- }
- }
- }
-
- impl<'a> Drop for EnabledRadio<'a> {
- fn drop(&mut self) {
- let nrf24 = self.nrf24.take().unwrap();
- // Disable the chip and remove the supply voltage.
- let nrf24 = nrf24.power_down().unwrap();
- self.radio.pwr.set_high().ok();
- self.radio.nrf24 = Some(nrf24);
- }
- }
|