1#![no_std]
10
11extern crate embedded_hal as hal;
12
13extern crate radio;
14use radio::Registers;
15
16use hal::blocking::{spi, delay};
17use hal::digital::{OutputPin};
18use hal::spi::{Mode, Phase, Polarity};
19
20pub mod device;
21pub use device::{TrxCmd, TrxStatus, CCAMode, defaults};
22pub mod regs;
23pub use regs::{Register};
24
25#[derive(Copy, Clone, Debug)]
27pub enum At86rf212Error<SPIError> {
28 SPI(SPIError),
30 InvalidPart(u8),
32 InvalidLength(usize),
34 MaxRetries,
36 PLLLock,
38 DigitalVoltage,
40 AnalogueVoltage,
42}
43
44impl <SPIError>From<SPIError> for At86rf212Error<SPIError> {
45 fn from(e: SPIError) -> At86rf212Error<SPIError> {
46 At86rf212Error::SPI(e)
47 }
48}
49
50pub const MODE: Mode = Mode {
52 polarity: Polarity::IdleLow,
53 phase: Phase::CaptureOnFirstTransition,
54};
55
56pub struct At86Rf212<SPI, OUTPUT, DELAY> {
58 spi: SPI,
59 reset: OUTPUT,
60 cs: OUTPUT,
61 sleep: OUTPUT,
62 delay: DELAY,
63 auto_crc: bool,
64}
65
66impl<E, SPI, OUTPUT, DELAY> At86Rf212<SPI, OUTPUT, DELAY>
67where
68 SPI: spi::Transfer<u8, Error = E> + spi::Write<u8, Error = E>,
69 OUTPUT: OutputPin,
70 DELAY: delay::DelayMs<u32>,
71{
72 pub fn new(spi: SPI, reset: OUTPUT, cs: OUTPUT, sleep: OUTPUT, delay: DELAY) -> Result<Self, At86rf212Error<E>> {
73 let mut at86rf212 = At86Rf212 { spi, reset, cs, sleep, delay, auto_crc: true };
74
75 at86rf212.sleep.set_low();
77
78 at86rf212.reset.set_low();
80 at86rf212.delay.delay_ms(10);
81 at86rf212.reset.set_high();
82
83 at86rf212.delay.delay_ms(20);
85
86 let who = at86rf212.reg_read(Register::PART_NUM)?;
88 if who != 0x07 {
89 return Err(At86rf212Error::InvalidPart(who));
90 }
91
92 at86rf212.set_state(TrxCmd::TRX_OFF)?;
94
95 let v = at86rf212.reg_read(Register::VREG_CTRL)?;
97 if v & regs::VREG_CTRL_DVDD_OK_MASK == 0 {
98 return Err(At86rf212Error::DigitalVoltage);
99 }
100
101 at86rf212.set_channel(defaults::CHANNEL)?;
103
104 at86rf212.set_cca_mode(defaults::CCA_MODE)?;
106
107 at86rf212.reg_write(Register::CSMA_BE, (defaults::MINBE << regs::CSMA_BE_MIN_SHIFT) | ((defaults::MAXBE as u8) << regs::CSMA_BE_MAX_SHIFT))?;
110
111 at86rf212.reg_update(Register::XAH_CTRL_0, regs::XAH_CTRL_MAX_CSMA_RETRIES_MASK, defaults::MAX_CSMA_BACKOFFS << regs::XAH_CTRL_MAX_CSMA_RETRIES_SHIFT)?;
113
114 at86rf212.reg_update(Register::XAH_CTRL_1, regs::XAH_CTRL_1_AACK_PROM_MODE_MASK, 1 << regs::XAH_CTRL_1_AACK_PROM_MODE_SHIFT)?;
116
117 at86rf212.reg_update(Register::TRX_CTRL_1, regs::TRX_CTRL1_TX_AUTO_CRC_ON_MASK, 1 << regs::TRX_CTRL1_TX_AUTO_CRC_ON_SHIFT)?;
119
120 at86rf212.reg_update(Register::TRX_CTRL_1, regs::TRX_CTRL1_IRQ_MASK_MODE_MASK, 1 << regs::TRX_CTRL1_IRQ_MASK_MODE_SHIFT)?;
122
123 at86rf212.reg_update(Register::TRX_CTRL_2, regs::TRX_CTRL2_RX_SAFE_MODE_MASK, 1 << regs::TRX_CTRL2_RX_SAFE_MODE_SHIFT)?;
125
126 Ok(at86rf212)
129 }
130
131 pub fn read_frame<'a>(&mut self, data: &'a mut [u8]) -> Result<&'a [u8], At86rf212Error<E>> {
133 let cmd: [u8; 1] = [device::FRAME_READ_FLAG as u8];
135 self.cs.set_low();
137 match self.spi.write(&cmd) {
139 Ok(_r) => (),
140 Err(e) => {
141 self.cs.set_high();
142 return Err(At86rf212Error::SPI(e));
143 }
144 };
145 let res = match self.spi.transfer(data) {
147 Ok(r) => r,
148 Err(e) => {
149 self.cs.set_high();
150 return Err(At86rf212Error::SPI(e));
151 }
152 };
153 self.cs.set_high();
155 Ok(res)
157 }
158
159 pub fn write_frame(&mut self, data: &[u8]) -> Result<(), At86rf212Error<E>> {
161 let mut cmd: [u8; 2] = [device::FRAME_WRITE_FLAG as u8, 0];
163 if self.auto_crc {
164 cmd[1] = (data.len() + device::LEN_FIELD_LEN + device::CRC_LEN) as u8;
165 } else {
166 cmd[1] = (data.len() + device::LEN_FIELD_LEN) as u8;
167 }
168 self.cs.set_low();
170 match self.spi.write(&cmd) {
172 Ok(_r) => (),
173 Err(e) => {
174 self.cs.set_high();
175 return Err(At86rf212Error::SPI(e));
176 }
177 };
178 match self.spi.write(&data) {
180 Ok(_r) => (),
181 Err(e) => {
182 self.cs.set_high();
183 return Err(At86rf212Error::SPI(e));
184 }
185 };
186 if self.auto_crc {
188 let crc = [0u8; device::CRC_LEN];
189 match self.spi.write(&crc) {
190 Ok(_r) => (),
191 Err(e) => {
192 self.cs.set_high();
193 return Err(At86rf212Error::SPI(e));
194 }
195 };
196 }
197 self.cs.set_high();
199
200 Ok(())
201 }
202
203 pub fn set_state(&mut self, state: device::TrxCmd) -> Result<(), At86rf212Error<E>> {
205 self.reg_update(Register::TRX_STATE, regs::TRX_STATE_TRX_CMD_MASK, state as u8)
206 }
207
208 pub fn set_state_blocking(&mut self, state: device::TrxCmd) -> Result<(), At86rf212Error<E>> {
209 self.reg_update(Register::TRX_STATE, regs::TRX_STATE_TRX_CMD_MASK, state as u8)?;
210
211 for _i in 0..defaults::MAX_SPI_RETRIES {
212 let v = self.reg_read(Register::TRX_STATE)?;
213 if (v & regs::TRX_STATUS_TRX_STATUS_MASK) != (TrxStatus::STATE_TRANSITION_IN_PROGRESS as u8) {
214 return Ok(());
215 }
216 self.delay.delay_ms(1);
217 }
218
219 Err(At86rf212Error::MaxRetries)
220 }
221
222 pub fn get_state(&mut self) -> Result<u8, At86rf212Error<E>> {
224 self.reg_read(Register::TRX_STATE).map(|v| v & regs::TRX_STATUS_TRX_STATUS_MASK)
225 }
226
227 pub fn set_channel(&mut self, channel: u8) -> Result<(), At86rf212Error<E>> {
229 self.reg_update(Register::PHY_CC_CCA, regs::PHY_CC_CCA_CHANNEL_MASK, channel << regs::PHY_CC_CCA_CHANNEL_SHIFT)
230 }
231
232 pub fn get_channel(&mut self) -> Result<u8, At86rf212Error<E>> {
234 self.reg_read(Register::PHY_CC_CCA).map(|v| (v & regs::PHY_CC_CCA_CHANNEL_MASK) >> regs::PHY_CC_CCA_CHANNEL_SHIFT)
235 }
236
237 pub fn set_irq_mask(&mut self, mask: u8) -> Result<(), At86rf212Error<E>> {
239 self.reg_write(Register::IRQ_MASK, mask)
240 }
241
242 pub fn get_irq_status(&mut self) -> Result<u8, At86rf212Error<E>> {
244 self.reg_read(Register::IRQ_STATUS)
245 }
246
247 pub fn set_cca_mode(&mut self, mode: CCAMode) -> Result<(), At86rf212Error<E>> {
249 self.reg_update(Register::PHY_CC_CCA, regs::PHY_CC_CCA_CCA_MODE_MASK, (mode as u8) << regs::PHY_CC_CCA_CCA_MODE_SHIFT)
250 }
251
252 pub fn get_cca_mode(&mut self) -> Result<u8, At86rf212Error<E>> {
254 self.reg_read(Register::PHY_CC_CCA).map(|v| (v & regs::PHY_CC_CCA_CCA_MODE_MASK) >> regs::PHY_CC_CCA_CCA_MODE_SHIFT)
255 }
256
257 pub fn set_short_address(&mut self, address: u16) -> Result<(), At86rf212Error<E>> {
259 self.reg_write(Register::SHORT_ADDR_0, (address & 0xFF) as u8)?;
260 self.reg_write(Register::SHORT_ADDR_1, (address >> 8) as u8)?;
261 Ok(())
262 }
263
264 pub fn set_pan_id(&mut self, pan_id: u16) -> Result<(), At86rf212Error<E>> {
266 self.reg_write(Register::PAN_ID_0, (pan_id & 0xFF) as u8)?;
267 self.reg_write(Register::PAN_ID_1, (pan_id >> 8) as u8)?;
268 Ok(())
269 }
270
271 pub fn set_power_raw(&mut self, power: u8) -> Result<(), At86rf212Error<E>> {
273 self.reg_update(Register::PHY_TX_PWR, regs::PHY_TX_PWR_TX_PWR_MASK, power << regs::PHY_TX_PWR_TX_PWR_SHIFT)?;
274 Ok(())
275 }
276
277
278 fn enable_pll(&mut self) -> Result<(), At86rf212Error<E>> {
279 self.set_state_blocking(TrxCmd::PLL_ON)?;
281
282 for _i in 0 .. defaults::MAX_SPI_RETRIES {
284 let v = self.get_irq_status()?;
285 if (v & regs::IRQ_STATUS_IRQ_0_PLL_LOCK_MASK) != 0 {
286 return Ok(())
287 }
288 }
289
290 Err(At86rf212Error::PLLLock)
291 }
292
293 fn check_tx_rx(&mut self) -> Result<bool, At86rf212Error<E>> {
294 let v = self.get_irq_status()?;
295 if (v & regs::IRQ_STATUS_IRQ_3_TRX_END_MASK) != 0 {
296 Ok(true)
297 } else {
298 Ok(false)
299 }
300 }
301
302 fn get_rx<'a>(&mut self, data: &'a mut [u8]) -> Result<&'a [u8], At86rf212Error<E>>{
303 let mut buf = [0u8; 1];
305 let len = self.read_frame(&mut buf)?[0] as usize;
306 if len > device::MAX_LENGTH {
308 return Err(At86rf212Error::InvalidLength(len));
309 }
310 if (len + device::LEN_FIELD_LEN + device::FRAME_RX_OVERHEAD) > data.len() {
312 return Err(At86rf212Error::InvalidLength(len));
313 }
314 self.read_frame(data)
316 }
317
318}
319
320impl<E, SPI, OUTPUT, DELAY> radio::Registers for At86Rf212<SPI, OUTPUT, DELAY>
321where
322 SPI: spi::Transfer<u8, Error = E> + spi::Write<u8, Error = E>,
323 OUTPUT: OutputPin,
324 DELAY: delay::DelayMs<u32>,
325{
326 type Error = At86rf212Error<E>;
327 type Register = Register;
328
329 fn reg_read<'a>(&mut self, reg: Self::Register) -> Result<u8, Self::Error>{
330 let mut buf: [u8; 2] = [device::REG_READ_FLAG as u8 | reg as u8, 0];
332 self.cs.set_low();
334 let res = self.spi.transfer(&mut buf);
336 self.cs.set_high();
338 match res {
340 Ok(v) => Ok(v[1]),
341 Err(e) => Err(At86rf212Error::SPI(e)),
342 }
343 }
344
345 fn reg_write(&mut self, reg: Self::Register, value: u8) -> Result<(), Self::Error>{
346 let buf: [u8; 2] = [device::REG_WRITE_FLAG as u8 | reg as u8, value];
348 self.cs.set_low();
350 let res = self.spi.write(&buf);
352 self.cs.set_high();
354 match res {
356 Ok(_) => Ok(()),
357 Err(e) => Err(At86rf212Error::SPI(e)),
358 }
359 }
360
361 fn reg_update(&mut self, reg: Self::Register, mask: u8, value: u8) -> Result<(), Self::Error>{
362 let mut data = self.reg_read(reg.clone())?;
363 data &= !mask;
364 data |= mask & value;
365 self.reg_write(reg, data)?;
366 Ok(())
367 }
368
369}
370
371impl<E, SPI, OUTPUT, DELAY> radio::Transmit for At86Rf212<SPI, OUTPUT, DELAY>
372where
373 SPI: spi::Transfer<u8, Error = E> + spi::Write<u8, Error = E>,
374 OUTPUT: OutputPin,
375 DELAY: delay::DelayMs<u32>,
376{
377 type Error = At86rf212Error<E>;
378
379 fn start_transmit(&mut self, channel: u16, data: &[u8]) -> Result<(), Self::Error>{
380 self.set_state_blocking(TrxCmd::TRX_OFF)?;
382 self.get_irq_status()?;
384 self.set_channel(channel as u8)?;
386 self.enable_pll()?;
388 self.write_frame(data)?;
390 self.set_state_blocking(TrxCmd::TX_START)?;
392
393 Ok(())
394 }
395
396 fn check_transmit(&mut self) -> Result<bool, Self::Error>{
397 self.check_tx_rx()
400 }
401}
402
403impl<E, SPI, OUTPUT, DELAY> radio::Receive for At86Rf212<SPI, OUTPUT, DELAY>
404where
405 SPI: spi::Transfer<u8, Error = E> + spi::Write<u8, Error = E>,
406 OUTPUT: OutputPin,
407 DELAY: delay::DelayMs<u32>,
408{
409 type Error = At86rf212Error<E>;
410 type Info = ();
411
412 fn start_receive(&mut self, channel: u16) -> Result<(), Self::Error> {
413 self.set_state_blocking(TrxCmd::TRX_OFF)?;
415
416 self.set_channel(channel as u8)?;
418
419 self.get_irq_status()?;
421
422 self.enable_pll()?;
424
425 self.set_state_blocking(TrxCmd::RX_ON)?;
427
428 Ok(())
429 }
430
431 fn get_received<'a>(&mut self, buff: &'a mut [u8]) -> Result<Option<(&'a[u8], Self::Info)>, Self::Error> {
432 if !self.check_tx_rx()? {
436 return Ok(None);
437 }
438 let data = self.get_rx(buff)?;
440
441 Ok(Some((data, ())))
444 }
445}