COSA
An Object-Oriented Platform for Arduino Programming
RFM69.hh
Go to the documentation of this file.
1 
21 #ifndef COSA_RFM69_HH
22 #define COSA_RFM69_HH
23 
24 #include "Cosa/SPI.hh"
25 #include "Cosa/OutputPin.hh"
27 #include "Cosa/Wireless.hh"
28 #if !defined(BOARD_ATTINYX5)
29 
56 class RFM69 : private SPI::Driver, public Wireless::Driver {
57 public:
61  static const size_t HEADER_MAX = 3;
62 
67  static const size_t PAYLOAD_MAX = 66 - HEADER_MAX;
68 
79 #if defined(BOARD_ATTINYX4)
80  RFM69(uint16_t net, uint8_t dev,
83 #elif defined(BOARD_ATMEGA2560)
84  RFM69(uint16_t net, uint8_t dev,
87 #else
88  RFM69(uint16_t net, uint8_t dev,
91 #endif
92 
101  virtual bool begin(const void* config = NULL);
102 
109  virtual bool end();
110 
122  virtual int send(uint8_t dest, uint8_t port, const iovec_t* vec);
123 
136  virtual int send(uint8_t dest, uint8_t port, const void* buf, size_t len);
137 
153  virtual int recv(uint8_t& src, uint8_t& port, void* buf, size_t len,
154  uint32_t ms = 0L);
155 
160  virtual void powerdown();
161 
166  virtual void wakeup_on_radio();
167 
173  virtual void output_power_level(int8_t dBm);
174 
180  virtual int input_power_level();
181 
187  int temperature();
188 
193  void recalibrate();
194 
195 private:
199  enum Reg {
200  FIFO = 0x00,
201  OP_MODE = 0x01,
202  DATA_MODUL = 0x02,
203  BITRATE = 0x03,
204  BITRATE_MSB = 0x03,
205  BITRATE_LSB = 0x04,
206  FDEV = 0x05,
207  FDEV_MSB = 0x05,
208  FDEV_LSB = 0x06,
209  FRF = 0x07,
210  FRF_MSB = 0x07,
211  FRF_MID = 0x08,
212  FRF_LSB = 0x09,
213  OSC1 = 0x0A,
214  AFC_CTRL = 0x0B,
215  LISTEN1 = 0x0D,
216  LISTEN2 = 0x0E,
217  LISTEN3 = 0x0F,
218  VERSION = 0x10,
219  PA_LEVEL = 0x11,
220  PA_RAMP = 0x12,
221  OCP = 0x13,
222  LNA = 0x18,
223  RX_BW = 0x19,
224  AFC_BW = 0x1A,
225  OOK_PEAK = 0x1B,
226  OOK_AVG = 0x1C,
227  OOK_FIXED = 0x1D,
228  AFC_FEI = 0x1E,
229  AFC = 0x1F,
230  AFC_MSB = 0x1F,
231  AFC_LSB = 0x20,
232  FEI = 0x21,
233  FEI_MSB = 0x21,
234  FEI_LSB = 0x22,
235  RSSI_CONFIG = 0x23,
236  RSSI_VALUE = 0x24,
237  DIO_MAPPING1 = 0x25,
238  DIO_MAPPING2 = 0x26,
239  IRQ_FLAGS1 = 0x27,
240  IRQ_FLAGS2 = 0x28,
241  RSSI_THRESH = 0x29,
242  RX_TIMEOUT1 = 0x2A,
243  RX_TIMEOUT2 = 0x2B,
244  PREAMBLE = 0x2C,
245  PREAMBLE_MSB = 0x2C,
246  PREAMBLE_LSB = 0x2D,
247  SYNC_CONFIG = 0x2E,
248  SYNC_VALUE = 0x2F,
249  SYNC_VALUE1 = 0x2F,
250  SYNC_VALUE2 = 0x30,
251  SYNC_VALUE3 = 0x31,
252  SYNC_VALUE4 = 0x32,
253  SYNC_VALUE5 = 0x33,
254  SYNC_VALUE6 = 0x34,
255  SYNC_VALUE7 = 0x35,
256  SYNC_VALUE8 = 0x36,
257  PACKET_CONFIG1 = 0x37,
258  PAYLOAD_LENGTH = 0x38,
259  NODE_ADDR = 0x39,
260  BROADCAST_ADDR = 0x3A,
261  AUTO_MODES = 0x3B,
262  FIFO_THRESHOLD = 0x3C,
263  PACKET_CONFIG2 = 0x3D,
264  CYPHER_KEY = 0x3E,
265  TEMP1 = 0x4E,
266  TEMP2 = 0x4F,
267  TEST_LNA = 0x58,
268  TEST_PA1 = 0x5A,
269  TEST_PA2 = 0x5C,
270  TEST_DAGC = 0x6F,
271  TEST_AFC = 0x71,
272  } __attribute__((packed));
273 
278  enum {
279  REG_READ = 0x00,
280  REG_WRITE = 0x80,
281  REG_MASK = 0x7F
282  } __attribute__((packed));
283 
289  uint8_t read(Reg reg)
290  {
291  spi.acquire(this);
292  spi.begin();
293  spi.transfer(REG_READ | reg);
294  uint8_t res = spi.transfer(0);
295  spi.end();
296  spi.release();
297  return (res);
298  }
299 
306  void read(Reg reg, void* buf, size_t count)
307  {
308  spi.acquire(this);
309  spi.begin();
310  spi.transfer(REG_READ | reg);
311  spi.read(buf, count);
312  spi.end();
313  spi.release();
314  }
315 
321  void write(Reg reg, uint8_t value)
322  {
323  spi.acquire(this);
324  spi.begin();
325  spi.transfer(REG_WRITE | reg);
326  spi.transfer(value);
327  spi.end();
328  spi.release();
329  }
330 
337  void write(Reg reg, const void* buf, size_t count)
338  {
339  spi.acquire(this);
340  spi.begin();
341  spi.transfer(REG_WRITE | reg);
342  spi.write(buf, count);
343  spi.end();
344  spi.release();
345  }
346 
353  void write_P(Reg reg, const uint8_t* buf, size_t count)
354  {
355  spi.acquire(this);
356  spi.begin();
357  spi.transfer(REG_WRITE | reg);
358  spi.write_P(buf, count);
359  spi.end();
360  spi.release();
361  }
362 
366  enum {
367  SEQUENCER_OFF = 0x80,
368  SEQUENCER_ON = 0x00,
369  LISTEN_OFF = 0x00,
370  LISTEN_ON = 0x40,
371  LISTEN_ABORT = 0x20,
372  MODE_MASK = 0x1C
373  } __attribute__((packed));
374 
378  enum {
379  PACKET_MODE = 0x00,
380  CONTINUOUS_MODE_WITH_BIT_SYNC = 0x40,
381  CONTINUOUS_MODE_WITHOUT_BIT_SYNC = 0x60,
382  FSK_MODULATION = 0x00,
383  OOK_MODULATION = 0x80,
384  FSK_NO_SHAPING = 0x00,
385  FSK_BT_1_0 = 0x01,
386  FSK_BT_0_5 = 0x02,
387  FSK_BT_0_3 = 0x03,
388  OOK_NO_SHAPING = 0x00,
389  OOK_BS_1 = 0x01,
390  OOK_BS_2 = 0x02,
391  } __attribute__((packed));
392 
396  enum {
397  RC_CAL_START = 0x80,
398  RC_CAL_DONE = 0x40
399  } __attribute__((packed));
400 
404  enum {
405  AFC_LOW_BETA_OFF = 0x00,
406  AFC_LOW_BETA_ON = 0x20,
407  } __attribute__((packed));
408 
412  enum {
413  RESOL_IDLE_64_US = 0x40,
414  RESOL_IDLE_410_US = 0x80,
415  RESOL_IDLE_262000_US = 0xC0,
416  RESOL_RX_64_US = 0x10,
417  RESOL_RX_410_US = 0x20,
418  RESOL_RX_262000_US = 0x30,
419  CRITERIA_RSSI_THRESHOLD = 0x00,
420  CRITERIA_RSSI_SYNC_THRESHOLD = 0x08,
421  END_MODE0 = 0x00,
422  END_MODE1 = 0x02,
423  END_MODE2 = 0x04
424  } __attribute__((packed));
425 
429  enum {
430  PA0_ON = 0x80,
431  PA0_OFF = 0x00,
432  PA1_ON = 0x40,
433  PA1_OFF = 0x00,
434  PA2_ON = 0x20,
435  PA2_OFF = 0x00,
436  OUTPUT_POWER = 0,
437  OUTPUT_POWER_MASK = 0x1F,
438  FULL_OUTPUT_POWER = 0x1F
439  } __attribute__((packed));
440 
444  enum {
445  OCP_ON = 0x10,
446  OCP_OFF = 0x00,
447  OCP_TRIM = 0,
448  OCP_TRIM_MASK = 0x0F
449  } __attribute__((packed));
450 
454  enum {
455  ZIN_50_OHM = 0x00,
456  ZIN_200_OHM = 0x80,
457  CURRENT_GAIN = 3,
458  CURRENT_GAIN_MASK = 0x07,
459  SELECT_GAIN = 0,
460  SELECT_GAIN_MASK = 0x07
461  } __attribute__((packed));
462 
466  enum {
467  DCC_FREQ = 5,
468  DCC_FREQ_MASK = 0x07,
469  BW_MANT_16 = 0x00,
470  BW_MANT_20 = 0x08,
471  BW_MANT_24 = 0x10,
472  BW_EXP = 0,
473  BW_EXP_MASK = 0x07,
474  } __attribute__((packed));
475 
479  enum {
480  OOK_THRESHOLD_FIXED = 0x00,
481  OOK_THRESHOLD_PEAK = 0x40,
482  OOK_THRESHOLD_AVG = 0x80,
483  OOK_PEAK_THRESHOLD_STEP = 3,
484  OOK_PEAK_THRESHOLD_STEP_MASK = 0x7,
485  OOK_PEAK_THRESHOLD_DECR = 0,
486  OOK_PEAK_THRESHOLD_DECR_MASK = 0x7
487  } __attribute__((packed));
488 
492  enum {
493  OOK_AVG_THRESHOLD_FILTER_32_PI = 0x00,
494  OOK_AVG_THRESHOLD_FILTER_8_PI = 0x40,
495  OOK_AVG_THRESHOLD_FILTER_4_PI = 0x80,
496  OOK_AVG_THRESHOLD_FILTER_2_PI = 0xC0
497  } __attribute__((packed));
498 
502  enum {
503  FEI_DONE = 0x40,
504  FEI_START = 0x20,
505  AFC_DONE = 0x10,
506  AFC_AUTO_CLEAR_ON = 0x08,
507  AFC_AUTO_ON = 0x04,
508  AFC_CLEAR = 0x02,
509  AFC_START = 0x01
510  } __attribute__((packed));
511 
515  enum {
516  RSSI_DONE = 0x02,
517  RSSI_START = 0x01
518  } __attribute__((packed));
519 
523  enum {
524  DIO0_MAPPING1 = 6,
525  DIO1_MAPPING1 = 4,
526  DIO2_MAPPING1 = 2,
527  DIO3_MAPPING1 = 0,
528  DIO4_MAPPING2 = 6,
529  DIO5_MAPPING2 = 4,
530  DIO_MAPPING_MASK = 0x3,
531  CLK_OUT = 0,
532  CLK_OUT_MASK = 0x7
533  } __attribute__((packed));
534 
538  enum {
539  MODE_READY = 0x80,
540  RX_READY = 0x40,
541  TX_READY = 0x20,
542  PLL_LOCKED = 0x10,
543  RSSI_READY = 0x08,
544  TIMEOUT = 0x04,
545  AUTO_MODE = 0x02,
546  SYNC_ADDR_MATCH = 0x01,
547  } __attribute__((packed));
548 
552  enum {
553  FIFO_FULL = 0x80,
554  FIFO_NOT_EMPTY = 0x40,
555  FIFO_LEVEL = 0x20,
556  FIFO_OVERRUN = 0x10,
557  PACKET_SENT = 0x08,
558  PAYLOAD_READY = 0x04,
559  CRC_OK = 0x02,
560  } __attribute__((packed));
561 
565  enum {
566  SYNC_ON = 0x80,
567  SYNC_OFF = 0x00,
568  FIFO_FILL_AUTO = 0x00,
569  FIFO_FILL_MANUAL = 0x40,
570  SYNC_SIZE = 3,
571  SYNC_SIZE_MASK = 0x7,
572  SYNC_TOL = 0,
573  SYNC_TOL_MASK = 0x7
574  } __attribute__((packed));
575 
579  enum {
580  FIXED_LENGTH = 0x00,
581  VARIABLE_LENGTH = 0x80,
582  DC_FREE_OFF = 0x00,
583  MANCHESTER = 0x20,
584  WHITENING = 0x40,
585  CRC_OFF = 0x00,
586  CRC_ON = 0x10,
587  CRC_AUTO_CLEAR_OFF = 0x08,
588  CRC_AUTO_CLEAR_ON = 0x00,
589  ADDR_FILTER_OFF = 0x00,
590  ADDR_FILTER_ON = 0x04,
591  ADDR_FILTER_NODE = 0x02
592  } __attribute__((packed));
593 
597  enum {
598  INTER_PACKET_RX_DELAY = 4,
599  INTER_PACKET_RX_DELAY_MASK = 0xF,
600  RESTART_RX = 0x04,
601  AUTO_RX_RESTART_ON = 0x02,
602  AUTO_RX_RESTART_OFF = 0x00,
603  AES_ON = 0x01,
604  AES_OFF = 0x00
605  } __attribute__((packed));
606 
610  enum {
611  TX_START_THRESHOLD = 0x00,
612  TX_START_NOT_EMPTY = 0x80,
613  FIFO_THRESHOLD_MASK = 0x7F
614  } __attribute__((packed));
615 
619  enum {
620  TEMP_MEAS_START = 0x08,
621  TEMP_MEAS_RUNNING = 0x04
622  } __attribute__((packed));
623 
627  enum {
628  TEST_LNA_NORMAL_SENSITIVITY = 0x1B,
629  TEST_LNA_HIGH_SENSITIVITY = 0x2D,
630  TEST_PA1_NORMAL_MODE = 0x55,
631  TEST_PA1_BOOST_20_DB_MODE = 0x5D,
632  TEST_PA2_NORMAL_MODE = 0x70,
633  TEST_PA2_BOOST_20_DB_MODE = 0x7C,
634  TEST_DAGC_NORMAL_MODE = 0x00,
635  TEST_DAGC_IMPROVED_MARGIN_AFC_LOW_BETA_ON = 0x20,
636  TEST_DAGC_IMPROVED_MARGIN_AFC_LOG_BETA_OFF = 0x30
637  } __attribute__((packed));
638 
642  enum Mode {
643  SLEEP_MODE = 0x00,
644  STANDBY_MODE = 0x04,
645  FREQUENCY_SYNTHESIZER_MODE = 0x08,
646  TRANSMITTER_MODE = 0x0C,
647  RECEIVER_MODE = 0x10
648  } __attribute__((packed));
649 
654  void set(Mode mode);
655 
660  class IRQPin : public ExternalInterrupt {
661  public:
669  IRQPin(Board::ExternalInterruptPin pin, InterruptMode mode, RFM69* rf) :
670  ExternalInterrupt(pin, mode),
671  m_rf(rf)
672  {}
673 
680  virtual void on_interrupt(uint16_t arg = 0);
681 
682  friend class RFM69;
683  private:
684  RFM69* m_rf;
685  };
686 
688  static const uint8_t config[] __PROGMEM;
689 
690  IRQPin m_irq;
691  volatile bool m_done;
692  Mode m_opmode;
693 };
694 #endif
695 #endif
Definition: RFM69.hh:56
uint8_t transfer(uint8_t data)
Definition: SOFT_SPI.cpp:87
#define __PROGMEM
Definition: Types.h:183
virtual bool end()
Definition: RFM69.cpp:172
void acquire(Driver *dev)
Definition: SOFT_SPI.cpp:43
#define NULL
Definition: Types.h:101
int temperature()
Definition: RFM69.cpp:287
static const size_t PAYLOAD_MAX
Definition: RFM69.hh:67
void read(void *buf, size_t count)
Definition: SPI.hh:308
Definition: Types.h:391
void write(const void *buf, size_t count)
Definition: SPI.hh:321
ExternalInterruptPin
Definition: ATmega1284P.hh:190
virtual void output_power_level(int8_t dBm)
Definition: RFM69.cpp:271
virtual int send(uint8_t dest, uint8_t port, const iovec_t *vec)
Definition: RFM69.cpp:180
RFM69(uint16_t net, uint8_t dev, Board::DigitalPin csn=Board::D10, Board::ExternalInterruptPin irq=Board::EXT0)
Definition: RFM69.cpp:110
void begin()
Definition: SPI.hh:216
void end()
Definition: SPI.hh:226
virtual bool begin(const void *config=NULL)
Definition: RFM69.cpp:142
virtual void wakeup_on_radio()
Definition: RFM69.cpp:264
static const size_t HEADER_MAX
Definition: RFM69.hh:61
void recalibrate()
Definition: RFM69.cpp:295
virtual int input_power_level()
Definition: RFM69.cpp:281
void write_P(const uint8_t *buf, size_t count)
Definition: SPI.hh:334
SPI spi
Definition: SPI.cpp:29
virtual int recv(uint8_t &src, uint8_t &port, void *buf, size_t len, uint32_t ms=0L)
Definition: RFM69.cpp:223
void release()
Definition: SOFT_SPI.cpp:64
virtual void powerdown()
Definition: RFM69.cpp:258