|
|
@@ -0,0 +1,631 @@
|
|
|
+/*
|
|
|
+ * MiLightRadioPL1167_LT89000.cpp
|
|
|
+ *
|
|
|
+ * Created on: 31 March 2017
|
|
|
+ * Author: WoodsterDK
|
|
|
+ *
|
|
|
+ * Very inspired by:
|
|
|
+ * https://github.com/pmoscetta/authometion-milight/tree/master/Authometion-MiLight
|
|
|
+ * https://bitbucket.org/robvanderveer/lt8900lib
|
|
|
+ */
|
|
|
+
|
|
|
+#include "MiLightRadioPL1167_LT8900.h"
|
|
|
+#include <SPI.h>
|
|
|
+
|
|
|
+#define DEBUG_PRINTF
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Constructor
|
|
|
+/**************************************************************************/
|
|
|
+MiLightRadioPL1167_LT8900::MiLightRadioPL1167_LT8900(byte byCSPin, byte byResetPin, byte byPktFlag, const MiLightRadioConfig& config)
|
|
|
+ : config(config)
|
|
|
+{
|
|
|
+ _csPin = byCSPin;
|
|
|
+ _pin_pktflag = byPktFlag;
|
|
|
+
|
|
|
+ pinMode(_pin_pktflag, INPUT);
|
|
|
+
|
|
|
+ if (byResetPin > 0) // If zero then bypass hardware reset
|
|
|
+ {
|
|
|
+ pinMode(byResetPin, OUTPUT);
|
|
|
+ digitalWrite(byResetPin, LOW);
|
|
|
+ delay(200);
|
|
|
+ digitalWrite(byResetPin, HIGH);
|
|
|
+ delay(200);
|
|
|
+ }
|
|
|
+
|
|
|
+ pinMode(_csPin, OUTPUT);
|
|
|
+ digitalWrite(_csPin, HIGH);
|
|
|
+
|
|
|
+ SPI.begin();
|
|
|
+
|
|
|
+ SPI.setFrequency(1000000);
|
|
|
+ SPI.setDataMode(SPI_MODE1);
|
|
|
+ //SPI.setClockDivider(SPI_CLOCK_DIV64); // UNO and 328
|
|
|
+ SPI.setClockDivider(SPI_CLOCK_DIV128); // MEGA and FASTER
|
|
|
+ SPI.setBitOrder(MSBFIRST);
|
|
|
+
|
|
|
+ //Initialize transceiver with correct settings
|
|
|
+ vInitRadioModule(config.type);
|
|
|
+ delay(50);
|
|
|
+
|
|
|
+ // Check if HW is connected
|
|
|
+ bCheckRadioConnection();
|
|
|
+
|
|
|
+ //Reset SPI MODE to default
|
|
|
+ SPI.setDataMode(SPI_MODE0);
|
|
|
+ _waiting = false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Checks the connection to the radio module by verifying a register setting
|
|
|
+/**************************************************************************/
|
|
|
+bool MiLightRadioPL1167_LT8900::bCheckRadioConnection(void)
|
|
|
+{
|
|
|
+ int iRetValue = 0;
|
|
|
+ uint16_t value_0 = uiReadRegister(0);
|
|
|
+ uint16_t value_1 = uiReadRegister(1);
|
|
|
+
|
|
|
+ if ((value_0 == 0x6fe0) && (value_1 == 0x5681))
|
|
|
+ {
|
|
|
+ #ifdef DEBUG_PRINTF
|
|
|
+ Serial.println("Radio module running correctly...");
|
|
|
+ #endif
|
|
|
+ iRetValue = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ #ifdef DEBUG_PRINTF
|
|
|
+ Serial.println("Failed initializing the radio module...");
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+
|
|
|
+ return iRetValue;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Initialize radio module
|
|
|
+/**************************************************************************/
|
|
|
+void MiLightRadioPL1167_LT8900::vInitRadioModule(MiLightRadioType type)
|
|
|
+{
|
|
|
+ if (type == RGB_CCT)
|
|
|
+ {
|
|
|
+ bool bWriteDefaultDefault = true; // Is it okay to use the default power up values, without setting them
|
|
|
+
|
|
|
+ regWrite16(0x00, 0x6F, 0xE0, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x02, 0x66, 0x17, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x04, 0x9C, 0xC9, 7); // Recommended value by PMmicro
|
|
|
+
|
|
|
+ regWrite16(0x05, 0x66, 0x37, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x07, 0x00, 0x4C, 7); // PL1167's TX/RX Enable and Channel Register, Default channel 76
|
|
|
+ regWrite16(0x08, 0x6C, 0x90, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x09, 0x48, 0x00, 7); // PA Control register
|
|
|
+
|
|
|
+ regWrite16(0x0B, 0x00, 0x08, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x0D, 0x48, 0xBD, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x16, 0x00, 0xFF, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x18, 0x00, 0x67, 7); // Recommended value by PMmicro
|
|
|
+
|
|
|
+ regWrite16(0x1A, 0x19, 0xE0, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x1B, 0x13, 0x00, 7); // Recommended value by PMmicro
|
|
|
+
|
|
|
+ regWrite16(0x20, 0x48, 0x00, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x21, 0x3F, 0xC7, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x22, 0x20, 0x00, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x23, 0x03, 0x00, 7); // Recommended value by PMmicro
|
|
|
+
|
|
|
+ regWrite16(0x24, 0x72, 0x36, 7); // Sync R0
|
|
|
+ regWrite16(0x27, 0x18, 0x09, 7); // Sync R3
|
|
|
+ regWrite16(0x28, 0x44, 0x02, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x29, 0xB0, 0x00, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x2A, 0xFD, 0xB0, 7); // Recommended value by PMmicro
|
|
|
+
|
|
|
+ if (bWriteDefaultDefault == true)
|
|
|
+ {
|
|
|
+ regWrite16(0x01, 0x56, 0x81, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x0A, 0x7F, 0xFD, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x0C, 0x00, 0x00, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x17, 0x80, 0x05, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x19, 0x16, 0x59, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x1C, 0x18, 0x00, 7); // Recommended value by PMmicro
|
|
|
+
|
|
|
+ regWrite16(0x25, 0x00, 0x00, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x26, 0x00, 0x00, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(0x2B, 0x00, 0x0F, 7); // Recommended value by PMmicro
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if((type == RGBW) || (type == CCT) || (type == RGB) )
|
|
|
+ {
|
|
|
+ regWrite16(0, 111, 224, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(1, 86, 129, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(2, 102, 23, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(4, 156, 201, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(5, 102, 55, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(7, 0, 76, 7); // PL1167's TX/RX Enable and Channel Register
|
|
|
+ regWrite16(8, 108, 144, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(9, 72, 0, 7); // PL1167's PA Control Register
|
|
|
+ regWrite16(10, 127, 253, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(11, 0, 8, 7); // PL1167's RSSI OFF Control Register -- ???
|
|
|
+ regWrite16(12, 0, 0, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(13, 72, 189, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(22, 0, 255, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(23, 128, 5, 7); // PL1167's VCO Calibration Enable Register
|
|
|
+ regWrite16(24, 0, 103, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(25, 22, 89, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(26, 25, 224, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(27, 19, 0, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(28, 24, 0, 7); // Recommended value by PMmicro
|
|
|
+ regWrite16(32, 72, 0, 7); // PL1167's Data Configure Register: LEN_PREAMBLE = 010 -> (0xAAAAAA) 3 bytes, LEN_SYNCWORD = 01 -> 32 bits, LEN_TRAILER = 000 -> (0x05) 4 bits, TYPE_PKT_DAT = 00 -> NRZ law data, TYPE_FEC = 00 -> No FEC
|
|
|
+ regWrite16(33, 63, 199, 7); // PL1167's Delay Time Control Register 0
|
|
|
+ regWrite16(34, 32, 0, 7); // PL1167's Delay Time Control Register 1
|
|
|
+ regWrite16(35, 3, 0, 7); // PL1167's Power Management and Miscellaneous Register
|
|
|
+ regWrite16(40, 68, 2, 7); // PL1167's FIFO and SYNCWORD Threshold Register
|
|
|
+ regWrite16(41, 176, 0, 7); // PL1167's Miscellaneous Register: CRC_ON = 1 -> ON, SCR_ON = 0 -> OFF, EN_PACK_LEN = 1 -> ON, FW_TERM_TX = 1 -> ON, AUTO_ACK = 0 -> OFF, PKT_LEVEL = 0 -> PKT active high, CRC_INIT_DAT = 0
|
|
|
+ regWrite16(42, 253, 176, 7); // PL1167's SCAN RSSI Register 0
|
|
|
+ regWrite16(43, 0, 15, 7); // PL1167's SCAN RSSI Register 1
|
|
|
+ delay(200);
|
|
|
+ regWrite16(128, 0, 0, 7);
|
|
|
+ regWrite16(129, 255, 255, 7);
|
|
|
+ regWrite16(130, 0, 0, 7);
|
|
|
+ regWrite16(132, 0, 0, 7);
|
|
|
+ regWrite16(133, 255, 255, 7);
|
|
|
+ regWrite16(135, 255, 255, 7);
|
|
|
+ regWrite16(136, 0, 0, 7);
|
|
|
+ regWrite16(137, 255, 255, 7);
|
|
|
+ regWrite16(138, 0, 0, 7);
|
|
|
+ regWrite16(139, 255, 255, 7);
|
|
|
+ regWrite16(140, 0, 0, 7);
|
|
|
+ regWrite16(141, 255, 255, 7);
|
|
|
+ regWrite16(150, 0, 0, 7);
|
|
|
+ regWrite16(151, 255, 255, 7);
|
|
|
+ regWrite16(152, 0, 0, 7);
|
|
|
+ regWrite16(153, 255, 255, 7);
|
|
|
+ regWrite16(154, 0, 0, 7);
|
|
|
+ regWrite16(155, 255, 255, 7);
|
|
|
+ regWrite16(156, 0, 0, 7);
|
|
|
+ regWrite16(160, 0, 0, 7);
|
|
|
+ regWrite16(161, 255, 255, 7);
|
|
|
+ regWrite16(162, 0, 0, 7);
|
|
|
+ regWrite16(163, 255, 255, 7);
|
|
|
+ regWrite16(168, 0, 0, 7);
|
|
|
+ regWrite16(169, 255, 255, 7);
|
|
|
+ regWrite16(170, 0, 0, 7);
|
|
|
+ regWrite16(171, 255, 255, 7);
|
|
|
+ regWrite16(7, 0, 0, 7); // Disable TX/RX and set radio channel to 0
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Set sync word
|
|
|
+/**************************************************************************/
|
|
|
+void MiLightRadioPL1167_LT8900::vSetSyncWord(uint16_t syncWord3, uint16_t syncWord2, uint16_t syncWord1, uint16_t syncWord0)
|
|
|
+{
|
|
|
+ uiWriteRegister(R_SYNCWORD1, syncWord0);
|
|
|
+ uiWriteRegister(R_SYNCWORD2, syncWord1);
|
|
|
+ uiWriteRegister(R_SYNCWORD3, syncWord1);
|
|
|
+ uiWriteRegister(R_SYNCWORD4, syncWord3);
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Low level register write with delay
|
|
|
+/**************************************************************************/
|
|
|
+void MiLightRadioPL1167_LT8900::regWrite16(byte ADDR, byte V1, byte V2, byte WAIT)
|
|
|
+{
|
|
|
+ digitalWrite(_csPin, LOW);
|
|
|
+ SPI.transfer(ADDR);
|
|
|
+ SPI.transfer(V1);
|
|
|
+ SPI.transfer(V2);
|
|
|
+ digitalWrite(_csPin, HIGH);
|
|
|
+ delayMicroseconds(WAIT);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Low level register read
|
|
|
+/**************************************************************************/
|
|
|
+uint16_t MiLightRadioPL1167_LT8900::uiReadRegister(uint8_t reg)
|
|
|
+{
|
|
|
+ SPI.setDataMode(SPI_MODE1);
|
|
|
+ digitalWrite(_csPin, LOW);
|
|
|
+ SPI.transfer(REGISTER_READ | (REGISTER_MASK & reg));
|
|
|
+ uint8_t high = SPI.transfer(0x00);
|
|
|
+ uint8_t low = SPI.transfer(0x00);
|
|
|
+
|
|
|
+ digitalWrite(_csPin, HIGH);
|
|
|
+
|
|
|
+ SPI.setDataMode(SPI_MODE0);
|
|
|
+ return (high << 8 | low);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Low level 16bit register write
|
|
|
+/**************************************************************************/
|
|
|
+uint8_t MiLightRadioPL1167_LT8900::uiWriteRegister(uint8_t reg, uint16_t data)
|
|
|
+{
|
|
|
+ uint8_t high = data >> 8;
|
|
|
+ uint8_t low = data & 0xFF;
|
|
|
+
|
|
|
+ digitalWrite(_csPin, LOW);
|
|
|
+
|
|
|
+ uint8_t result = SPI.transfer(REGISTER_WRITE | (REGISTER_MASK & reg));
|
|
|
+ SPI.transfer(high);
|
|
|
+ SPI.transfer(low);
|
|
|
+
|
|
|
+ digitalWrite(_csPin, HIGH);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Start listening on specified channel and syncword
|
|
|
+/**************************************************************************/
|
|
|
+void MiLightRadioPL1167_LT8900::vStartListening(uint uiChannelToListenTo)
|
|
|
+{
|
|
|
+ _dupes_received = 0;
|
|
|
+ vSetSyncWord(config.syncword3, 0,0,config.syncword0);
|
|
|
+ vSetChannel(uiChannelToListenTo);
|
|
|
+
|
|
|
+ uiWriteRegister(R_CHANNEL, _channel & CHANNEL_MASK); //turn off rx/tx
|
|
|
+ delay(3);
|
|
|
+ uiWriteRegister(R_FIFO_CONTROL, 0x0080); //flush rx
|
|
|
+ uiWriteRegister(R_CHANNEL, (_channel & CHANNEL_MASK) | _BV(CHANNEL_RX_BIT)); //enable RX
|
|
|
+ delay(5);
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Resume listening - without changing the channel and syncword
|
|
|
+/**************************************************************************/
|
|
|
+void MiLightRadioPL1167_LT8900::vResumeRX(void)
|
|
|
+{
|
|
|
+ _dupes_received = 0;
|
|
|
+ uiWriteRegister(R_CHANNEL, _channel & CHANNEL_MASK); //turn off rx/tx
|
|
|
+ delay(3);
|
|
|
+ uiWriteRegister(R_FIFO_CONTROL, 0x0080); //flush rx
|
|
|
+ uiWriteRegister(R_CHANNEL, (_channel & CHANNEL_MASK) | _BV(CHANNEL_RX_BIT)); //enable RX
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Check if data is available using the hardware pin PKT_FLAG
|
|
|
+/**************************************************************************/
|
|
|
+bool MiLightRadioPL1167_LT8900::bAvailablePin()
|
|
|
+{
|
|
|
+ //read the PKT_FLAG pin.
|
|
|
+ if (digitalRead(_pin_pktflag) != 0)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Check if data is available using the PKT_FLAG state in the status register
|
|
|
+/**************************************************************************/
|
|
|
+bool MiLightRadioPL1167_LT8900::bAvailableRegister()
|
|
|
+{
|
|
|
+ //read the PKT_FLAG state; this can also be done with a hard wire.
|
|
|
+ uint16_t value = uiReadRegister(R_STATUS);
|
|
|
+
|
|
|
+ if (value & STATUS_PKT_BIT_MASK != 0)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Read the RX buffer
|
|
|
+/**************************************************************************/
|
|
|
+int MiLightRadioPL1167_LT8900::iReadRXBuffer(uint8_t *buffer, size_t maxBuffer)
|
|
|
+{
|
|
|
+ uint16_t value = uiReadRegister(R_STATUS);
|
|
|
+ if (bitRead(value, STATUS_CRC_BIT) == 0)
|
|
|
+ {
|
|
|
+ uint16_t data = uiReadRegister(R_FIFO);
|
|
|
+ uint8_t packetSize = data >> 8;
|
|
|
+ if (maxBuffer < packetSize + 1)
|
|
|
+ {
|
|
|
+ //BUFFER TOO SMALL
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint8_t pos = 0;;
|
|
|
+ buffer[pos++] = (data & 0xFF);
|
|
|
+ while (pos < packetSize)
|
|
|
+ {
|
|
|
+ data = uiReadRegister(R_FIFO);
|
|
|
+ buffer[pos++] = data >> 8;
|
|
|
+ buffer[pos++] = data & 0xFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ return packetSize;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //CRC error
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Set the active channel for the radio module
|
|
|
+/**************************************************************************/
|
|
|
+void MiLightRadioPL1167_LT8900::vSetChannel(uint8_t channel)
|
|
|
+{
|
|
|
+ _channel = channel;
|
|
|
+ uiWriteRegister(R_CHANNEL, (_channel & CHANNEL_MASK));
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Startup
|
|
|
+/**************************************************************************/
|
|
|
+int MiLightRadioPL1167_LT8900::begin()
|
|
|
+{
|
|
|
+ vSetChannel(config.channels[0]);
|
|
|
+ configure();
|
|
|
+ available();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Configure the module according to type, and start listening
|
|
|
+/**************************************************************************/
|
|
|
+int MiLightRadioPL1167_LT8900::configure()
|
|
|
+{
|
|
|
+ vInitRadioModule(config.type);
|
|
|
+ vSetSyncWord(config.syncword3, 0,0,config.syncword0);
|
|
|
+ vStartListening(config.channels[0]);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Check if data is available
|
|
|
+/**************************************************************************/
|
|
|
+bool MiLightRadioPL1167_LT8900::available()
|
|
|
+{
|
|
|
+ _waiting = false;
|
|
|
+
|
|
|
+ if(bAvailablePin())
|
|
|
+ {
|
|
|
+ int iStartTime = millis();
|
|
|
+ int iUpdateStamp = 0;
|
|
|
+ static byte byLastReceived[32];
|
|
|
+
|
|
|
+ byte byaFramesSizes[20];
|
|
|
+ byte byaFramesReceivedCount[20];
|
|
|
+ byte byaFramesReceived[20][32];
|
|
|
+ byte byFrameCounter = 0;
|
|
|
+
|
|
|
+ bool bDifference = false;
|
|
|
+
|
|
|
+ bool bRetVal = false;
|
|
|
+
|
|
|
+ if (bAvailablePin())
|
|
|
+ {
|
|
|
+ unsigned long ulTimeStamp = millis();
|
|
|
+ unsigned long ulElapsedTime = 0;
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ if (bAvailablePin())
|
|
|
+ {
|
|
|
+ iUpdateStamp = millis();
|
|
|
+ uint8_t buf[32];
|
|
|
+
|
|
|
+ int packetSize = iReadRXBuffer(buf, 32);
|
|
|
+ if (packetSize > 0)
|
|
|
+ {
|
|
|
+ bRetVal = true;
|
|
|
+ bDifference = false;
|
|
|
+
|
|
|
+ for (int iCounter = 0; iCounter < packetSize && bDifference == false; iCounter++)
|
|
|
+ {
|
|
|
+ if (buf[iCounter] != byLastReceived[iCounter])
|
|
|
+ {
|
|
|
+ bDifference = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bDifference == true)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < packetSize; i++)
|
|
|
+ {
|
|
|
+ byaFramesReceived[byFrameCounter][i] = buf[i];
|
|
|
+ byLastReceived[i] = buf[i];
|
|
|
+ byaFramesSizes[i] = packetSize;
|
|
|
+ }
|
|
|
+
|
|
|
+ byaFramesReceivedCount[byFrameCounter] = 1;
|
|
|
+ byFrameCounter++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ byaFramesReceivedCount[byFrameCounter-1]++;
|
|
|
+ //Serial.print(".");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (packetSize < 0)
|
|
|
+ {
|
|
|
+ Serial.println(F("Packet less than zero, buffer to small"));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Serial.println(F("Packet read fail"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ vResumeRX();
|
|
|
+ }
|
|
|
+
|
|
|
+ ulElapsedTime = millis();
|
|
|
+ yield();
|
|
|
+ ulElapsedTime = ulElapsedTime - ulTimeStamp;
|
|
|
+ }while (ulElapsedTime <1000 );
|
|
|
+
|
|
|
+ Serial.print("ElapsedRX: ");
|
|
|
+ Serial.println(iUpdateStamp - iStartTime);
|
|
|
+
|
|
|
+ if (byFrameCounter != 0)
|
|
|
+ {
|
|
|
+ Serial.println("");
|
|
|
+ Serial.print(F("Packets received: "));
|
|
|
+ Serial.print(byFrameCounter);
|
|
|
+
|
|
|
+ for (byte byCounterFrame = 0; byCounterFrame < byFrameCounter; byCounterFrame++)
|
|
|
+ {
|
|
|
+ _dupes_received = byaFramesReceivedCount[byCounterFrame];
|
|
|
+ Serial.println("");
|
|
|
+ Serial.print(F("Packet read OK, rec: "));
|
|
|
+ Serial.print(byaFramesReceivedCount[byCounterFrame]);
|
|
|
+ Serial.println(F(" Frame: "));
|
|
|
+ //dump the packet.
|
|
|
+
|
|
|
+ _packet[0]=byaFramesSizes[byCounterFrame];
|
|
|
+ for (int iByteCounter = 0; iByteCounter < byaFramesSizes[byCounterFrame]; iByteCounter++)
|
|
|
+ {
|
|
|
+ byte byReceivedvalue = byaFramesReceived[byCounterFrame][iByteCounter];
|
|
|
+ _packet[iByteCounter+1] = byReceivedvalue;
|
|
|
+
|
|
|
+ String stringOne = String(byReceivedvalue, HEX);
|
|
|
+ String stringToWrite = "0x";
|
|
|
+
|
|
|
+ if (byReceivedvalue < 0x10)
|
|
|
+ {
|
|
|
+ stringToWrite += "0";
|
|
|
+ }
|
|
|
+ stringToWrite += stringOne;
|
|
|
+ stringToWrite += " ";
|
|
|
+
|
|
|
+
|
|
|
+ Serial.print(stringToWrite);
|
|
|
+ }
|
|
|
+
|
|
|
+ _waiting = true;
|
|
|
+ }
|
|
|
+ Serial.println("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ yield();
|
|
|
+ }
|
|
|
+
|
|
|
+ return _waiting;
|
|
|
+}
|
|
|
+
|
|
|
+int MiLightRadioPL1167_LT8900::dupesReceived()
|
|
|
+{
|
|
|
+ return _dupes_received;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Read received data from buffer to upper layer
|
|
|
+/**************************************************************************/
|
|
|
+int MiLightRadioPL1167_LT8900::read(uint8_t frame[], size_t &frame_length)
|
|
|
+{
|
|
|
+ if (!_waiting)
|
|
|
+ {
|
|
|
+ frame_length = 0;
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (frame_length > sizeof(_packet) - 1)
|
|
|
+ {
|
|
|
+ frame_length = sizeof(_packet) - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (frame_length > _packet[0])
|
|
|
+ {
|
|
|
+ frame_length = _packet[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(frame, _packet +1 , frame_length);
|
|
|
+ _waiting = false;
|
|
|
+
|
|
|
+ // Start RX mode again
|
|
|
+ vResumeRX();
|
|
|
+
|
|
|
+ return _packet[0];
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Write data
|
|
|
+/**************************************************************************/
|
|
|
+int MiLightRadioPL1167_LT8900::write(uint8_t frame[], size_t frame_length)
|
|
|
+{
|
|
|
+ if (frame_length > sizeof(_out_packet) - 1) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(_out_packet + 1, frame, frame_length);
|
|
|
+ _out_packet[0] = frame_length;
|
|
|
+
|
|
|
+ SPI.setDataMode(SPI_MODE1);
|
|
|
+
|
|
|
+ int retval = resend();
|
|
|
+ yield();
|
|
|
+
|
|
|
+ SPI.setDataMode(SPI_MODE0);
|
|
|
+
|
|
|
+ if (retval < 0) {
|
|
|
+ return retval;
|
|
|
+ }
|
|
|
+ return frame_length;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// Handle the transmission to regarding to freq diversity and repeats
|
|
|
+/**************************************************************************/
|
|
|
+int MiLightRadioPL1167_LT8900::resend()
|
|
|
+{
|
|
|
+ byte Length = _out_packet[0];
|
|
|
+
|
|
|
+ for (size_t i = 0; i < MiLightRadioConfig::NUM_CHANNELS; i++)
|
|
|
+ {
|
|
|
+ sendPacket(_out_packet, Length, config.channels[i]);
|
|
|
+ delayMicroseconds(DEFAULT_TIME_BETWEEN_RETRANSMISSIONS_uS);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**************************************************************************/
|
|
|
+// The actual transmit happens here
|
|
|
+/**************************************************************************/
|
|
|
+bool MiLightRadioPL1167_LT8900::sendPacket(uint8_t *data, size_t packetSize, byte byChannel)
|
|
|
+{
|
|
|
+ if (packetSize < 1 || packetSize > 255)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ uiWriteRegister(R_CHANNEL, 0x0000);
|
|
|
+ uiWriteRegister(R_FIFO_CONTROL, 0x8080); //flush tx and RX
|
|
|
+
|
|
|
+ digitalWrite(_csPin, LOW); // Enable PL1167 SPI transmission
|
|
|
+ SPI.transfer(R_FIFO); // Start writing PL1167's FIFO Data register
|
|
|
+ SPI.transfer(packetSize); // Length of data buffer: x bytes
|
|
|
+
|
|
|
+ for (byte iCounter = 0; iCounter < packetSize; iCounter++)
|
|
|
+ {
|
|
|
+ SPI.transfer((data[1+iCounter]));
|
|
|
+ }
|
|
|
+ digitalWrite(_csPin, HIGH); // Disable PL1167 SPI transmission
|
|
|
+ delayMicroseconds(10);
|
|
|
+
|
|
|
+ uiWriteRegister(R_CHANNEL, (byChannel & CHANNEL_MASK) | _BV(CHANNEL_TX_BIT)); //enable RX
|
|
|
+
|
|
|
+ //Wait until the packet is sent.
|
|
|
+ while (digitalRead(_pin_pktflag) == 0)
|
|
|
+ {
|
|
|
+ //do nothing.
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|