Initial ability to send a packet from RFPowerView
This commit is contained in:
35
include/BufferFiller.h
Normal file
35
include/BufferFiller.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef BUFFERFILLER_H
|
||||
#define BUFFERFILLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#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
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <RF24.h>
|
||||
#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<void(const Packet*)> callback);
|
||||
void sendPacket(const Packet* packet);
|
||||
|
||||
private:
|
||||
RF24 radio;
|
||||
PacketReceiver packetReceiver;
|
||||
PacketParser packetParser;
|
||||
BufferFiller bufferFiller;
|
||||
uint8_t irqPin;
|
||||
uint8_t rfID[2];
|
||||
|
||||
std::function<void(const Packet*)> packetCallback;
|
||||
|
||||
uint8_t sendBuffer[32];
|
||||
|
||||
void startListening();
|
||||
void startTransmitting();
|
||||
|
||||
void interruptHandler();
|
||||
|
||||
void processBuffer(const uint8_t *buffer);
|
||||
|
||||
162
src/BufferFiller.cpp
Normal file
162
src/BufferFiller.cpp
Normal file
@@ -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++;
|
||||
}
|
||||
@@ -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<uint8_t>(rfID & 0xFF), static_cast<uint8_t>(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<void(const Packet*)> 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user