summaryrefslogtreecommitdiffstats
path: root/martin/door/src/cc1101.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-03-17 12:18:56 +0100
committermanuel <manuel@mausz.at>2020-03-17 12:18:56 +0100
commit0553b9907f912e56a2cd2a08b03a83ce6f2a75c6 (patch)
tree45ed1908a50168f8420f13866cfd68386d0f2c78 /martin/door/src/cc1101.cpp
parentf0ecb4d38fff522c72905a8551355ca925381fa3 (diff)
downloadarduino-0553b9907f912e56a2cd2a08b03a83ce6f2a75c6.tar.gz
arduino-0553b9907f912e56a2cd2a08b03a83ce6f2a75c6.tar.bz2
arduino-0553b9907f912e56a2cd2a08b03a83ce6f2a75c6.zip
Add martin/door
Diffstat (limited to 'martin/door/src/cc1101.cpp')
-rw-r--r--martin/door/src/cc1101.cpp395
1 files changed, 395 insertions, 0 deletions
diff --git a/martin/door/src/cc1101.cpp b/martin/door/src/cc1101.cpp
new file mode 100644
index 0000000..86129db
--- /dev/null
+++ b/martin/door/src/cc1101.cpp
@@ -0,0 +1,395 @@
1#include <Arduino.h>
2#if defined(LINUX_ARCH_RASPBERRYPI)
3#include <wiringPi.h>
4#include <wiringPiSPI.h>
5#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
6#include <SPI.h>
7#endif
8
9#include "cc1101.h"
10
11static const uint8_t cc1101_init[] = {
12 // IDX NAME RESET COMMENT
13 0x0D, // 00 IOCFG2 29 GDO2 as serial output
14 0x2E, // 01 IOCFG1 Tri-State
15 0x2E, // 02 IOCFG0 3F GDO0 for input
16 0x47, // 03 FIFOTHR RX filter bandwidth = 325 kHz, FIFOTHR = 0x47
17 0xD3, // 04 SYNC1
18 0x91, // 05 SYNC0
19 0x3D, // 06 PKTLEN 0F
20 0x04, // 07 PKTCTRL1
21 0x32, // 08 PKTCTRL0 45
22 0x00, // 09 ADDR
23 0x00, // 0A CHANNR
24 0x06, // 0B FSCTRL1 0F 152kHz IF Frquency
25 0x00, // 0C FSCTRL0
26 0x10, // 0D FREQ2 1E Freq #12 Reg Pos 0C
27 0xB0, // 0E FREQ1 C4 Reg Pos 0D
28 0x71, // 0F FREQ0 EC Reg Pos 0E
29 0x57, // 10 MDMCFG4 8C bWidth 325kHz
30 0xC4, // 11 MDMCFG3 22 DataRate
31 0x30, // 12 MDMCFG2 02 Modulation: ASK
32 0x23, // 13 MDMCFG1 22
33 0xb9, // 14 MDMCFG0 F8 ChannelSpace: 350kHz
34 0x00, // 15 DEVIATN 47
35 0x07, // 16 MCSM2 07
36 0x00, // 17 MCSM1 30 Bit 3:2 RXOFF_MODE: Select what should happen when a packet has been received: 0 = IDLE 3 = Stay in RX ####
37 0x18, // 18 MCSM0 04 Calibration: RX/TX->IDLE
38 0x14, // 19 FOCCFG 36
39 0x6C, // 1A BSCFG
40 0x07, // 1B AGCCTRL2 03 42 dB instead of 33dB
41 0x00, // 1C AGCCTRL1 40
42 0x91, // 1D AGCCTRL0 91 8dB decision boundery
43 0x87, // 1E WOREVT1
44 0x6B, // 1F WOREVT0
45 0xF8, // 20 WORCTRL
46 0xB6, // 21 FREND1 B6 RX filter bandwidth > 101 kHz, FREND1 = 0xB6
47 0x11, // 22 FREND0 16 0x11 for no PA ramping
48 0xE9, // 23 FSCAL3 A9 E9 ??
49 0x2A, // 24 FSCAL2 0A
50 0x00, // 25 FSCAL1 20 19 ??
51 0x1F, // 26 FSCAL0 0D
52 0x41, // 27 RCCTRL1
53 0x00, // 28 RCCTRL0
54};
55
56static const uint8_t patable_power_315[8] = { 0x17, 0x1D, 0x26, 0x69, 0x51, 0x86, 0xCC, 0xC3 };
57static const uint8_t patable_power_434[8] = { 0x6C, 0x1C, 0x06, 0x3A, 0x51, 0x85, 0xC8, 0xC0 };
58static const uint8_t patable_power_868[8] = { 0x00, 0x17, 0x1D, 0x26, 0x50, 0x86, 0xCD, 0xC0 };
59static const uint8_t patable_power_915[8] = { 0x0B, 0x1B, 0x6D, 0x67, 0x50, 0x85, 0xC9, 0xC1 };
60
61// 5 dB default value for factory reset
62static const uint8_t patable_power_ook[8] = { 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
63
64enum MarcState
65 : uint8_t
66{
67 STATE_SLEEP = 0x00,
68 STATE_IDLE = 0x01,
69 STATE_XOFF = 0x02,
70 STATE_VCOON_MC = 0x03,
71 STATE_REGON_MC = 0x04,
72 STATE_MANCAL = 0x05,
73 STATE_VCOON = 0x06,
74 STATE_REGCON = 0x07,
75 STATE_STARTCAL = 0x08,
76 STATE_BWBOOST = 0x09,
77 STATE_FS_LOCK = 0x0A,
78 STATE_IFADCON = 0x0B,
79 STATE_ENDCAL = 0x0C,
80 STATE_RX = 0x0D,
81 STATE_RX_END = 0x0E,
82 STATE_TX_RST = 0x0F,
83 STATE_TXRX_SWITCH = 0x10,
84 STATE_RXFIFO_OVERFLOW = 0x11,
85 STATE_FSTXON = 0x12,
86 STATE_TX = 0x13,
87 STATE_TX_END = 0x14,
88 STATE_RXTX_SWITCH = 0x15,
89 STATE_TXFIFO_UNDERFLOW = 0x16,
90 STATE_MASK = 0x1F,
91};
92
93CC1101::~CC1101()
94{
95 if (_init_done)
96 (void)idle();
97}
98
99#if !defined(LINUX_ARCH_RASPBERRYPI)
100void CC1101::set_spi_pins(uint8_t mosi, uint8_t miso, uint8_t sck)
101{
102 _mosi = mosi;
103 _miso = miso;
104 _sck = sck;
105}
106
107void CC1101::select()
108{
109 digitalWrite(_ss, LOW);
110}
111
112void CC1101::deselect()
113{
114 digitalWrite(_ss, HIGH);
115}
116
117bool CC1101::wait_MISO()
118{
119 uint8_t miso_count = 255;
120 while(digitalRead(_miso) == HIGH && miso_count > 0)
121 --miso_count;
122 return (miso_count > 0);
123}
124
125uint8_t CC1101::spi_putc(const uint8_t value)
126{
127#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
128 return SPI.transfer(value);
129#else
130 SPDR = value;
131 asm volatile("nop");
132 while(!(SPSR & _BV(SPIF)));
133 return SPDR;
134#endif
135}
136#endif
137
138bool CC1101::spi_begin()
139{
140#if defined(LINUX_ARCH_RASPBERRYPI)
141 //4MHz SPI speed
142 return (wiringPiSPISetup(0, 4000000) >= 0);
143#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
144 pinMode(_ss, OUTPUT);
145 deselect();
146
147 SPI.setDataMode(SPI_MODE0);
148 SPI.setBitOrder(MSBFIRST);
149 SPI.begin();
150 SPI.setClockDivider(SPI_CLOCK_DIV4);
151#else
152 pinMode(_ss, OUTPUT);
153 deselect();
154
155 pinMode(_sck, OUTPUT);
156 pinMode(_mosi, OUTPUT);
157 pinMode(_miso, INPUT);
158
159 // SPI init
160 SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4
161 digitalWrite(_sck, HIGH);
162 digitalWrite(_mosi, LOW);
163#endif
164 return true;
165}
166
167void CC1101::spi_write_register(Register spi_instr, uint8_t value)
168{
169#if defined(LINUX_ARCH_RASPBERRYPI)
170 uint8_t tbuf[2] = {0};
171 tbuf[0] = spi_instr | WRITE_SINGLE_BYTE;
172 tbuf[1] = value;
173 wiringPiSPIDataRW(0, tbuf, 2);
174#else
175 select();
176 wait_MISO();
177 spi_putc(spi_instr | WRITE_SINGLE_BYTE);
178 spi_putc(value);
179 deselect();
180#endif
181}
182
183uint8_t CC1101::spi_read_register(Register spi_instr)
184{
185#if defined(LINUX_ARCH_RASPBERRYPI)
186 uint8_t rbuf[2] = {0};
187 rbuf[0] = spi_instr | READ_SINGLE_BYTE;
188 wiringPiSPIDataRW(0, rbuf, 2);
189 return rbuf[1];
190#else
191 select();
192 wait_MISO();
193 spi_putc(spi_instr | READ_SINGLE_BYTE);
194 uint8_t ret = spi_putc(0x00);
195 deselect();
196 return ret;
197#endif
198}
199
200uint8_t CC1101::spi_write_strobe(Strobe spi_instr)
201{
202#if defined(LINUX_ARCH_RASPBERRYPI)
203 uint8_t tbuf[1] = {0};
204 tbuf[0] = spi_instr;
205 wiringPiSPIDataRW(0, tbuf, 1);
206 return tbuf[0];
207#else
208 select();
209 wait_MISO();
210 uint8_t ret = spi_putc(spi_instr);
211 wait_MISO();
212 deselect();
213 return ret;
214#endif
215}
216
217void CC1101::spi_read_burst(SPI_RW spi_instr, uint8_t *pArr, uint8_t len)
218{
219#if defined(LINUX_ARCH_RASPBERRYPI)
220 uint8_t rbuf[len + 1];
221 rbuf[0] = spi_instr | READ_BURST;
222 wiringPiSPIDataRW(0, rbuf, len + 1);
223 for (uint8_t i = 0; i < len ;i++ )
224 pArr[i] = rbuf[i + 1];
225#else
226 select();
227 wait_MISO();
228 spi_putc(spi_instr | READ_BURST);
229 for (uint8_t i = 0; i < len ;i++ )
230 pArr[i] = spi_putc(0x00);
231 deselect();
232#endif
233}
234
235void CC1101::spi_write_burst(SPI_RW spi_instr, const uint8_t *pArr, uint8_t len)
236{
237#if defined(LINUX_ARCH_RASPBERRYPI)
238 uint8_t tbuf[len + 1];
239 tbuf[0] = spi_instr | WRITE_BURST;
240 for (uint8_t i = 0; i < len; i++)
241 tbuf[i + 1] = pArr[i];
242 wiringPiSPIDataRW(0, tbuf, len + 1);
243#else
244 select();
245 wait_MISO();
246 spi_putc(spi_instr | WRITE_BURST);
247 for (uint8_t i = 0; i < len; i++)
248 spi_putc(pArr[i]);
249 deselect();
250#endif
251}
252
253bool CC1101::setup()
254{
255#if defined(LINUX_ARCH_RASPBERRYPI)
256 wiringPiSetup();
257#endif
258 pinMode(_gdo0, OUTPUT);
259 digitalWrite(_gdo0, LOW);
260 pinMode(_gdo2, INPUT);
261
262 spi_begin();
263 reset();
264
265 //uint8_t partnum = spi_read_register(PARTNUM);
266 uint8_t version = spi_read_register(VERSION);
267 //checks if valid Chip ID is found. Usualy 0x03 or 0x14. if not -> abort
268 if (version == 0x00 || version == 0xFF)
269 return false;
270
271 spi_write_burst(WRITE_BURST, cc1101_init, sizeof(cc1101_init));
272 if (!register_check())
273 return false;
274 _init_done = true;
275 return true;
276}
277
278bool CC1101::setISM(CC1101::ISM_FREQ ism_freq)
279{
280 uint8_t freq2, freq1, freq0;
281 const uint8_t *patable = patable_power_ook;
282 switch(ism_freq)
283 {
284 case CC1101::FREQ_315MHZ:
285 freq2 = 0x0C;
286 freq1 = 0x1D;
287 freq0 = 0x89;
288 //patable = patable_power_315;
289 break;
290 case CC1101::FREQ_434MHZ:
291 freq2 = 0x10;
292 freq1 = 0xB0;
293 freq0 = 0x71;
294 //patable = patable_power_434;
295 break;
296 case CC1101::FREQ_868MHZ:
297 freq2 = 0x21;
298 freq1 = 0x65;
299 freq0 = 0x6A;
300 //patable = patable_power_868;
301 break;
302 case CC1101::FREQ_915MHZ:
303 freq2 = 0x23;
304 freq1 = 0x31;
305 freq0 = 0x3B;
306 //patable = patable_power_915;
307 break;
308 /*
309 case CC1101::FREQ_2430MHZ:
310 freq2 = 0x5D;
311 freq1 = 0x76;
312 freq0 = 0x27;
313 //patable = patable_power_2430;
314 break;
315 */
316 default:
317 return false;
318 }
319
320 spi_write_burst(PATABLE_BURST, patable, 8);
321
322 // stores the new freq setting for defined ISM band
323 spi_write_register(FREQ2, freq2);
324 spi_write_register(FREQ1, freq1);
325 spi_write_register(FREQ0, freq0);
326
327 return true;
328}
329
330bool CC1101::register_check()
331{
332 return (spi_read_register(PKTCTRL0) == cc1101_init[PKTCTRL0]
333 && spi_read_register(IOCFG2) == cc1101_init[IOCFG2]);
334}
335
336bool CC1101::transmit()
337{
338 idle();
339 setGDO0(LOW);
340 spi_write_strobe(STX);
341 uint8_t maxloop = 255;
342 while (--maxloop && (spi_read_register(MARCSTATE) & STATE_MASK) != STATE_TX)
343 delay(1);
344 return (maxloop != 0);
345}
346
347void CC1101::setGDO0(int value)
348{
349 digitalWrite(_gdo0, value);
350}
351
352bool CC1101::receive()
353{
354 idle();
355 spi_write_strobe(SRX);
356 uint8_t maxloop = 255;
357 while (--maxloop && (spi_read_register(MARCSTATE) & STATE_MASK) != STATE_RX)
358 delay(1);
359 return (maxloop != 0);
360}
361
362void CC1101::wakeup()
363{
364 digitalWrite(_ss, LOW);
365 delayMicroseconds(10);
366 digitalWrite(_ss, HIGH);
367 delayMicroseconds(10);
368 idle();
369}
370
371void CC1101::powerdown()
372{
373 idle();
374 spi_write_strobe(SPWD);
375}
376
377void CC1101::idle()
378{
379 spi_write_strobe(SIDLE);
380 uint8_t maxloop = 0xff;
381 while (--maxloop && (spi_read_register(MARCSTATE) & STATE_MASK) != STATE_IDLE)
382 delay(1);
383 delayMicroseconds(100);
384}
385
386void CC1101::reset(void)
387{
388 digitalWrite(_ss, LOW);
389 delayMicroseconds(10);
390 digitalWrite(_ss, HIGH);
391 delayMicroseconds(40);
392
393 spi_write_strobe(SRES);
394 delay(1);
395}