diff --git a/include/BufferFiller.h b/include/BufferFiller.h new file mode 100644 index 0000000..54f2436 --- /dev/null +++ b/include/BufferFiller.h @@ -0,0 +1,35 @@ +#ifndef BUFFERFILLER_H +#define BUFFERFILLER_H + +#include +#include "PacketCRC.h" +#include "PacketTypes.h" + +class BufferFiller { +public: + BufferFiller(uint8_t rollingCode1, uint8_t rollingCode2, uint8_t protocolVersion); + ~BufferFiller(); + + bool fill(uint8_t *buffer, const Packet* packet); + +private: + uint8_t rollingCode1; + uint8_t rollingCode2; + uint8_t protocolVersion; + + PacketCRC packetCRC; + + void setPacketSize(uint8_t *buffer, uint8_t); + void setConstants(uint8_t *buffer); + void setSourceAddress(uint8_t *buffer, uint16_t); + void setDestinationAddress(uint8_t *buffer, uint16_t); + void setRollingCodes(uint8_t *buffer); + void setProtocolVersion(uint8_t *buffer, uint8_t); + void setOpenPacketData(uint8_t *buffer); + void setClosePacketData(uint8_t *buffer); + void setStopPacketData(uint8_t *buffer); + void calculateCRC(uint8_t *buffer); + void incrementRollingCodes(); +}; + +#endif // BUFFERFILLER_H \ No newline at end of file diff --git a/include/RFPowerView.h b/include/RFPowerView.h index f88ae39..4975a63 100644 --- a/include/RFPowerView.h +++ b/include/RFPowerView.h @@ -5,6 +5,7 @@ #include #include "PacketReceiver.h" #include "PacketParser.h" +#include "BufferFiller.h" #include "PacketTypes.h" #define DEFAULT_RF_CHANNEL (7) //this is the channel HD shades use @@ -21,19 +22,25 @@ public: bool begin(); void loop(); - void startListening(); void setPacketCallback(std::function callback); + void sendPacket(const Packet* packet); private: RF24 radio; PacketReceiver packetReceiver; PacketParser packetParser; + BufferFiller bufferFiller; uint8_t irqPin; uint8_t rfID[2]; std::function packetCallback; + uint8_t sendBuffer[32]; + + void startListening(); + void startTransmitting(); + void interruptHandler(); void processBuffer(const uint8_t *buffer); diff --git a/src/BufferFiller.cpp b/src/BufferFiller.cpp new file mode 100644 index 0000000..c895cf4 --- /dev/null +++ b/src/BufferFiller.cpp @@ -0,0 +1,162 @@ +#include "BufferFiller.h" + +BufferFiller::BufferFiller(uint8_t rollingCode1, uint8_t rollingCode2, uint8_t protocolVersion) : + rollingCode1(rollingCode1), + rollingCode2(rollingCode2), + protocolVersion(protocolVersion) +{ +} + +BufferFiller::~BufferFiller() +{ +} + +bool BufferFiller::fill(uint8_t *buffer, const Packet* packet) { + uint8_t packetSize = 0; + switch(packet->type) { + case PacketType::STOP: + case PacketType::OPEN: + case PacketType::CLOSE: + packetSize = 0x11; + break; + // TODO: Calculate fields length in buffer + default: + return false; + } + + setPacketSize(buffer, packetSize); + setConstants(buffer); + setProtocolVersion(buffer, protocolVersion); + setSourceAddress(buffer, packet->source); + setDestinationAddress(buffer, packet->destination); + + switch(packet->type) { + case PacketType::STOP: + setStopPacketData(buffer); + break; + case PacketType::CLOSE: + setClosePacketData(buffer); + break; + case PacketType::OPEN: + setOpenPacketData(buffer); + break; + default: + return false; + } + + setRollingCodes(buffer); + calculateCRC(buffer); + + incrementRollingCodes(); + + return true; +} + +void BufferFiller::setOpenPacketData(uint8_t *buffer) +{ + buffer[16] = 0x52; + buffer[17] = 0x55; + buffer[18] = 0x00; +} + +void BufferFiller::setClosePacketData(uint8_t *buffer) +{ + buffer[16] = 0x52; + buffer[17] = 0x44; + buffer[18] = 0x00; +} + + +void BufferFiller::setStopPacketData(uint8_t *buffer) +{ + buffer[16] = 0x52; + buffer[17] = 0x53; + buffer[18] = 0x00; +} + +/* +void BufferFiller::setPositionCommand(uint8_t *buffer, float percentage) +{ + // packetSize = 0x15; + + buffer[16] = 0x3F; // Field command + buffer[17] = 0x5A; // Constant + + buffer[18] = 0x04; // Field of 4 bytes + buffer[19] = 0x40; // Field type (0x40 is set) + buffer[20] = 0x50; // ID of position field + + uint16_t position = (uint16_t)(0xFFFF * percentage); + + buffer[21] = (uint8_t)(position & 0x00FF); + buffer[22] = (uint8_t)((position & 0xFF00) >> 8); +} + + void BufferFiller::setFetchPositionCommand(uint8_t *buffer) { + // packetSize = 0x13; + + buffer[16] = 0x3F; // Field command + buffer[17] = 0x5A; // Constant + + buffer[18] = 0x02; // Field of 2 bytes + buffer[19] = 0x3F; // Field type (0x3F is fetch) + buffer[20] = 0x50; // ID of position field + } +*/ + +void BufferFiller::setPacketSize(uint8_t *buffer, uint8_t length) { + buffer[1] = length; // Packet size +} + +void BufferFiller::setConstants(uint8_t *buffer) { + buffer[0] = 0xC0; // Header byte + + buffer[2] = 0x00; // Constant when sending, can be 0x10 when receiving a packet + buffer[3] = 0x05; // Constant + + buffer[5] = 0xFF; // Constant + buffer[6] = 0xFF; // Constant + + buffer[9] = 0x86; // Constant? +} + +void BufferFiller::setSourceAddress(uint8_t *buffer, uint16_t sourceID) { + // Physical source address (could be the address of a repeater when receiving a packet) + buffer[7] = (uint8_t)((sourceID & 0xFF00) >> 8); + buffer[8] = (uint8_t)(sourceID & 0x00FF); + + // Logical source address (usually the same as the physical source address) + buffer[14] = (uint8_t)((sourceID & 0xFF00) >> 8); + buffer[15] = (uint8_t)(sourceID & 0x00FF); +} + +void BufferFiller::setDestinationAddress(uint8_t *buffer, uint16_t targetID) { + // Logical target address + buffer[12] = (uint8_t)((targetID & 0xFF00) >> 8); + buffer[13] = (uint8_t)(targetID & 0x00FF); +} + +void BufferFiller::setRollingCodes(uint8_t *buffer) { + buffer[4] = rollingCode1; // Rolling code 1 + buffer[11] = rollingCode2; // Rolling code 2 +} + +void BufferFiller::setProtocolVersion(uint8_t *buffer, uint8_t version) { + buffer[10] = version; // Protocol version? +} + +void BufferFiller::calculateCRC(uint8_t *buffer) { // must be called after the buffer has been filled + uint8_t length = buffer[1]; + uint16_t result = packetCRC.calculate(buffer); + + uint8_t checksum1 = (uint8_t)((result & 0xFF00) >> 8); + uint8_t checksum2 = (uint8_t)(result & 0x00FF); + + buffer[length + 2] = checksum1; // Checksum + buffer[length + 3] = checksum2; // Checksum +} + +void BufferFiller::incrementRollingCodes() { + rollingCode1++; + rollingCode2++; +} \ No newline at end of file diff --git a/src/RFPowerView.cpp b/src/RFPowerView.cpp index 8ac1016..066075e 100644 --- a/src/RFPowerView.cpp +++ b/src/RFPowerView.cpp @@ -4,6 +4,7 @@ RFPowerView::RFPowerView(uint8_t cePin, uint8_t csPin, uint8_t irqPin, uint16_t rfID) : radio(cePin, csPin), packetReceiver(&radio), + bufferFiller(0x00, 0x00, 0x05), irqPin(irqPin), rfID{static_cast(rfID & 0xFF), static_cast(rfID >> 8)}, packetCallback(nullptr) {} @@ -16,6 +17,18 @@ bool RFPowerView::begin() { packetReceiver.setBufferCallback([this](const uint8_t* buffer) { this->processBuffer(buffer); }); packetReceiver.setInvalidBufferCallback([this](const uint8_t* buffer) { this->processInvalidBuffer(buffer); }); + pinMode(irqPin, INPUT); + + attachInterrupt(digitalPinToInterrupt(irqPin), std::bind(&RFPowerView::interruptHandler, this), FALLING); + + radio.setChannel(DEFAULT_RF_CHANNEL); + radio.setDataRate(DEFAULT_RF_DATARATE); + radio.setAutoAck(false); + radio.disableCRC(); + radio.setRetries(0, 0); + radio.setPayloadSize(32); + radio.setAddressWidth(2); + startListening(); return true; @@ -26,25 +39,22 @@ void RFPowerView::loop() { } void RFPowerView::startListening() { - radio.setChannel(DEFAULT_RF_CHANNEL); - radio.setDataRate(DEFAULT_RF_DATARATE); - radio.setAutoAck(false); - radio.disableCRC(); - radio.setPayloadSize(32); - - // TODO: Verify that putting this in begin() instead of startListening() works - pinMode(irqPin, INPUT); - - radio.setAddressWidth(2); radio.openReadingPipe(0, rfID); radio.startListening(); - Serial.println("Listening"); - // TODO: Verify that putting this in being() instead of startListening() works - attachInterrupt(digitalPinToInterrupt(irqPin), std::bind(&RFPowerView::interruptHandler, this), FALLING); + interrupts(); } +void RFPowerView::startTransmitting() { + radio.stopListening(); + + radio.setPALevel(RF24_PA_HIGH, true); + + radio.openWritingPipe(rfID); + radio.powerUp(); +} + void RFPowerView::interruptHandler() { packetReceiver.read(); } @@ -65,4 +75,23 @@ void RFPowerView::processInvalidBuffer(const uint8_t *buffer) { void RFPowerView::setPacketCallback(std::function callback) { packetCallback = callback; +} + +void RFPowerView::sendPacket(const Packet* packet) { + if (bufferFiller.fill(sendBuffer, packet)) { + startTransmitting(); + + uint8_t bytecount = sendBuffer[1] + 4; + for (int j = 1; j < 5; j++) { + radio.openWritingPipe(rfID); + for (int i = 1; i < 200; i++) { + radio.writeFast(sendBuffer, bytecount); + } + delay(100); + radio.flush_tx(); + radio.txStandBy(); + } + + startListening(); + } } \ No newline at end of file