From 0553b9907f912e56a2cd2a08b03a83ce6f2a75c6 Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 17 Mar 2020 12:18:56 +0100 Subject: Add martin/door --- martin/door/src/cc1101.cpp | 395 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 martin/door/src/cc1101.cpp (limited to 'martin/door/src/cc1101.cpp') 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 @@ +#include +#if defined(LINUX_ARCH_RASPBERRYPI) +#include +#include +#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#include +#endif + +#include "cc1101.h" + +static const uint8_t cc1101_init[] = { + // IDX NAME RESET COMMENT + 0x0D, // 00 IOCFG2 29 GDO2 as serial output + 0x2E, // 01 IOCFG1 Tri-State + 0x2E, // 02 IOCFG0 3F GDO0 for input + 0x47, // 03 FIFOTHR RX filter bandwidth = 325 kHz, FIFOTHR = 0x47 + 0xD3, // 04 SYNC1 + 0x91, // 05 SYNC0 + 0x3D, // 06 PKTLEN 0F + 0x04, // 07 PKTCTRL1 + 0x32, // 08 PKTCTRL0 45 + 0x00, // 09 ADDR + 0x00, // 0A CHANNR + 0x06, // 0B FSCTRL1 0F 152kHz IF Frquency + 0x00, // 0C FSCTRL0 + 0x10, // 0D FREQ2 1E Freq #12 Reg Pos 0C + 0xB0, // 0E FREQ1 C4 Reg Pos 0D + 0x71, // 0F FREQ0 EC Reg Pos 0E + 0x57, // 10 MDMCFG4 8C bWidth 325kHz + 0xC4, // 11 MDMCFG3 22 DataRate + 0x30, // 12 MDMCFG2 02 Modulation: ASK + 0x23, // 13 MDMCFG1 22 + 0xb9, // 14 MDMCFG0 F8 ChannelSpace: 350kHz + 0x00, // 15 DEVIATN 47 + 0x07, // 16 MCSM2 07 + 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 #### + 0x18, // 18 MCSM0 04 Calibration: RX/TX->IDLE + 0x14, // 19 FOCCFG 36 + 0x6C, // 1A BSCFG + 0x07, // 1B AGCCTRL2 03 42 dB instead of 33dB + 0x00, // 1C AGCCTRL1 40 + 0x91, // 1D AGCCTRL0 91 8dB decision boundery + 0x87, // 1E WOREVT1 + 0x6B, // 1F WOREVT0 + 0xF8, // 20 WORCTRL + 0xB6, // 21 FREND1 B6 RX filter bandwidth > 101 kHz, FREND1 = 0xB6 + 0x11, // 22 FREND0 16 0x11 for no PA ramping + 0xE9, // 23 FSCAL3 A9 E9 ?? + 0x2A, // 24 FSCAL2 0A + 0x00, // 25 FSCAL1 20 19 ?? + 0x1F, // 26 FSCAL0 0D + 0x41, // 27 RCCTRL1 + 0x00, // 28 RCCTRL0 +}; + +static const uint8_t patable_power_315[8] = { 0x17, 0x1D, 0x26, 0x69, 0x51, 0x86, 0xCC, 0xC3 }; +static const uint8_t patable_power_434[8] = { 0x6C, 0x1C, 0x06, 0x3A, 0x51, 0x85, 0xC8, 0xC0 }; +static const uint8_t patable_power_868[8] = { 0x00, 0x17, 0x1D, 0x26, 0x50, 0x86, 0xCD, 0xC0 }; +static const uint8_t patable_power_915[8] = { 0x0B, 0x1B, 0x6D, 0x67, 0x50, 0x85, 0xC9, 0xC1 }; + +// 5 dB default value for factory reset +static const uint8_t patable_power_ook[8] = { 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +enum MarcState + : uint8_t +{ + STATE_SLEEP = 0x00, + STATE_IDLE = 0x01, + STATE_XOFF = 0x02, + STATE_VCOON_MC = 0x03, + STATE_REGON_MC = 0x04, + STATE_MANCAL = 0x05, + STATE_VCOON = 0x06, + STATE_REGCON = 0x07, + STATE_STARTCAL = 0x08, + STATE_BWBOOST = 0x09, + STATE_FS_LOCK = 0x0A, + STATE_IFADCON = 0x0B, + STATE_ENDCAL = 0x0C, + STATE_RX = 0x0D, + STATE_RX_END = 0x0E, + STATE_TX_RST = 0x0F, + STATE_TXRX_SWITCH = 0x10, + STATE_RXFIFO_OVERFLOW = 0x11, + STATE_FSTXON = 0x12, + STATE_TX = 0x13, + STATE_TX_END = 0x14, + STATE_RXTX_SWITCH = 0x15, + STATE_TXFIFO_UNDERFLOW = 0x16, + STATE_MASK = 0x1F, +}; + +CC1101::~CC1101() +{ + if (_init_done) + (void)idle(); +} + +#if !defined(LINUX_ARCH_RASPBERRYPI) +void CC1101::set_spi_pins(uint8_t mosi, uint8_t miso, uint8_t sck) +{ + _mosi = mosi; + _miso = miso; + _sck = sck; +} + +void CC1101::select() +{ + digitalWrite(_ss, LOW); +} + +void CC1101::deselect() +{ + digitalWrite(_ss, HIGH); +} + +bool CC1101::wait_MISO() +{ + uint8_t miso_count = 255; + while(digitalRead(_miso) == HIGH && miso_count > 0) + --miso_count; + return (miso_count > 0); +} + +uint8_t CC1101::spi_putc(const uint8_t value) +{ +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) + return SPI.transfer(value); +#else + SPDR = value; + asm volatile("nop"); + while(!(SPSR & _BV(SPIF))); + return SPDR; +#endif +} +#endif + +bool CC1101::spi_begin() +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + //4MHz SPI speed + return (wiringPiSPISetup(0, 4000000) >= 0); +#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) + pinMode(_ss, OUTPUT); + deselect(); + + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + SPI.begin(); + SPI.setClockDivider(SPI_CLOCK_DIV4); +#else + pinMode(_ss, OUTPUT); + deselect(); + + pinMode(_sck, OUTPUT); + pinMode(_mosi, OUTPUT); + pinMode(_miso, INPUT); + + // SPI init + SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 + digitalWrite(_sck, HIGH); + digitalWrite(_mosi, LOW); +#endif + return true; +} + +void CC1101::spi_write_register(Register spi_instr, uint8_t value) +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + uint8_t tbuf[2] = {0}; + tbuf[0] = spi_instr | WRITE_SINGLE_BYTE; + tbuf[1] = value; + wiringPiSPIDataRW(0, tbuf, 2); +#else + select(); + wait_MISO(); + spi_putc(spi_instr | WRITE_SINGLE_BYTE); + spi_putc(value); + deselect(); +#endif +} + +uint8_t CC1101::spi_read_register(Register spi_instr) +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + uint8_t rbuf[2] = {0}; + rbuf[0] = spi_instr | READ_SINGLE_BYTE; + wiringPiSPIDataRW(0, rbuf, 2); + return rbuf[1]; +#else + select(); + wait_MISO(); + spi_putc(spi_instr | READ_SINGLE_BYTE); + uint8_t ret = spi_putc(0x00); + deselect(); + return ret; +#endif +} + +uint8_t CC1101::spi_write_strobe(Strobe spi_instr) +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + uint8_t tbuf[1] = {0}; + tbuf[0] = spi_instr; + wiringPiSPIDataRW(0, tbuf, 1); + return tbuf[0]; +#else + select(); + wait_MISO(); + uint8_t ret = spi_putc(spi_instr); + wait_MISO(); + deselect(); + return ret; +#endif +} + +void CC1101::spi_read_burst(SPI_RW spi_instr, uint8_t *pArr, uint8_t len) +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + uint8_t rbuf[len + 1]; + rbuf[0] = spi_instr | READ_BURST; + wiringPiSPIDataRW(0, rbuf, len + 1); + for (uint8_t i = 0; i < len ;i++ ) + pArr[i] = rbuf[i + 1]; +#else + select(); + wait_MISO(); + spi_putc(spi_instr | READ_BURST); + for (uint8_t i = 0; i < len ;i++ ) + pArr[i] = spi_putc(0x00); + deselect(); +#endif +} + +void CC1101::spi_write_burst(SPI_RW spi_instr, const uint8_t *pArr, uint8_t len) +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + uint8_t tbuf[len + 1]; + tbuf[0] = spi_instr | WRITE_BURST; + for (uint8_t i = 0; i < len; i++) + tbuf[i + 1] = pArr[i]; + wiringPiSPIDataRW(0, tbuf, len + 1); +#else + select(); + wait_MISO(); + spi_putc(spi_instr | WRITE_BURST); + for (uint8_t i = 0; i < len; i++) + spi_putc(pArr[i]); + deselect(); +#endif +} + +bool CC1101::setup() +{ +#if defined(LINUX_ARCH_RASPBERRYPI) + wiringPiSetup(); +#endif + pinMode(_gdo0, OUTPUT); + digitalWrite(_gdo0, LOW); + pinMode(_gdo2, INPUT); + + spi_begin(); + reset(); + + //uint8_t partnum = spi_read_register(PARTNUM); + uint8_t version = spi_read_register(VERSION); + //checks if valid Chip ID is found. Usualy 0x03 or 0x14. if not -> abort + if (version == 0x00 || version == 0xFF) + return false; + + spi_write_burst(WRITE_BURST, cc1101_init, sizeof(cc1101_init)); + if (!register_check()) + return false; + _init_done = true; + return true; +} + +bool CC1101::setISM(CC1101::ISM_FREQ ism_freq) +{ + uint8_t freq2, freq1, freq0; + const uint8_t *patable = patable_power_ook; + switch(ism_freq) + { + case CC1101::FREQ_315MHZ: + freq2 = 0x0C; + freq1 = 0x1D; + freq0 = 0x89; + //patable = patable_power_315; + break; + case CC1101::FREQ_434MHZ: + freq2 = 0x10; + freq1 = 0xB0; + freq0 = 0x71; + //patable = patable_power_434; + break; + case CC1101::FREQ_868MHZ: + freq2 = 0x21; + freq1 = 0x65; + freq0 = 0x6A; + //patable = patable_power_868; + break; + case CC1101::FREQ_915MHZ: + freq2 = 0x23; + freq1 = 0x31; + freq0 = 0x3B; + //patable = patable_power_915; + break; + /* + case CC1101::FREQ_2430MHZ: + freq2 = 0x5D; + freq1 = 0x76; + freq0 = 0x27; + //patable = patable_power_2430; + break; + */ + default: + return false; + } + + spi_write_burst(PATABLE_BURST, patable, 8); + + // stores the new freq setting for defined ISM band + spi_write_register(FREQ2, freq2); + spi_write_register(FREQ1, freq1); + spi_write_register(FREQ0, freq0); + + return true; +} + +bool CC1101::register_check() +{ + return (spi_read_register(PKTCTRL0) == cc1101_init[PKTCTRL0] + && spi_read_register(IOCFG2) == cc1101_init[IOCFG2]); +} + +bool CC1101::transmit() +{ + idle(); + setGDO0(LOW); + spi_write_strobe(STX); + uint8_t maxloop = 255; + while (--maxloop && (spi_read_register(MARCSTATE) & STATE_MASK) != STATE_TX) + delay(1); + return (maxloop != 0); +} + +void CC1101::setGDO0(int value) +{ + digitalWrite(_gdo0, value); +} + +bool CC1101::receive() +{ + idle(); + spi_write_strobe(SRX); + uint8_t maxloop = 255; + while (--maxloop && (spi_read_register(MARCSTATE) & STATE_MASK) != STATE_RX) + delay(1); + return (maxloop != 0); +} + +void CC1101::wakeup() +{ + digitalWrite(_ss, LOW); + delayMicroseconds(10); + digitalWrite(_ss, HIGH); + delayMicroseconds(10); + idle(); +} + +void CC1101::powerdown() +{ + idle(); + spi_write_strobe(SPWD); +} + +void CC1101::idle() +{ + spi_write_strobe(SIDLE); + uint8_t maxloop = 0xff; + while (--maxloop && (spi_read_register(MARCSTATE) & STATE_MASK) != STATE_IDLE) + delay(1); + delayMicroseconds(100); +} + +void CC1101::reset(void) +{ + digitalWrite(_ss, LOW); + delayMicroseconds(10); + digitalWrite(_ss, HIGH); + delayMicroseconds(40); + + spi_write_strobe(SRES); + delay(1); +} -- cgit v1.2.3