RadioHead
RH_CC110.h
1 // RH_CC110.h
2 //
3 // Definitions for Texas Instruments CC110L transceiver.
4 // http://www.ti.com/lit/ds/symlink/cc110l.pdf
5 // As used in Anaren CC110L Air Module BoosterPack
6 // https://www.anaren.com/air/cc110l-air-module-boosterpack-embedded-antenna-module-anaren
7 //
8 // Author: Mike McCauley (mikem@airspayce.com)
9 // Copyright (C) 2016 Mike McCauley
10 // $Id: RH_CC110.h,v 1.9 2020/01/05 07:02:23 mikem Exp $
11 //
12 
13 #ifndef RH_CC110_h
14 #define RH_CC110_h
15 
16 
17 #include <RHNRFSPIDriver.h>
18 
19 // This is the maximum number of interrupts the driver can support
20 // Most Arduinos can handle 2, Megas can handle more
21 #define RH_CC110_NUM_INTERRUPTS 3
22 
23 // Max number of octets the FIFO can hold
24 #define RH_CC110_FIFO_SIZE 64
25 
26 // This is the maximum number of bytes that can be carried by the chip
27 // We use some for headers, keeping fewer for RadioHead messages
28 #define RH_CC110_MAX_PAYLOAD_LEN RH_CC110_FIFO_SIZE
29 
30 // The length of the headers we add.
31 // The headers are inside the chip payload
32 #define RH_CC110_HEADER_LEN 4
33 
34 // This is the maximum message length that can be supported by this driver.
35 // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
36 // Here we allow for 1 byte message length, 4 bytes headers, user data
37 #ifndef RH_CC110_MAX_MESSAGE_LEN
38  #define RH_CC110_MAX_MESSAGE_LEN (RH_CC110_MAX_PAYLOAD_LEN - RH_CC110_HEADER_LEN - 1)
39 #endif
40 
41 #define RH_CC110_SPI_READ_MASK 0x80
42 #define RH_CC110_SPI_BURST_MASK 0x40
43 
44 // Register definitions from Table 5-22
45 #define RH_CC110_REG_00_IOCFG2 0x00
46 #define RH_CC110_REG_01_IOCFG1 0x01
47 #define RH_CC110_REG_02_IOCFG0 0x02
48 #define RH_CC110_REG_03_FIFOTHR 0x03
49 #define RH_CC110_REG_04_SYNC1 0x04
50 #define RH_CC110_REG_05_SYNC0 0x05
51 #define RH_CC110_REG_06_PKTLEN 0x06
52 #define RH_CC110_REG_07_PKTCTRL1 0x07
53 #define RH_CC110_REG_08_PKTCTRL0 0x08
54 #define RH_CC110_REG_09_ADDR 0x09
55 #define RH_CC110_REG_0A_CHANNR 0x0a
56 #define RH_CC110_REG_0B_FSCTRL1 0x0b
57 #define RH_CC110_REG_0C_FSCTRL0 0x0c
58 #define RH_CC110_REG_0D_FREQ2 0x0d
59 #define RH_CC110_REG_0E_FREQ1 0x0e
60 #define RH_CC110_REG_0F_FREQ0 0x0f
61 #define RH_CC110_REG_10_MDMCFG4 0x10
62 #define RH_CC110_REG_11_MDMCFG3 0x11
63 #define RH_CC110_REG_12_MDMCFG2 0x12
64 #define RH_CC110_REG_13_MDMCFG1 0x13
65 #define RH_CC110_REG_14_MDMCFG0 0x14
66 #define RH_CC110_REG_15_DEVIATN 0x15
67 #define RH_CC110_REG_16_MCSM2 0x16
68 #define RH_CC110_REG_17_MCSM1 0x17
69 #define RH_CC110_REG_18_MCSM0 0x18
70 #define RH_CC110_REG_19_FOCCFG 0x19
71 #define RH_CC110_REG_1A_BSCFG 0x1a
72 #define RH_CC110_REG_1B_AGCCTRL2 0x1b
73 #define RH_CC110_REG_1C_AGCCTRL1 0x1c
74 #define RH_CC110_REG_1D_AGCCTRL0 0x1d
75 #define RH_CC110_REG_1E_WOREVT1 0x1e
76 #define RH_CC110_REG_1F_WOREVT0 0x1f
77 #define RH_CC110_REG_20_WORCTRL 0x20
78 #define RH_CC110_REG_21_FREND1 0x21
79 #define RH_CC110_REG_22_FREND0 0x22
80 #define RH_CC110_REG_23_FSCAL3 0x23
81 #define RH_CC110_REG_24_FSCAL2 0x24
82 #define RH_CC110_REG_25_FSCAL1 0x25
83 #define RH_CC110_REG_26_FSCAL0 0x26
84 #define RH_CC110_REG_27_RCCTRL1 0x28
85 #define RH_CC110_REG_28_RCCTRL0 0x29
86 #define RH_CC110_REG_29_FSTEST 0x2a
87 #define RH_CC110_REG_2A_PTEST 0x2b
88 #define RH_CC110_REG_2B_AGCTEST 0x2c
89 #define RH_CC110_REG_2C_TEST2 0x2c
90 #define RH_CC110_REG_2D_TEST1 0x2d
91 #define RH_CC110_REG_2E_TEST0 0x2e
92 
93 // Single byte read and write version of registers 0x30 to 0x3f. Strobes
94 // use spiCommand()
95 #define RH_CC110_STROBE_30_SRES 0x30
96 #define RH_CC110_STROBE_31_SFSTXON 0x31
97 #define RH_CC110_STROBE_32_SXOFF 0x32
98 #define RH_CC110_STROBE_33_SCAL 0x33
99 #define RH_CC110_STROBE_34_SRX 0x34
100 #define RH_CC110_STROBE_35_STX 0x35
101 #define RH_CC110_STROBE_36_SIDLE 0x36
102 
103 #define RH_CC110_STROBE_39_SPWD 0x39
104 #define RH_CC110_STROBE_3A_SFRX 0x3a
105 #define RH_CC110_STROBE_3B_SFTX 0x3b
106 
107 #define RH_CC110_STROBE_3D_SNOP 0x3d
108 
109 
110 // Burst read from these registers gives more data:
111 // use spiBurstReadRegister()
112 #define RH_CC110_REG_30_PARTNUM 0x30
113 #define RH_CC110_REG_31_VERSION 0x31
114 #define RH_CC110_REG_32_FREQEST 0x32
115 #define RH_CC110_REG_33_CRC_REG 0x33
116 #define RH_CC110_REG_34_RSSI 0x34
117 #define RH_CC110_REG_35_MARCSTATE 0x35
118 
119 #define RH_CC110_REG_38_PKTSTATUS 0x38
120 
121 #define RH_CC110_REG_3A_TXBYTES 0x3a
122 #define RH_CC110_REG_3B_RXBYTES 0x3b
123 
124 // PATABLE, TXFIFO, RXFIFO also support burst
125 #define RH_CC110_REG_3E_PATABLE 0x3e
126 #define RH_CC110_REG_3F_FIFO 0x3f
127 
128 // Status Byte
129 #define RH_CC110_STATUS_CHIP_RDY 0x80
130 #define RH_CC110_STATUS_STATE 0x70
131 #define RH_CC110_STATUS_IDLE 0x00
132 #define RH_CC110_STATUS_RX 0x10
133 #define RH_CC110_STATUS_TX 0x20
134 #define RH_CC110_STATUS_FSTXON 0x30
135 #define RH_CC110_STATUS_CALIBRATE 0x40
136 #define RH_CC110_STATUS_SETTLING 0x50
137 #define RH_CC110_STATUS_RXFIFO_OVERFLOW 0x60
138 #define RH_CC110_STATUS_TXFIFO_UNDERFLOW 0x70
139 #define RH_CC110_STATUS_FIFOBYTES_AVAILABLE 0x0f
140 
141 // Register contents
142 // Chip Status Byte, read from header, data or command strobe
143 #define RH_CC110_CHIP_RDY 0x80
144 #define RH_CC110_STATE 0x70
145 #define RH_CC110_FIFO_BYTES_AVAILABLE 0x0f
146 
147 // Register bit field definitions
148 // #define RH_CC110_REG_00_IOCFG2 0x00
149 // #define RH_CC110_REG_01_IOCFG1 0x01
150 // #define RH_CC110_REG_02_IOCFG0 0x02
151 #define RH_CC110_GDO_CFG_RX_FIFO_THR 0x00
152 #define RH_CC110_GDO_CFG_RX_FIFO_FULL 0x01
153 #define RH_CC110_GDO_CFG_TX_FIFO_THR 0x02
154 #define RH_CC110_GDO_CFG_TX_FIFO_EMPTY 0x03
155 #define RH_CC110_GDO_CFG_RX_FIFO_OVERFLOW 0x04
156 #define RH_CC110_GDO_CFG_TX_FIFO_UNDEFLOOW 0x05
157 #define RH_CC110_GDO_CFG_SYNC 0x06
158 #define RH_CC110_GDO_CFG_CRC_OK_AUTORESET 0x07
159 #define RH_CC110_GDO_CFG_CCA 0x09
160 #define RH_CC110_GDO_CFG_LOCK_DETECT 0x0a
161 #define RH_CC110_GDO_CFG_SERIAL_CLOCK 0x0b
162 #define RH_CC110_GDO_CFG_SYNCHRONOUS_SDO 0x0c
163 #define RH_CC110_GDO_CFG_SDO 0x0d
164 #define RH_CC110_GDO_CFG_CARRIER 0x0e
165 #define RH_CC110_GDO_CFG_CRC_OK 0x0f
166 #define RH_CC110_GDO_CFG_PA_PD 0x1b
167 #define RH_CC110_GDO_CFG_LNA_PD 0x1c
168 #define RH_CC110_GDO_CFG_CLK_32K 0x27
169 #define RH_CC110_GDO_CFG_CHIP_RDYN 0x29
170 #define RH_CC110_GDO_CFG_XOSC_STABLE 0x2b
171 #define RH_CC110_GDO_CFG_HIGH_IMPEDANCE 0x2e
172 #define RH_CC110_GDO_CFG_0 0x2f
173 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_1 0x30
174 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_1_5 0x31
175 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_2 0x32
176 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_3 0x33
177 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_4 0x34
178 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_6 0x35
179 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_8 0x36
180 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_12 0x37
181 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_16 0x38
182 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_24 0x39
183 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_32 0x3a
184 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_48 0x3b
185 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_64 0x3c
186 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_96 0x3d
187 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_128 0x3e
188 #define RH_CC110_GDO_CFG_CLK_XOSC_DIV_192 0x3f
189 
190 // #define RH_CC110_REG_03_FIFOTHR 0x03
191 #define RH_CC110_ADC_RETENTION 0x80
192 
193 #define RH_CC110_CLOSE_IN_RX 0x30
194 #define RH_CC110_CLOSE_IN_RX_0DB 0x00
195 #define RH_CC110_CLOSE_IN_RX_6DB 0x10
196 #define RH_CC110_CLOSE_IN_RX_12DB 0x20
197 #define RH_CC110_CLOSE_IN_RX_18DB 0x30
198 
199 #define RH_CC110_FIFO_THR 0x0f
200 
201 // #define RH_CC110_REG_04_SYNC1 0x04
202 // #define RH_CC110_REG_05_SYNC0 0x05
203 // #define RH_CC110_REG_06_PKTLEN 0x06
204 // #define RH_CC110_REG_07_PKTCTRL1 0x07
205 #define RH_CC110_CRC_AUTOFLUSH 0x08
206 #define RH_CC110_APPEND_STATUS 0x04
207 #define RH_CC110_ADDR_CHK 0x03
208 // can or the next 2:
209 #define RH_CC110_ADDR_CHK_ADDRESS 0x01
210 #define RH_CC110_ADDR_CHK_BROADCAST 0x02
211 
212 
213 // #define RH_CC110_REG_08_PKTCTRL0 0x08
214 #define RH_CC110_PKT_FORMAT 0x30
215 #define RH_CC110_PKT_FORMAT_NORMAL 0x00
216 #define RH_CC110_PKT_FORMAT_SYNC_SERIAL 0x10
217 #define RH_CC110_PKT_FORMAT_RANDOM_TX 0x20
218 #define RH_CC110_PKT_FORMAT_ASYNC_SERIAL 0x30
219 
220 #define RH_CC110_CRC_EN 0x04
221 
222 #define RH_CC110_LENGTH_CONFIG 0x03
223 #define RH_CC110_LENGTH_CONFIG_FIXED 0x00
224 #define RH_CC110_LENGTH_CONFIG_VARIABLE 0x01
225 #define RH_CC110_LENGTH_CONFIG_INFINITE 0x02
226 
227 // #define RH_CC110_REG_09_ADDR 0x09
228 // #define RH_CC110_REG_0A_CHANNR 0x0a
229 // #define RH_CC110_REG_0B_FSCTRL1 0x0b
230 // #define RH_CC110_REG_0C_FSCTRL0 0x0c
231 // #define RH_CC110_REG_0D_FREQ2 0x0d
232 // #define RH_CC110_REG_0E_FREQ1 0x0e
233 // #define RH_CC110_REG_0F_FREQ0 0x0f
234 // #define RH_CC110_REG_10_MDMCFG4 0x10
235 #define RH_CC110_CHANBW_E 0xc0
236 #define RH_CC110_CHANBW_M 0x30
237 #define RH_CC110_DRATE_E 0x0f
238 
239 // #define RH_CC110_REG_11_MDMCFG3 0x11
240 // #define RH_CC110_REG_12_MDMCFG2 0x12
241 #define RH_CC110_DEM_DCFILT_OFF 0x80
242 #define RH_CC110_MOD_FORMAT 0x70
243 #define RH_CC110_MOD_FORMAT_2FSK 0x00
244 #define RH_CC110_MOD_FORMAT_GFSK 0x10
245 #define RH_CC110_MOD_FORMAT_OOK 0x30
246 #define RH_CC110_MOD_FORMAT_4FSK 0x40
247 #define RH_CC110_MANCHESTER_EN 0x08
248 #define RH_CC110_SYNC_MODE 0x07
249 #define RH_CC110_SYNC_MODE_NONE 0x00
250 #define RH_CC110_SYNC_MODE_15_16 0x01
251 #define RH_CC110_SYNC_MODE_16_16 0x02
252 #define RH_CC110_SYNC_MODE_30_32 0x03
253 #define RH_CC110_SYNC_MODE_NONE_CARRIER 0x04
254 #define RH_CC110_SYNC_MODE_15_16_CARRIER 0x05
255 #define RH_CC110_SYNC_MODE_16_16_CARRIER 0x06
256 #define RH_CC110_SYNC_MODE_30_32_CARRIER 0x07
257 
258 // #define RH_CC110_REG_13_MDMCFG1 0x13
259 #define RH_CC110_NUM_PREAMBLE 0x70
260 #define RH_CC110_NUM_PREAMBLE_2 0x00
261 #define RH_CC110_NUM_PREAMBLE_3 0x10
262 #define RH_CC110_NUM_PREAMBLE_4 0x20
263 #define RH_CC110_NUM_PREAMBLE_6 0x30
264 #define RH_CC110_NUM_PREAMBLE_8 0x40
265 #define RH_CC110_NUM_PREAMBLE_12 0x50
266 #define RH_CC110_NUM_PREAMBLE_16 0x60
267 #define RH_CC110_NUM_PREAMBLE_24 0x70
268 
269 #define RH_CC110_CHANSPC_E 0x03
270 
271 // #define RH_CC110_REG_14_MDMCFG0 0x14
272 // #define RH_CC110_REG_15_DEVIATN 0x15
273 #define RH_CC110_DEVIATION_E 0x70
274 #define RH_CC110_DEVIATION_M 0x07
275 
276 // #define RH_CC110_REG_16_MCSM2 0x16
277 #define RH_CC110_RX_TIME_RSSI 0x10
278 
279 // #define RH_CC110_REG_17_MCSM1 0x17
280 #define RH_CC110_CCA_MODE 0x30
281 #define RH_CC110_CCA_MODE_ALWAYS 0x00
282 #define RH_CC110_CCA_MODE_RSSI 0x10
283 #define RH_CC110_CCA_MODE_PACKET 0x20
284 #define RH_CC110_CCA_MODE_RSSI_PACKET 0x30
285 #define RH_CC110_RXOFF_MODE 0x0c
286 #define RH_CC110_RXOFF_MODE_IDLE 0x00
287 #define RH_CC110_RXOFF_MODE_FSTXON 0x04
288 #define RH_CC110_RXOFF_MODE_TX 0x08
289 #define RH_CC110_RXOFF_MODE_RX 0x0c
290 #define RH_CC110_TXOFF_MODE 0x03
291 #define RH_CC110_TXOFF_MODE_IDLE 0x00
292 #define RH_CC110_TXOFF_MODE_FSTXON 0x01
293 #define RH_CC110_TXOFF_MODE_TX 0x02
294 #define RH_CC110_TXOFF_MODE_RX 0x03
295 
296 // #define RH_CC110_REG_18_MCSM0 0x18
297 #define RH_CC110_FS_AUTOCAL 0x30
298 #define RH_CC110_FS_AUTOCAL_NEVER 0x00
299 #define RH_CC110_FS_AUTOCAL_FROM_IDLE 0x10
300 #define RH_CC110_FS_AUTOCAL_TO_IDLE 0x20
301 #define RH_CC110_FS_AUTOCAL_TO_IDLE_4 0x30
302 #define RH_CC110_PO_TIMEOUT 0x0c
303 #define RH_CC110_PO_TIMEOUT_1 0x00
304 #define RH_CC110_PO_TIMEOUT_16 0x04
305 #define RH_CC110_PO_TIMEOUT_64 0x08
306 #define RH_CC110_PO_TIMEOUT_256 0x0c
307 #define RH_CC110_XOSC_FORCE_ON 0x01
308 
309 // #define RH_CC110_REG_19_FOCCFG 0x19
310 #define RH_CC110_FOC_BS_CS_GATE 0x20
311 #define RH_CC110_FOC_PRE_K 0x18
312 #define RH_CC110_FOC_PRE_K_0 0x00
313 #define RH_CC110_FOC_PRE_K_1 0x08
314 #define RH_CC110_FOC_PRE_K_2 0x10
315 #define RH_CC110_FOC_PRE_K_3 0x18
316 #define RH_CC110_FOC_POST_K 0x04
317 #define RH_CC110_FOC_LIMIT 0x03
318 #define RH_CC110_FOC_LIMIT_0 0x00
319 #define RH_CC110_FOC_LIMIT_8 0x01
320 #define RH_CC110_FOC_LIMIT_4 0x02
321 #define RH_CC110_FOC_LIMIT_2 0x03
322 
323 // #define RH_CC110_REG_1A_BSCFG 0x1a
324 #define RH_CC110_BS_PRE_K 0xc0
325 #define RH_CC110_BS_PRE_K_1 0x00
326 #define RH_CC110_BS_PRE_K_2 0x40
327 #define RH_CC110_BS_PRE_K_3 0x80
328 #define RH_CC110_BS_PRE_K_4 0xc0
329 #define RH_CC110_BS_PRE_KP 0x30
330 #define RH_CC110_BS_PRE_KP_1 0x00
331 #define RH_CC110_BS_PRE_KP_2 0x10
332 #define RH_CC110_BS_PRE_KP_3 0x20
333 #define RH_CC110_BS_PRE_KP_4 0x30
334 #define RH_CC110_BS_POST_KI 0x08
335 #define RH_CC110_BS_POST_KP 0x04
336 #define RH_CC110_BS_LIMIT 0x03
337 #define RH_CC110_BS_LIMIT_0 0x00
338 #define RH_CC110_BS_LIMIT_3 0x01
339 #define RH_CC110_BS_LIMIT_6 0x02
340 #define RH_CC110_BS_LIMIT_12 0x03
341 
342 // #define RH_CC110_REG_1B_AGCCTRL2 0x1b
343 #define RH_CC110_MAX_DVA_GAIN 0xc0
344 #define RH_CC110_MAX_DVA_GAIN_ALL 0x00
345 #define RH_CC110_MAX_DVA_GAIN_ALL_LESS_1 0x40
346 #define RH_CC110_MAX_DVA_GAIN_ALL_LESS_2 0x80
347 #define RH_CC110_MAX_DVA_GAIN_ALL_LESS_3 0xc0
348 #define RH_CC110_MAX_LNA_GAIN 0x38
349 
350 #define RH_CC110_MAGN_TARGET 0x07
351 #define RH_CC110_MAGN_TARGET_24DB 0x00
352 #define RH_CC110_MAGN_TARGET_27DB 0x01
353 #define RH_CC110_MAGN_TARGET_30DB 0x02
354 #define RH_CC110_MAGN_TARGET_33DB 0x03
355 #define RH_CC110_MAGN_TARGET_36DB 0x04
356 #define RH_CC110_MAGN_TARGET_38DB 0x05
357 #define RH_CC110_MAGN_TARGET_40DB 0x06
358 #define RH_CC110_MAGN_TARGET_42DB 0x07
359 
360 // #define RH_CC110_REG_1C_AGCCTRL1 0x1c
361 #define RH_CC110_AGC_LNA_PRIORITY 0x40
362 #define RH_CC110_CARRIER_SENSE_REL_THR 0x30
363 #define RH_CC110_CARRIER_SENSE_REL_THR_0DB 0x00
364 #define RH_CC110_CARRIER_SENSE_REL_THR_6DB 0x10
365 #define RH_CC110_CARRIER_SENSE_REL_THR_10DB 0x20
366 #define RH_CC110_CARRIER_SENSE_REL_THR_14DB 0x30
367 #define RH_CC110_CARRIER_SENSE_ABS_THR 0x0f
368 
369 // #define RH_CC110_REG_1D_AGCCTRL0 0x1d
370 #define RH_CC110_HYST_LEVEL 0xc0
371 #define RH_CC110_HYST_LEVEL_NONE 0x00
372 #define RH_CC110_HYST_LEVEL_LOW 0x40
373 #define RH_CC110_HYST_LEVEL_MEDIUM 0x80
374 #define RH_CC110_HYST_LEVEL_HIGH 0xc0
375 #define RH_CC110_WAIT_TIME 0x30
376 #define RH_CC110_WAIT_TIME_8 0x00
377 #define RH_CC110_WAIT_TIME_16 0x10
378 #define RH_CC110_WAIT_TIME_24 0x20
379 #define RH_CC110_WAIT_TIME_32 0x30
380 #define RH_CC110_AGC_FREEZE 0x0c
381 #define RH_CC110_AGC_FILTER_LENGTH 0x03
382 #define RH_CC110_AGC_FILTER_LENGTH_8 0x00
383 #define RH_CC110_AGC_FILTER_LENGTH_16 0x01
384 #define RH_CC110_AGC_FILTER_LENGTH_32 0x02
385 #define RH_CC110_AGC_FILTER_LENGTH_64 0x03
386 
387 // #define RH_CC110_REG_1E_WOREVT1 0x1e
388 // #define RH_CC110_REG_1F_WOREVT0 0x1f
389 // #define RH_CC110_REG_20_WORCTRL 0x20
390 // #define RH_CC110_REG_21_FREND1 0x21
391 #define RH_CC110_LNA_CURRENT 0xc0
392 #define RH_CC110_LNA2MIX_CURRENT 0x30
393 #define RH_CC110_LODIV_BUF_CURRENT_RX 0x0c
394 #define RH_CC110_MIX_CURRENT 0x03
395 
396 // #define RH_CC110_REG_22_FREND0 0x22
397 #define RH_CC110_LODIV_BUF_CURRENT_TX 0x30
398 #define RH_CC110_PA_POWER 0x07
399 
400 // #define RH_CC110_REG_23_FSCAL3 0x23
401 #define RH_CC110_FSCAL3_7_6 0xc0
402 #define RH_CC110_CHP_CURR_CAL_EN 0x30
403 #define RH_CC110_FSCAL3_3_0 0x0f
404 
405 // #define RH_CC110_REG_24_FSCAL2 0x24
406 #define RH_CC110_VCO_CORE_H_EN 0x20
407 #define RH_CC110_FSCAL2 0x1f
408 
409 // #define RH_CC110_REG_25_FSCAL1 0x25
410 #define RH_CC110_FSCAL1 0x3f
411 
412 // #define RH_CC110_REG_26_FSCAL0 0x26
413 #define RH_CC110_FSCAL0 0x7f
414 
415 // #define RH_CC110_REG_27_RCCTRL1 0x28
416 // #define RH_CC110_REG_28_RCCTRL0 0x29
417 // #define RH_CC110_REG_29_FSTEST 0x2a
418 // #define RH_CC110_REG_2A_PTEST 0x2b
419 // #define RH_CC110_REG_2B_AGCTEST 0x2c
420 // #define RH_CC110_REG_2C_TEST2 0x2c
421 // #define RH_CC110_REG_2D_TEST1 0x2d
422 // #define RH_CC110_REG_2E_TEST0 0x2e
423 #define RH_CC110_TEST0_7_2 0xfc
424 #define RH_CC110_VCO_SEL_CAL_EN 0x02
425 #define RH_CC110_TEST0_0 0x01
426 
427 // #define RH_CC110_REG_30_PARTNUM 0x30
428 // #define RH_CC110_REG_31_VERSION 0x31
429 // #define RH_CC110_REG_32_FREQEST 0x32
430 // #define RH_CC110_REG_33_CRC_REG 0x33
431 #define RH_CC110_CRC_REG_CRC_OK 0x80
432 
433 // #define RH_CC110_REG_34_RSSI 0x34
434 // #define RH_CC110_REG_35_MARCSTATE 0x35
435 #define RH_CC110_MARC_STATE 0x1f
436 #define RH_CC110_MARC_STATE_SLEEP 0x00
437 #define RH_CC110_MARC_STATE_IDLE 0x01
438 #define RH_CC110_MARC_STATE_XOFF 0x02
439 #define RH_CC110_MARC_STATE_VCOON_MC 0x03
440 #define RH_CC110_MARC_STATE_REGON_MC 0x04
441 #define RH_CC110_MARC_STATE_MANCAL 0x05
442 #define RH_CC110_MARC_STATE_VCOON 0x06
443 #define RH_CC110_MARC_STATE_REGON 0x07
444 #define RH_CC110_MARC_STATE_STARTCAL 0x08
445 #define RH_CC110_MARC_STATE_BWBOOST 0x09
446 #define RH_CC110_MARC_STATE_FS_LOCK 0x0a
447 #define RH_CC110_MARC_STATE_IFADCON 0x0b
448 #define RH_CC110_MARC_STATE_ENDCAL 0x0c
449 #define RH_CC110_MARC_STATE_RX 0x0d
450 #define RH_CC110_MARC_STATE_RX_END 0x0e
451 #define RH_CC110_MARC_STATE_RX_RST 0x0f
452 #define RH_CC110_MARC_STATE_TXRX_SWITCH 0x10
453 #define RH_CC110_MARC_STATE_RXFIFO_OVERFLOW 0x11
454 #define RH_CC110_MARC_STATE_FSTXON 0x12
455 #define RH_CC110_MARC_STATE_TX 0x13
456 #define RH_CC110_MARC_STATE_TX_END 0x14
457 #define RH_CC110_MARC_STATE_RXTX_SWITCH 0x15
458 #define RH_CC110_MARC_STATE_TXFIFO_UNDERFLOW 0x16
459 
460 // #define RH_CC110_REG_38_PKTSTATUS 0x38
461 #define RH_CC110_PKTSTATUS_CRC_OK 0x80
462 #define RH_CC110_PKTSTATUS_CS 0x40
463 #define RH_CC110_PKTSTATUS_CCA 0x10
464 #define RH_CC110_PKTSTATUS_SFD 0x08
465 #define RH_CC110_PKTSTATUS_GDO2 0x04
466 #define RH_CC110_PKTSTATUS_GDO0 0x01
467 
468 // #define RH_CC110_REG_3A_TXBYTES 0x3a
469 #define RH_CC110_TXFIFO_UNDERFLOW 0x80
470 #define RH_CC110_NUM_TXBYTES 0x7f
471 
472 // #define RH_CC110_REG_3B_RXBYTES 0x3b
473 #define RH_CC110_RXFIFO_UNDERFLOW 0x80
474 #define RH_CC110_NUM_RXBYTES 0x7f
475 
476 /////////////////////////////////////////////////////////////////////
477 /// \class RH_CC110 RH_CC110.h <RH_CC110.h>
478 /// \brief Send and receive unaddressed, unreliable, datagrams by Texas Instruments CC110L and compatible transceivers and modules.
479 ///
480 /// The TI CC110L is a low cost tranceiver chip capable of 300 to 928MHz and with a wide range of modulation types and speeds.
481 /// The chip is typically provided on a module that also includes the antenna and coupling hardware
482 /// and is therefore capable of a more restricted frequency range.
483 ///
484 /// Supported modules include:
485 /// - Anaren AIR BoosterPack 430BOOST-CC110L
486 ///
487 /// This base class provides basic functions for sending and receiving unaddressed, unreliable datagrams
488 /// of arbitrary length to 59 octets per packet at a selected data rate and modulation type.
489 /// Use one of the Manager classes to get addressing and
490 /// acknowledgement reliability, routing, meshes etc.
491 ///
492 /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
493 /// data rate, and with identical network addresses.
494 ///
495 /// Several CC110L modules can be connected to an Arduino, permitting the construction of translators
496 /// and frequency changers, etc.
497 ///
498 /// Several GFSK modulation schemes are provided and may be selected by calling setModemConfig(). No FSK or OOK
499 /// modulation schemes are provided though the implementor may configure the mnodem characteristics directly
500 /// by calling setModemRegisters().
501 ///
502 /// Implementation based on:
503 /// http://www.ti.com/lit/ds/symlink/cc110l.pdf
504 /// and
505 /// https://www.anaren.com/air/cc110l-air-module-boosterpack-embedded-antenna-module-anaren
506 ///
507 /// \par Crystal Frequency
508 ///
509 /// Modules based on the CC110L may contain a crystal oscillator with one of 2 possible frequencies: 26MHz or 27MHz.
510 /// A number of radio configuration parameters (including carrier frequency and data rates) depend on the
511 /// crystal oscillator frequency. The chip has no knowledge of the frequency, so it is up to the implementer
512 /// to tell the driver the oscillator frequency by passing in the appropriate value of is27MHz to the constructor (default 26MHz)
513 /// or by calling setIs27MHz() before calling init().
514 /// Failure to correctly set this flag will cause incorrect frequency and modulation
515 /// characteristics to be used.
516 ///
517 /// Caution: it is not easy to determine what the actual crystal frequency is on some modules. For example,
518 /// the documentation for the Anaren BoosterPack indictes a 26MHz crystal, but measurements on the devices delivered here
519 /// indicate a 27MHz crystal is actually installed. TI recommend 27MHz for
520 ///
521 /// \par Packet Format
522 ///
523 /// - 2 octets sync (a configurable network address)
524 /// - 1 octet message length
525 /// - 4 to 63 octets of payload consisting of:
526 /// - 1 octet TO header
527 /// - 1 octet FROM header
528 /// - 1 octet ID header
529 /// - 1 octet FLAGS header
530 /// - 0 to 59 octets of user message
531 /// - 2 octets CRC
532 ///
533 /// \par Connecting CC110L to Arduino
534 ///
535 /// Warning: the CC110L is a 3.3V part, and exposing it to 5V on any pin will damage it. Ensure you are using a 3.3V
536 /// MCU or use level shifters. We tested with Teensy 3.1.
537 ///
538 /// The electrical connection between a CC110L module and the Arduino or other processor
539 /// require 3.3V, the 3 x SPI pins (SCK, SDI, SDO),
540 /// a Chip Select pin and an Interrupt pin.
541 /// Examples below assume the Anaren BoosterPack. Caution: the pin numbering on the Anaren BoosterPack
542 /// is a bit counter-intuitive: the direction of number on J1 is the reverse of J2. Check the pin numbers
543 /// stenciled on the front of the board to be sure.
544 ///
545 /// \code
546 /// Teensy 3.1 CC110L pin name Anaren BoosterPack pin
547 /// 3.3V---------VDD (3.3V in) J1-1
548 /// SS pin D10----------CSn (chip select in) J2-8
549 /// SCK pin D13----------SCLK (SPI clock in) J1-7
550 /// MOSI pin D11----------MOSI (SPI data in) J2-5
551 /// MISO pin D12----------MISO (SPI data out) J2-4
552 /// D2-----------GDO0 (Interrupt output) J2-9
553 /// GND----------GND (ground in) J2-10
554 /// \endcode
555 /// and use the default RH_CC110 constructor. You can use other pins by passing the appropriate arguments
556 /// to the RH_CC110 constructor, depending on what your MCU supports.
557 ///
558 /// For the Particle Photon:
559 /// \code
560 /// Photon CC110L pin name Anaren BoosterPack pin
561 /// 3.3V---------VDD (3.3V in) J1-1
562 /// SS pin A2-----------CSn (chip select in) J2-8
563 /// SCK pin A3-----------SCLK (SPI clock in) J1-7
564 /// MOSI pin A5-----------MOSI (SPI data in) J2-5
565 /// MISO pin A4-----------MISO (SPI data out) J2-4
566 /// D2-----------GDO0 (Interrupt output) J2-9
567 /// GND----------GND (ground in) J2-10
568 /// \endcode
569 /// and use the default RH_CC110 constructor. You can use other pins by passing the appropriate arguments
570 /// to the RH_CC110 constructor, depending on what your MCU supports.
571 ///
572 /// \par Example programs
573 ///
574 /// Several example programs are provided.
575 ///
576 /// \par Radio operating strategy and defaults
577 ///
578 /// The radio is enabled at all times and switched between RX, TX and IDLE modes.
579 /// When RX is enabled (by calling available() or setModeRx()) the radio will stay in RX mode until a
580 /// valid CRC correct message addressed to thiis node is received, when it will transition to IDLE.
581 /// When TX is enabled (by calling send()) it will stay in TX mode until the message has ben sent
582 /// and waitPacketSent() is called when it wil transition to IDLE
583 ///(this radio has no 'packet sent' interrupt that could be used, so polling
584 /// with waitPacketSent() is required
585 ///
586 /// The modulation schemes supported include the GFSK schemes provided by default in the TI SmartRF Suite.
587 /// This software allows you to get the correct register values for diferent modulation schemes. All the modulation
588 /// schemes prvided in the driver are based on the recommended register values given by SmartRF.
589 /// Other schemes such a 2-FSK, 4-FSK and OOK are suported by the chip, but canned configurations are not provided with this driver.
590 /// The implementer may choose to create their own modem configurations and pass them to setModemRegisters().
591 ///
592 class RH_CC110 : public RHNRFSPIDriver
593 {
594 public:
595 
596  /// \brief Defines register configuration values for a desired modulation
597  ///
598  /// Defines values for various configuration fields and registers to
599  /// achieve a desired modulation speed and frequency deviation.
600  typedef struct
601  {
602  uint8_t reg_0b; ///< RH_CC110_REG_0B_FSCTRL1
603  uint8_t reg_0c; ///< RH_CC110_REG_0C_FSCTRL0
604  uint8_t reg_10; ///< RH_CC110_REG_10_MDMCFG4
605  uint8_t reg_11; ///< RH_CC110_REG_11_MDMCFG3
606  uint8_t reg_12; ///< RH_CC110_REG_12_MDMCFG2
607  uint8_t reg_15; ///< RH_CC110_REG_15_DEVIATN
608  uint8_t reg_19; ///< RH_CC110_REG_19_FOCCFG
609  uint8_t reg_1a; ///< RH_CC110_REG_1A_BSCFG
610  uint8_t reg_1b; ///< RH_CC110_REG_1B_AGCCTRL2
611  uint8_t reg_1c; ///< RH_CC110_REG_1C_AGCCTRL1
612  uint8_t reg_1d; ///< RH_CC110_REG_1D_AGCCTRL0
613  uint8_t reg_21; ///< RH_CC110_REG_21_FREND1
614  uint8_t reg_22; ///< RH_CC110_REG_22_FREND0
615  uint8_t reg_23; ///< RH_CC110_REG_23_FSCAL3
616  uint8_t reg_24; ///< RH_CC110_REG_24_FSCAL2
617  uint8_t reg_25; ///< RH_CC110_REG_25_FSCAL1
618  uint8_t reg_26; ///< RH_CC110_REG_26_FSCAL0
619  uint8_t reg_2c; ///< RH_CC110_REG_2C_TEST2
620  uint8_t reg_2d; ///< RH_CC110_REG_2D_TEST1
621  uint8_t reg_2e; ///< RH_CC110_REG_2E_TEST0
622  } ModemConfig;
623 
624 
625  /// Choices for setModemConfig() for a selected subset of common modulation types,
626  /// and data rates. If you need another configuration, use the register calculator.
627  /// and call setModemRegisters() with your desired settings.
628  /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
629  /// definitions and not their integer equivalents: its possible that new values will be
630  /// introduced in later versions (though we will try to avoid it).
631  /// All configs use SYNC_MODE = RH_CC110_SYNC_MODE_16_16 (2 byte sync)
632  typedef enum
633  {
634  GFSK_Rb1_2Fd5_2 = 0, ///< GFSK, Data Rate: 1.2kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity
635  GFSK_Rb2_4Fd5_2, ///< GFSK, Data Rate: 2.4kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity
636  GFSK_Rb4_8Fd25_4, ///< GFSK, Data Rate: 4.8kBaud, Dev: 25.4kHz, RX BW 100kHz, optimised for sensitivity
637  GFSK_Rb10Fd19, ///< GFSK, Data Rate: 10kBaud, Dev: 19kHz, RX BW 100kHz, optimised for sensitivity
638  GFSK_Rb38_4Fd20, ///< GFSK, Data Rate: 38.4kBaud, Dev: 20kHz, RX BW 100kHz, optimised for sensitivity
639  GFSK_Rb76_8Fd32, ///< GFSK, Data Rate: 76.8kBaud, Dev: 32kHz, RX BW 232kHz, optimised for sensitivity
640  GFSK_Rb100Fd47, ///< GFSK, Data Rate: 100kBaud, Dev: 47kHz, RX BW 325kHz, optimised for sensitivity
641  GFSK_Rb250Fd127, ///< GFSK, Data Rate: 250kBaud, Dev: 127kHz, RX BW 540kHz, optimised for sensitivity
643 
644  /// These power outputs are based on the suggested optimum values for
645  /// multilayer inductors in the 915MHz frequency band. Per table 5-15.
646  /// Caution: these enum values are indexes into PaPowerValues.
647  /// Do not change one without changing the other. Use the symbolic names, not the integer values
648  typedef enum
649  {
650  TransmitPowerM30dBm = 0, ///< -30dBm
651  TransmitPowerM20dBm, ///< -20dBm
652  TransmitPowerM15dBm, ///< -15dBm
653  TransmitPowerM10dBm, ///< -10dBm
654  TransmitPower0dBm, ///< 0dBm
655  TransmitPower5dBm, ///< 5dBm
656  TransmitPower7dBm, ///< 7dBm
657  TransmitPower10dBm, ///< 10dBm
658  } TransmitPower;
659 
660  /// Constructor. You can have multiple instances, but each instance must have its own
661  /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
662  /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
663  /// distinct interrupt lines, one for each instance.
664  /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the CC110L before
665  /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
666  /// \param[in] interruptPin The interrupt Pin number that is connected to the CC110L GDO0 interrupt line.
667  /// Defaults to pin 2.
668  /// Caution: You must specify an interrupt capable pin.
669  /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
670  /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
671  /// On other Arduinos pins 2 or 3.
672  /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
673  /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
674  /// On other boards, any digital pin may be used.
675  /// \param[in] is27MHz Set to true if your CC110 is equipped with a 27MHz crystal oscillator. Defaults to false.
676  /// \param[in] spi Pointer to the SPI interface object to use.
677  /// Defaults to the standard Arduino hardware SPI interface
678  RH_CC110(uint8_t slaveSelectPin = SS, uint8_t interruptPin = 2, bool is27MHz = false, RHGenericSPI& spi = hardware_spi);
679 
680  /// Initialise the Driver transport hardware and software.
681  /// Make sure the Driver is properly configured before calling init().
682  /// In particular, ensure you have called setIs27MHz(true) if your module has a 27MHz crystal oscillator.
683  /// After init(), the following default characteristics are set:
684  /// TxPower: TransmitPower5dBm
685  /// Frequency: 915.0
686  /// Modulation: GFSK_Rb1_2Fd5_2 (GFSK, Data Rate: 1.2kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity)
687  /// Sync Words: 0xd3, 0x91
688  /// \return true if initialisation succeeded.
689  virtual bool init();
690 
691  /// Prints the value of all chip registers
692  /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
693  /// For debugging purposes only.
694  /// \return true on success
695  bool printRegisters();
696 
697  /// Blocks until the current message (if any)
698  /// has been transmitted
699  /// \return true on success, false if the chip is not in transmit mode or other transmit failure
700  virtual bool waitPacketSent();
701 
702  /// Tests whether a new message is available
703  /// from the Driver.
704  /// On most drivers, this will also put the Driver into RHModeRx mode until
705  /// a message is actually received by the transport, when it will be returned to RHModeIdle
706  /// and available() will return true.
707  /// This can be called multiple times in a timeout loop
708  /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
709  virtual bool available();
710 
711  /// Turns the receiver on if it not already on (after wiaint gor any currenly transmitting message to complete).
712  /// If there is a valid message available, copy it to buf and return true
713  /// else return false.
714  /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
715  /// You should be sure to call this function frequently enough to not miss any messages
716  /// It is recommended that you call it in your main loop.
717  /// \param[in] buf Location to copy the received message
718  /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
719  /// \return true if a valid message was copied to buf. The message cannot be retreived again.
720  virtual bool recv(uint8_t* buf, uint8_t* len);
721 
722  /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
723  /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
724  /// of 0 is permitted.
725  /// \param[in] data Array of data to be sent
726  /// \param[in] len Number of bytes of data to send
727  /// \return true if the message length was valid and it was correctly queued for transmit
728  virtual bool send(const uint8_t* data, uint8_t len);
729 
730  /// Returns the maximum message length
731  /// available in this Driver.
732  /// \return The maximum legal message length
733  virtual uint8_t maxMessageLength();
734 
735  /// If current mode is Sleep, Rx or Tx changes it to Idle. If the transmitter or receiver is running,
736  /// disables them.
737  void setModeIdle();
738 
739  /// If current mode is Tx or Idle, changes it to Rx.
740  /// Starts the receiver. The radio will stay in Rx mode until a CRC correct message addressed to this node
741  /// is received, or the ode is changed to Tx, Idle or Sleep.
742  void setModeRx();
743 
744  /// If current mode is Rx or Idle, changes it to Tx.
745  /// Starts the transmitter sending the current message.
746  void setModeTx();
747 
748  /// Sets the radio into low-power sleep mode.
749  /// If successful, the transport will stay in sleep mode until woken by
750  /// changing mode to idle, transmit or receive (eg by calling send(), recv(), available() etc)
751  /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
752  /// Caution: waking up from sleep loses values from registers 0x29 through 0x2e
753  /// \return true if sleep mode was successfully entered.
754  virtual bool sleep();
755 
756  /// Set the Power Amplifier power setting.
757  /// The PaTable settings are based on are based on the suggested optimum values for
758  /// multilayer inductors in the 915MHz frequency band. Per table 5-15.
759  /// If these values are not suitable, use setPaTable() directly.
760  /// Caution: be a good neighbour and use the lowest power setting compatible with your application.
761  /// Caution: Permissable power settings for your area may depend on frequency and modulation characteristics:
762  /// consult local authorities.
763  /// param[in] power One of TransmitPower enum values
764  bool setTxPower(TransmitPower power);
765 
766  /// Indicates the presence of 27MHz crystal oscillator.
767  /// You must indicate to the driver if your CC110L is equipped with a 27MHz crystal oscillator (26MHz is the default
768  /// in the constructor).
769  /// This should be called before calling init() if you have a 27MHz crystal.
770  /// It can be called after calling init() but you must reset the frequency (with setFrequency()) and modulation
771  /// (with setModemConfig()) afterwards.
772  /// \param[in] is27MHz Pass true if the CC110L has a 27MHz crystal (default is true).
773  void setIs27MHz(bool is27MHz = true);
774 
775  /// Sets the transmitter and receiver
776  /// centre frequency.
777  /// Caution: permissable frequency bands will depend on you country and area: consult local authorities.
778  /// \param[in] centre Frequency in MHz. 300.0 to 928.0
779  /// \return true if the selected frquency centre is within range
780  bool setFrequency(float centre);
781 
782  /// Sets all the registers required to configure the data modem in the CC110, including the data rate,
783  /// bandwidths etc. You cas use this to configure the modem with custom configuraitons if none of the
784  /// canned configurations in ModemConfigChoice suit you.
785  /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
786  void setModemRegisters(const ModemConfig* config);
787 
788  /// Select one of the predefined modem configurations. If you need a modem configuration not provided
789  /// here, use setModemRegisters() with your own ModemConfig.
790  /// \param[in] index The configuration choice.
791  /// \return true if index is a valid choice.
792  bool setModemConfig(ModemConfigChoice index);
793 
794  /// Sets the sync words for transmit and receive in registers RH_CC110_REG_04_SYNC1 and RH_CC110_REG_05_SYNC0.
795  /// Caution: SyncWords should be set to the same
796  /// value on all nodes in your network. Nodes with different SyncWords set will never receive
797  /// each others messages, so different SyncWords can be used to isolate different
798  /// networks from each other. Default is { 0xd3, 0x91 }.
799  /// \param[in] syncWords Array of sync words, 2 octets long
800  /// \param[in] len Number of sync words to set. MUST be 2.
801  void setSyncWords(const uint8_t* syncWords, uint8_t len);
802 
803  /// Sets the PaTable registers directly.
804  /// Ensure you use suitable PATABLE values per Tbale 5-15 or 5-16
805  /// You may need to do this to implement an OOK modulation scheme.
806  void setPaTable(uint8_t* patable, uint8_t patablesize);
807 
808 protected:
809  /// This is a low level function to handle the interrupts for one instance of RH_RF95.
810  /// Called automatically by isr*()
811  /// Should not need to be called by user code.
812  void handleInterrupt();
813 
814  /// Reads a single register from the CC110L
815  /// \param[in] reg Register number, one of RH_CC110_REG
816  /// \return The value of the register
817  uint8_t spiReadRegister(uint8_t reg);
818 
819  /// Reads a single register in burst mode.
820  /// On the CC110L, some registers yield different data when read in burst mode
821  /// as opposed to single byte mode.
822  /// \param[in] reg Register number, one of RH_CC110_REG (burst mode readable)
823  /// \return The value of the register after a burst read
824  uint8_t spiBurstReadRegister(uint8_t reg);
825 
826  /// Writes to a single single register on the CC110L
827  /// \param[in] reg Register number, one of RH_CC110L_REG_*
828  /// \param[in] val The value to write
829  /// \return returns the chip status byte per table 5.2
830  uint8_t spiWriteRegister(uint8_t reg, uint8_t val);
831 
832  /// Write a number of bytes to a burst capable register
833  /// \param[in] reg Register number of the first register, one of RH_CC110L_REG_*
834  /// \param[in] src Array of new register values to write. Must be at least len bytes
835  /// \param[in] len Number of bytes to write
836  /// \return the chip status byte per table 5.2
837  uint8_t spiBurstWriteRegister(uint8_t reg, const uint8_t* src, uint8_t len);
838 
839  /// Examine the receive buffer to determine whether the message is for this node
840  /// Sets _rxBufValid.
841  void validateRxBuf();
842 
843  /// Clear our local receive buffer
844  void clearRxBuf();
845 
846  /// Reads and returns the status byte by issuing the SNOP strobe
847  /// \return The value of the status byte per Table 5-2
848  uint8_t statusRead();
849 
850  /// Handle the TX or RX overflow state of the given status
851  /// \param status The status byte read from the last SPI command
852  /// \return void
853  void handleOverFlows(uint8_t status);
854 
855 
856 private:
857  /// Low level interrupt service routine for device connected to interrupt 0
858  static void isr0();
859 
860  /// Low level interrupt service routine for device connected to interrupt 1
861  static void isr1();
862 
863  /// Low level interrupt service routine for device connected to interrupt 1
864  static void isr2();
865 
866  /// Array of instances connected to interrupts 0 and 1
867  static RH_CC110* _deviceForInterrupt[];
868 
869  /// Index of next interrupt number to use in _deviceForInterrupt
870  static uint8_t _interruptCount;
871 
872  /// The configured interrupt pin connected to this instance
873  uint8_t _interruptPin;
874 
875  /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
876  /// else 0xff
877  uint8_t _myInterruptIndex;
878 
879  /// Number of octets in the buffer
880  volatile uint8_t _bufLen;
881 
882  /// The receiver/transmitter buffer
883  uint8_t _buf[RH_CC110_MAX_PAYLOAD_LEN];
884 
885  /// True when there is a valid message in the buffer
886  volatile bool _rxBufValid;
887 
888  /// True if crystal oscillator is 26 MHz, not 26MHz.
889  bool _is27MHz;
890 };
891 
892 /// @example cc110_client.pde
893 /// @example cc110_server.pde
894 
895 #endif
RHGenericDriver::_rxGood
volatile uint16_t _rxGood
Count of the number of successfully transmitted messaged.
Definition: RHGenericDriver.h:292
RH_CC110::spiReadRegister
uint8_t spiReadRegister(uint8_t reg)
Definition: RH_CC110.cpp:208
RH_CC110::handleInterrupt
void handleInterrupt()
Definition: RH_CC110.cpp:158
RH_CC110::setModemRegisters
void setModemRegisters(const ModemConfig *config)
Definition: RH_CC110.cpp:447
RH_CC110::spiBurstWriteRegister
uint8_t spiBurstWriteRegister(uint8_t reg, const uint8_t *src, uint8_t len)
Definition: RH_CC110.cpp:223
RH_CC110::ModemConfig::reg_15
uint8_t reg_15
RH_CC110_REG_15_DEVIATN.
Definition: RH_CC110.h:607
RH_CC110::TransmitPowerM20dBm
@ TransmitPowerM20dBm
-20dBm
Definition: RH_CC110.h:651
RH_CC110::ModemConfig::reg_24
uint8_t reg_24
RH_CC110_REG_24_FSCAL2.
Definition: RH_CC110.h:616
RH_CC110::setModeRx
void setModeRx()
Definition: RH_CC110.cpp:369
RH_CC110::GFSK_Rb100Fd47
@ GFSK_Rb100Fd47
GFSK, Data Rate: 100kBaud, Dev: 47kHz, RX BW 325kHz, optimised for sensitivity.
Definition: RH_CC110.h:640
RHNRFSPIDriver::spiCommand
uint8_t spiCommand(uint8_t command)
Definition: RHNRFSPIDriver.cpp:31
RH_CC110::ModemConfig::reg_0c
uint8_t reg_0c
RH_CC110_REG_0C_FSCTRL0.
Definition: RH_CC110.h:603
RHGenericSPI
Base class for SPI interfaces.
Definition: RHGenericSPI.h:30
RHNRFSPIDriver::spiRead
uint8_t spiRead(uint8_t reg)
Definition: RHNRFSPIDriver.cpp:48
RH_CC110::sleep
virtual bool sleep()
Definition: RH_CC110.cpp:358
RH_CC110::ModemConfig::reg_0b
uint8_t reg_0b
RH_CC110_REG_0B_FSCTRL1.
Definition: RH_CC110.h:602
RHGenericDriver::_rxHeaderFrom
volatile uint8_t _rxHeaderFrom
FROM header in the last received mesasge.
Definition: RHGenericDriver.h:265
RH_CC110::setModeTx
void setModeTx()
Definition: RH_CC110.cpp:380
RH_CC110::TransmitPowerM15dBm
@ TransmitPowerM15dBm
-15dBm
Definition: RH_CC110.h:652
RH_CC110::recv
virtual bool recv(uint8_t *buf, uint8_t *len)
Definition: RH_CC110.cpp:286
RH_CC110::GFSK_Rb10Fd19
@ GFSK_Rb10Fd19
GFSK, Data Rate: 10kBaud, Dev: 19kHz, RX BW 100kHz, optimised for sensitivity.
Definition: RH_CC110.h:637
RH_CC110::ModemConfig::reg_2c
uint8_t reg_2c
RH_CC110_REG_2C_TEST2.
Definition: RH_CC110.h:619
RH_CC110::GFSK_Rb4_8Fd25_4
@ GFSK_Rb4_8Fd25_4
GFSK, Data Rate: 4.8kBaud, Dev: 25.4kHz, RX BW 100kHz, optimised for sensitivity.
Definition: RH_CC110.h:636
RHGenericDriver::_lastRssi
volatile int16_t _lastRssi
The value of the last received RSSI value, in some transport specific units.
Definition: RHGenericDriver.h:286
RH_CC110::RH_CC110
RH_CC110(uint8_t slaveSelectPin=SS, uint8_t interruptPin=2, bool is27MHz=false, RHGenericSPI &spi=hardware_spi)
Definition: RH_CC110.cpp:67
RH_CC110::printRegisters
bool printRegisters()
Definition: RH_CC110.cpp:228
RHGenericDriver::_rxHeaderTo
volatile uint8_t _rxHeaderTo
TO header in the last received mesasge.
Definition: RHGenericDriver.h:262
RH_CC110::TransmitPower
TransmitPower
Definition: RH_CC110.h:648
RH_CC110::ModemConfig::reg_23
uint8_t reg_23
RH_CC110_REG_23_FSCAL3.
Definition: RH_CC110.h:615
RHGenericDriver::_txHeaderFrom
uint8_t _txHeaderFrom
FROM header to send in all messages.
Definition: RHGenericDriver.h:277
RH_CC110::ModemConfig::reg_19
uint8_t reg_19
RH_CC110_REG_19_FOCCFG.
Definition: RH_CC110.h:608
RH_CC110::spiBurstReadRegister
uint8_t spiBurstReadRegister(uint8_t reg)
Definition: RH_CC110.cpp:213
RH_CC110::spiWriteRegister
uint8_t spiWriteRegister(uint8_t reg, uint8_t val)
Definition: RH_CC110.cpp:218
RH_CC110::ModemConfig::reg_2e
uint8_t reg_2e
RH_CC110_REG_2E_TEST0.
Definition: RH_CC110.h:621
RHGenericDriver::_thisAddress
uint8_t _thisAddress
This node id.
Definition: RHGenericDriver.h:256
RH_CC110::clearRxBuf
void clearRxBuf()
Clear our local receive buffer.
Definition: RH_CC110.cpp:278
RH_CC110::setIs27MHz
void setIs27MHz(bool is27MHz=true)
Definition: RH_CC110.cpp:151
RHNRFSPIDriver::init
bool init()
Definition: RHNRFSPIDriver.cpp:15
RH_CC110::TransmitPower5dBm
@ TransmitPower5dBm
5dBm
Definition: RH_CC110.h:655
RH_CC110::ModemConfig::reg_10
uint8_t reg_10
RH_CC110_REG_10_MDMCFG4.
Definition: RH_CC110.h:604
RHGenericDriver::_promiscuous
bool _promiscuous
Whether the transport is in promiscuous mode.
Definition: RHGenericDriver.h:259
RHNRFSPIDriver::spiBurstWrite
uint8_t spiBurstWrite(uint8_t reg, const uint8_t *src, uint8_t len)
Definition: RHNRFSPIDriver.cpp:109
RHGenericDriver::_rxHeaderFlags
volatile uint8_t _rxHeaderFlags
FLAGS header in the last received mesasge.
Definition: RHGenericDriver.h:271
RH_CC110::ModemConfig::reg_1c
uint8_t reg_1c
RH_CC110_REG_1C_AGCCTRL1.
Definition: RH_CC110.h:611
RH_CC110::ModemConfigChoice
ModemConfigChoice
Definition: RH_CC110.h:632
RH_CC110::ModemConfig
Defines register configuration values for a desired modulation.
Definition: RH_CC110.h:600
RH_CC110::GFSK_Rb38_4Fd20
@ GFSK_Rb38_4Fd20
GFSK, Data Rate: 38.4kBaud, Dev: 20kHz, RX BW 100kHz, optimised for sensitivity.
Definition: RH_CC110.h:638
RH_CC110::validateRxBuf
void validateRxBuf()
Definition: RH_CC110.cpp:250
RH_CC110::send
virtual bool send(const uint8_t *data, uint8_t len)
Definition: RH_CC110.cpp:305
RH_CC110::setSyncWords
void setSyncWords(const uint8_t *syncWords, uint8_t len)
Definition: RH_CC110.cpp:486
RHGenericDriver::RHModeSleep
@ RHModeSleep
Transport hardware is in low power sleep mode (if supported)
Definition: RHGenericDriver.h:51
RH_CC110
Send and receive unaddressed, unreliable, datagrams by Texas Instruments CC110L and compatible transc...
Definition: RH_CC110.h:592
RH_CC110::setModemConfig
bool setModemConfig(ModemConfigChoice index)
Definition: RH_CC110.cpp:473
RHNRFSPIDriver::spiUsingInterrupt
void spiUsingInterrupt(uint8_t interruptNumber)
Definition: RHNRFSPIDriver.cpp:133
RH_CC110::statusRead
uint8_t statusRead()
Definition: RH_CC110.cpp:389
RH_CC110::ModemConfig::reg_12
uint8_t reg_12
RH_CC110_REG_12_MDMCFG2.
Definition: RH_CC110.h:606
RH_CC110::TransmitPower7dBm
@ TransmitPower7dBm
7dBm
Definition: RH_CC110.h:656
RH_CC110::ModemConfig::reg_1a
uint8_t reg_1a
RH_CC110_REG_1A_BSCFG.
Definition: RH_CC110.h:609
RH_CC110::available
virtual bool available()
Definition: RH_CC110.cpp:268
RH_CC110::ModemConfig::reg_25
uint8_t reg_25
RH_CC110_REG_25_FSCAL1.
Definition: RH_CC110.h:617
RH_CC110::init
virtual bool init()
Definition: RH_CC110.cpp:77
RHGenericDriver::_txHeaderId
uint8_t _txHeaderId
ID header to send in all messages.
Definition: RHGenericDriver.h:280
RH_CC110::ModemConfig::reg_22
uint8_t reg_22
RH_CC110_REG_22_FREND0.
Definition: RH_CC110.h:614
RH_CC110::GFSK_Rb76_8Fd32
@ GFSK_Rb76_8Fd32
GFSK, Data Rate: 76.8kBaud, Dev: 32kHz, RX BW 232kHz, optimised for sensitivity.
Definition: RH_CC110.h:639
RHGenericDriver::_txHeaderTo
uint8_t _txHeaderTo
TO header to send in all messages.
Definition: RHGenericDriver.h:274
RH_CC110::ModemConfig::reg_2d
uint8_t reg_2d
RH_CC110_REG_2D_TEST1.
Definition: RH_CC110.h:620
RH_CC110::ModemConfig::reg_1d
uint8_t reg_1d
RH_CC110_REG_1D_AGCCTRL0.
Definition: RH_CC110.h:612
RHGenericDriver::_txHeaderFlags
uint8_t _txHeaderFlags
FLAGS header to send in all messages.
Definition: RHGenericDriver.h:283
RH_CC110::TransmitPower0dBm
@ TransmitPower0dBm
0dBm
Definition: RH_CC110.h:654
RH_CC110::setFrequency
bool setFrequency(float centre)
Definition: RH_CC110.cpp:428
RH_CC110::TransmitPowerM30dBm
@ TransmitPowerM30dBm
-30dBm
Definition: RH_CC110.h:650
RHNRFSPIDriver
Base class for RadioHead drivers that use the SPI bus to communicate with its NRF family transport ha...
Definition: RHNRFSPIDriver.h:33
RHNRFSPIDriver::spiWrite
uint8_t spiWrite(uint8_t reg, uint8_t val)
Definition: RHNRFSPIDriver.cpp:66
RH_CC110::GFSK_Rb1_2Fd5_2
@ GFSK_Rb1_2Fd5_2
GFSK, Data Rate: 1.2kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity.
Definition: RH_CC110.h:634
RH_CC110::GFSK_Rb2_4Fd5_2
@ GFSK_Rb2_4Fd5_2
GFSK, Data Rate: 2.4kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity.
Definition: RH_CC110.h:635
RH_CC110::GFSK_Rb250Fd127
@ GFSK_Rb250Fd127
GFSK, Data Rate: 250kBaud, Dev: 127kHz, RX BW 540kHz, optimised for sensitivity.
Definition: RH_CC110.h:641
RHGenericDriver::_rxHeaderId
volatile uint8_t _rxHeaderId
ID header in the last received mesasge.
Definition: RHGenericDriver.h:268
RH_CC110::TransmitPowerM10dBm
@ TransmitPowerM10dBm
-10dBm
Definition: RH_CC110.h:653
RH_CC110::ModemConfig::reg_26
uint8_t reg_26
RH_CC110_REG_26_FSCAL0.
Definition: RH_CC110.h:618
RHNRFSPIDriver::spiBurstRead
uint8_t spiBurstRead(uint8_t reg, uint8_t *dest, uint8_t len)
Definition: RHNRFSPIDriver.cpp:90
RHGenericDriver::RHModeIdle
@ RHModeIdle
Transport is idle.
Definition: RHGenericDriver.h:52
RH_CC110::setModeIdle
void setModeIdle()
Definition: RH_CC110.cpp:348
RH_CC110::setTxPower
bool setTxPower(TransmitPower power)
Definition: RH_CC110.cpp:411
RHGenericDriver::_mode
volatile RHMode _mode
The current transport operating mode.
Definition: RHGenericDriver.h:253
RHGenericDriver::RHModeTx
@ RHModeTx
Transport is in the process of transmitting a message.
Definition: RHGenericDriver.h:53
RH_CC110::TransmitPower10dBm
@ TransmitPower10dBm
10dBm
Definition: RH_CC110.h:657
RH_CC110::maxMessageLength
virtual uint8_t maxMessageLength()
Definition: RH_CC110.cpp:330
RH_CC110::setPaTable
void setPaTable(uint8_t *patable, uint8_t patablesize)
Definition: RH_CC110.cpp:423
RH_CC110::ModemConfig::reg_1b
uint8_t reg_1b
RH_CC110_REG_1B_AGCCTRL2.
Definition: RH_CC110.h:610
RH_CC110::ModemConfig::reg_11
uint8_t reg_11
RH_CC110_REG_11_MDMCFG3.
Definition: RH_CC110.h:605
RH_CC110::handleOverFlows
void handleOverFlows(uint8_t status)
Definition: RH_CC110.cpp:335
RH_CC110::ModemConfig::reg_21
uint8_t reg_21
RH_CC110_REG_21_FREND1.
Definition: RH_CC110.h:613
RHGenericDriver::RHModeRx
@ RHModeRx
Transport is in the process of receiving a message.
Definition: RHGenericDriver.h:54
RHGenericDriver::waitCAD
virtual bool waitCAD()
Definition: RHGenericDriver.cpp:72
RH_CC110::waitPacketSent
virtual bool waitPacketSent()
Definition: RH_CC110.cpp:397