COSA
An Object-Oriented Platform for Arduino Programming
CC1101.cpp
Go to the documentation of this file.
1 
21 #include "CC1101.hh"
22 
23 #if !defined(BOARD_ATTINYX5)
24 
25 #include "Cosa/Power.hh"
26 #include "Cosa/RTT.hh"
27 
28 #if defined(BOARD_ATTINY)
29 #define PIN PINA
30 #else
31 #define PIN PINB
32 #endif
33 
47 const uint8_t CC1101::config[CC1101::CONFIG_MAX] __PROGMEM = {
48  0x47, // GDO2 Output Pin Configuration
49  0x2E, // GDO1 Output Pin Configuration
50  0x2E, // GDO0 Output Pin Configuration
51  0x07, // RX FIFO and TX FIFO Thresholds
52  0xC0, // Synchronization word, high byte
53  0x5A, // Synchronization word, low byte
54  0x3D, // Packet Length, 61 bytes
55  0x06, // Packet Automation Control
56  0x45, // Packet Automation Control
57  0xFF, // Device Address
58  0x00, // Channel Number
59  0x08, // Frequency Synthesizer Control
60  0x00, // Frequency Synthesizer Control
61  0x10, // Frequency Control Word, High Byte
62  0xA7, // Frequency Control Word, Middle Byte
63  0x62, // Frequency Control Word, Low Byte
64  0xCA, // Modem Configuration
65  0x83, // Modem Configuration
66  0x93, // Modem Configuration
67  0x22, // Modem Configuration
68  0xF8, // Modem Configuration
69  0x35, // Modem Deviation Setting
70  0x07, // Main Radio Control State Machine Configuration
71  0x30, // Main Radio Control State Machine Configuration
72  0x18, // Main Radio Control State Machine Configuration
73  0x16, // Frequency Offset Compensation Configuration
74  0x6C, // Bit Synchronization Configuration
75  0x43, // AGC Control
76  0x40, // AGC Control
77  0x91, // AGC Control
78  0x87, // High Byte Event0 Timeout
79  0x6B, // Low Byte Event0 Timeout
80  0xFB, // Wake On Radio Control
81  0x56, // Front End RX Configuration
82  0x10, // Front End TX Configuration
83  0xE9, // Frequency Synthesizer Calibration
84  0x2A, // Frequency Synthesizer Calibration
85  0x00, // Frequency Synthesizer Calibration
86  0x1F, // Frequency Synthesizer Calibration
87  0x41, // RC Oscillator Configuration
88  0x00 // RC Oscillator Configuration
89 };
90 
91 void
93 {
94  UNUSED(arg);
95  if (m_rf == 0) return;
96  m_rf->m_avail = true;
97 }
98 
99 CC1101::CC1101(uint16_t net, uint8_t dev,
100  Board::DigitalPin csn,
102  SPI::Driver(csn, SPI::ACTIVE_LOW, SPI::DIV4_CLOCK, 0, SPI::MSB_ORDER, &m_irq),
103  Wireless::Driver(net, dev),
104  m_irq(irq, ExternalInterrupt::ON_FALLING_MODE, this),
105  m_status(0)
106 {
107 }
108 
109 void
111 {
112  spi.acquire(this);
113  spi.begin();
114  loop_until_bit_is_clear(PIN, Board::MISO);
115  m_status = spi.transfer(header_t(cmd, 0, 0));
116  spi.end();
117  spi.release();
118 }
119 
120 void
122 {
123  while (read_status().mode != mode) DELAY(100);
124 }
125 
126 bool
127 CC1101::begin(const void* config)
128 {
129  // Reset the device
130  m_cs.pulse(30);
131  DELAY(30);
132  strobe(SRES);
133  DELAY(300);
134 
135  // Upload the configuration. Check for default configuration
136  spi.acquire(this);
137  spi.begin();
138  loop_until_bit_is_clear(PIN, Board::MISO);
139  write_P(IOCFG2,
140  config ? (const uint8_t*) config : CC1101::config,
141  CONFIG_MAX);
142  spi.end();
143 
144  // Adjust configuration with instance specific state
145  uint16_t sync = hton(m_addr.network);
146  spi.begin();
147  loop_until_bit_is_clear(PIN, Board::MISO);
148  write(PATABLE, 0x60);
151  write(SYNC1, &sync, sizeof(sync));
152  spi.end();
153  spi.release();
154 
155  // Initiate device driver state and enable interrupt handler
156  strobe(SCAL);
157  m_avail = false;
158  spi.attach(this);
159  m_irq.enable();
160  return (true);
161 }
162 
163 bool
165 {
166  // Fix: Should be state-based disable/enable
167  m_irq.disable();
168  powerdown();
169  return (true);
170 }
171 
172 int
173 CC1101::send(uint8_t dest, uint8_t port, const iovec_t* vec)
174 {
175  // Sanity check the payload size
176  if (UNLIKELY(vec == NULL)) return (EINVAL);
177  size_t len = iovec_size(vec);
178  if (UNLIKELY(len > PAYLOAD_MAX)) return (EMSGSIZE);
179 
180  // Write frame length and header(dest, src, port) and payload buffers
181  spi.acquire(this);
182  spi.begin();
183  loop_until_bit_is_clear(PIN, Board::MISO);
184  m_status = spi.transfer(header_t(TXFIFO, 1, 0));
185  spi.transfer(len + 3);
186  spi.transfer(dest);
188  spi.transfer(port);
189  spi.write(vec);
190  spi.end();
191  spi.release();
192 
193  // Trigger transmission and wait for completion
194  strobe(STX);
195  await(IDLE_MODE);
196 
197  return (len);
198 }
199 
200 int
201 CC1101::send(uint8_t dest, uint8_t port, const void* buf, size_t len)
202 {
203  iovec_t vec[2];
204  iovec_t* vp = vec;
205  iovec_arg(vp, buf, len);
206  iovec_end(vp);
207  return (send(dest, port, vec));
208 }
209 
210 int
211 CC1101::recv(uint8_t& src, uint8_t& port, void* buf, size_t len, uint32_t ms)
212 {
213  uint32_t start = RTT::millis();
214  uint8_t size;
215 
216  // Put in receive mode and wait for incoming message
217  strobe(SFRX);
218  strobe(SRX);
219  m_avail = false;
220  do {
221  while (!m_avail && ((ms == 0) || (RTT::since(start) < ms))) yield();
222  if (!m_avail) {
223  strobe(SIDLE);
224  return (ETIME);
225  }
226  // Check the received frame size
227  spi.acquire(this);
228  spi.begin();
229  loop_until_bit_is_clear(PIN, Board::MISO);
230  size = read(RXBYTES);
231  spi.end();
232  spi.release();
233  } while ((size & BYTES_MASK) == 0);
234 
235  // Put in idle mode and read the payload
236  strobe(SIDLE);
237 
238  // Read the payload size and check against buffer length
239  spi.acquire(this);
240  spi.begin();
241  loop_until_bit_is_clear(PIN, Board::MISO);
242  m_status = spi.transfer(header_t(RXFIFO, 1, 1));
243  size = spi.transfer(0) - 3;
244  if (size > len) {
245  spi.end();
246  spi.release();
247  strobe(SFRX);
248  return (EMSGSIZE);
249  }
250 
251  // Read the frame header(dest, src, port), payload and link quality status
252  m_dest = spi.transfer(0);
253  src = spi.transfer(0);
254  port = spi.transfer(0);
255  spi.read(buf, size);
256  spi.read(&m_recv_status, sizeof(m_recv_status));
257  spi.end();
258  spi.release();
259 
260  // Fix: Add address checking for robustness
261  return (size);
262 }
263 
264 void
266 {
267  await(IDLE_MODE);
268  strobe(SPWD);
269 }
270 
271 void
273 {
274  await(IDLE_MODE);
275  strobe(SWOR);
276 }
277 
278 void
280 {
281  uint8_t pa = 0xC0;
282  if (dBm < -20) pa = 0x12;
283  else if (dBm < -15) pa = 0x0E;
284  else if (dBm < -10) pa = 0x1D;
285  else if (dBm < 0) pa = 0x34;
286  else if (dBm < 5) pa = 0x60;
287  else if (dBm < 7) pa = 0x84;
288  else if (dBm < 10) pa = 0xC4;
289  spi.acquire(this);
290  spi.begin();
291  loop_until_bit_is_clear(PIN, Board::MISO);
292  write(PATABLE, pa);
293  spi.end();
294  spi.release();
295 }
296 
297 int
299 {
300  int rssi = m_recv_status.rssi;
301  return (((rssi < 128) ? rssi : rssi - 256) / 2 - 74);
302 }
303 #endif
Exit RX/TX.
Definition: CC1101.hh:520
addr_t m_addr
Current network and device address.
Definition: Wireless.hh:299
Receiver FIFO.
Definition: CC1101.hh:414
#define PIN
Definition: CC1101.cpp:31
#define EINVAL
Definition: Errno.h:49
uint8_t transfer(uint8_t data)
Definition: SOFT_SPI.cpp:87
Command
Definition: CC1101.hh:513
Definition: SPI.hh:57
void acquire(Driver *dev)
Definition: SOFT_SPI.cpp:43
#define NULL
Definition: Types.h:101
#define EMSGSIZE
Definition: Errno.h:117
PA control table.
Definition: CC1101.hh:412
Calibrate frequency synthesizer.
Definition: CC1101.hh:517
virtual bool end()
Definition: CC1101.cpp:164
virtual bool begin(const void *config=NULL)
Definition: CC1101.cpp:127
Enable RX.
Definition: CC1101.hh:518
void write(uint8_t reg, uint8_t value)
Definition: CC1101.hh:267
volatile bool m_avail
Message available. May be set by ISR.
Definition: Wireless.hh:300
virtual int send(uint8_t dest, uint8_t port, const iovec_t *vec)
Definition: CC1101.cpp:173
virtual int input_power_level()
Definition: CC1101.cpp:298
Power down mode when CSn goes high.
Definition: CC1101.hh:523
virtual void disable()
void read(void *buf, size_t count)
Definition: SPI.hh:308
uint8_t m_channel
Current channel (device dependent.
Definition: Wireless.hh:298
uint8_t m_dest
Latest message destination device address.
Definition: Wireless.hh:301
uint8_t rssi
< Bit-field representation (little endian).
Definition: CC1101.hh:639
Definition: Types.h:391
Enable TX.
Definition: CC1101.hh:519
void pulse(uint16_t us) const
Definition: OutputPin.hh:378
GDO2 output pin configuration.
Definition: CC1101.hh:303
#define ETIME
Definition: Errno.h:89
Flush the RX FIFO buffer.
Definition: CC1101.hh:524
#define DELAY(us)
Definition: Types.h:280
virtual int recv(uint8_t &src, uint8_t &port, void *buf, size_t len, uint32_t ms=0L)
Definition: CC1101.cpp:211
uint8_t device
Device address (LSB).
Definition: Wireless.hh:41
static uint32_t since(uint32_t start)
Definition: RTT.hh:107
void strobe(Command cmd)
Definition: CC1101.cpp:110
int16_t network
Network address.
Definition: Wireless.hh:42
Reset chip.
Definition: CC1101.hh:514
static uint32_t millis()
Definition: RTT.cpp:121
uint8_t read(uint8_t reg)
Definition: CC1101.hh:242
void write(const void *buf, size_t count)
Definition: SPI.hh:321
ExternalInterruptPin
Definition: ATmega1284P.hh:190
virtual void on_interrupt(uint16_t arg=0)
Definition: CC1101.cpp:92
void(* yield)()
Channel number.
Definition: CC1101.hh:313
void begin()
Definition: SPI.hh:216
void end()
Definition: SPI.hh:226
#define UNUSED(x)
Definition: ATmega328P.hh:31
Number of configuration registers.
Definition: CC1101.hh:350
CC1101(uint16_t net, uint8_t dev, Board::DigitalPin csn=Board::D10, Board::ExternalInterruptPin irq=Board::EXT0)
Definition: CC1101.cpp:99
virtual void wakeup_on_radio()
Definition: CC1101.cpp:272
bool attach(Driver *dev)
Definition: SOFT_SPI.cpp:78
Overflow and # of bytes in RXFIFO.
Definition: CC1101.hh:490
status_t read_status(uint8_t fifo=1)
Definition: CC1101.hh:579
void write_P(uint8_t reg, const uint8_t *buf, size_t count)
Definition: CC1101.hh:293
Start automatic Wake-on-Radio.
Definition: CC1101.hh:522
static const size_t PAYLOAD_MAX
Definition: CC1101.hh:72
SPI spi
Definition: SPI.cpp:29
Sync word, high byte.
Definition: CC1101.hh:307
#define hton
Definition: Types.h:584
Mask # bytes.
Definition: CC1101.hh:491
virtual void output_power_level(int8_t dBm)
Definition: CC1101.cpp:279
void release()
Definition: SOFT_SPI.cpp:64
void await(Mode mode)
Definition: CC1101.cpp:121
Main State Machine Mode.
Definition: CC1101.hh:541
Device address.
Definition: CC1101.hh:312
#define UNLIKELY(x)
Definition: Types.h:153
OutputPin m_cs
Device chip select pin.
Definition: SPI.hh:166
Driver(Board::DigitalPin cs, Pulse pulse=DEFAULT_PULSE, Clock rate=DEFAULT_CLOCK, uint8_t mode=0, Order order=MSB_ORDER, Interrupt::Handler *irq=NULL)
Definition: SOFT_SPI.cpp:25
const uint8_t CC1101::config[CC1101::CONFIG_MAX] __PROGMEM
Definition: CC1101.cpp:47
void iovec_arg(iovec_t *&vp, const void *buf, size_t size)
Definition: Types.h:430
void iovec_end(iovec_t *&vp)
Definition: Types.h:449
size_t iovec_size(const iovec_t *vec)
Definition: Types.h:407
Transmitter FIFO.
Definition: CC1101.hh:413
virtual void powerdown()
Definition: CC1101.cpp:265