diff options
| author | manuel <manuel@mausz.at> | 2020-03-17 12:18:56 +0100 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2020-03-17 12:18:56 +0100 |
| commit | 0553b9907f912e56a2cd2a08b03a83ce6f2a75c6 (patch) | |
| tree | 45ed1908a50168f8420f13866cfd68386d0f2c78 /martin/door/src/cc1101.cpp | |
| parent | f0ecb4d38fff522c72905a8551355ca925381fa3 (diff) | |
| download | arduino-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.cpp | 395 |
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 | |||
| 11 | static 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 | |||
| 56 | static const uint8_t patable_power_315[8] = { 0x17, 0x1D, 0x26, 0x69, 0x51, 0x86, 0xCC, 0xC3 }; | ||
| 57 | static const uint8_t patable_power_434[8] = { 0x6C, 0x1C, 0x06, 0x3A, 0x51, 0x85, 0xC8, 0xC0 }; | ||
| 58 | static const uint8_t patable_power_868[8] = { 0x00, 0x17, 0x1D, 0x26, 0x50, 0x86, 0xCD, 0xC0 }; | ||
| 59 | static const uint8_t patable_power_915[8] = { 0x0B, 0x1B, 0x6D, 0x67, 0x50, 0x85, 0xC9, 0xC1 }; | ||
| 60 | |||
| 61 | // 5 dB default value for factory reset | ||
| 62 | static const uint8_t patable_power_ook[8] = { 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
| 63 | |||
| 64 | enum 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 | |||
| 93 | CC1101::~CC1101() | ||
| 94 | { | ||
| 95 | if (_init_done) | ||
| 96 | (void)idle(); | ||
| 97 | } | ||
| 98 | |||
| 99 | #if !defined(LINUX_ARCH_RASPBERRYPI) | ||
| 100 | void 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 | |||
| 107 | void CC1101::select() | ||
| 108 | { | ||
| 109 | digitalWrite(_ss, LOW); | ||
| 110 | } | ||
| 111 | |||
| 112 | void CC1101::deselect() | ||
| 113 | { | ||
| 114 | digitalWrite(_ss, HIGH); | ||
| 115 | } | ||
| 116 | |||
| 117 | bool 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 | |||
| 125 | uint8_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 | |||
| 138 | bool 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 | |||
| 167 | void 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 | |||
| 183 | uint8_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 | |||
| 200 | uint8_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 | |||
| 217 | void 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 | |||
| 235 | void 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 | |||
| 253 | bool 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 | |||
| 278 | bool 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 | |||
| 330 | bool CC1101::register_check() | ||
| 331 | { | ||
| 332 | return (spi_read_register(PKTCTRL0) == cc1101_init[PKTCTRL0] | ||
| 333 | && spi_read_register(IOCFG2) == cc1101_init[IOCFG2]); | ||
| 334 | } | ||
| 335 | |||
| 336 | bool 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 | |||
| 347 | void CC1101::setGDO0(int value) | ||
| 348 | { | ||
| 349 | digitalWrite(_gdo0, value); | ||
| 350 | } | ||
| 351 | |||
| 352 | bool 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 | |||
| 362 | void CC1101::wakeup() | ||
| 363 | { | ||
| 364 | digitalWrite(_ss, LOW); | ||
| 365 | delayMicroseconds(10); | ||
| 366 | digitalWrite(_ss, HIGH); | ||
| 367 | delayMicroseconds(10); | ||
| 368 | idle(); | ||
| 369 | } | ||
| 370 | |||
| 371 | void CC1101::powerdown() | ||
| 372 | { | ||
| 373 | idle(); | ||
| 374 | spi_write_strobe(SPWD); | ||
| 375 | } | ||
| 376 | |||
| 377 | void 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 | |||
| 386 | void 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 | } | ||
