improve data reciver
This commit is contained in:
parent
99ab8cf36d
commit
8fbbc167af
@ -1,21 +1,16 @@
|
||||
#include "W433DataReciver.h"
|
||||
#include <util/crc16.h>
|
||||
#include "writepin.h"
|
||||
#include <stdlib.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "serial.h"
|
||||
|
||||
W433DataReciver* W433DataReciver::instance = nullptr;
|
||||
|
||||
W433DataReciver::W433DataReciver(volatile unsigned char* const port, const unsigned char pin,
|
||||
volatile uint16_t * timerRegister, volatile uint8_t* const timerOverflowRegister,
|
||||
void (* const packetCallback)(uint32_t, void*), void* const userData, void (*errorCodeHandler)(uint8_t, void*) ):
|
||||
_port(port), _pin(pin), _timerRegister(timerRegister), _timerOverflowRegister(timerOverflowRegister),
|
||||
_packetCallback(packetCallback), _errorCodeHandler(errorCodeHandler), _userData(userData)
|
||||
W433DataReciver::W433DataReciver(volatile unsigned char* const portIn, const unsigned char pinIn,
|
||||
void (*packetCallbackIn)(uint32_t, void*), void* userDataIn,
|
||||
void (*errorCodeHandlerIn)(uint8_t, void*)):
|
||||
port(portIn), pin(pinIn),
|
||||
packetCallback(packetCallbackIn), errorCodeHandler(errorCodeHandlerIn), userData(userDataIn)
|
||||
{
|
||||
instance = this;
|
||||
for(uint8_t i = 0; i < 33; i++) timesBuffer[i] = 0;
|
||||
}
|
||||
|
||||
W433DataReciver::~W433DataReciver()
|
||||
@ -25,213 +20,125 @@ W433DataReciver::~W433DataReciver()
|
||||
|
||||
void W433DataReciver::staticInterrupt()
|
||||
{
|
||||
if(instance != nullptr) instance->interrupt();
|
||||
if(instance != nullptr)
|
||||
instance->interrupt();
|
||||
}
|
||||
|
||||
int8_t W433DataReciver::reciveBit(uint8_t index)
|
||||
uint16_t W433DataReciver::calcCrc(uint32_t data)
|
||||
{
|
||||
if(
|
||||
timesBuffer[index] < 0 &&
|
||||
isTime(timesBuffer[index+1], SMALL_TIME, true, SMALL_TIME_TOLERANCE) &&
|
||||
isTime(timesBuffer[index+2], LARGE_TIME, false, LARGE_TIME_TOLERANCE) //&&
|
||||
//isTime(timesBuffer[index+3], SMALL_TIME, true, SMALL_TIME_TOLERANCE)
|
||||
)
|
||||
uint16_t crc = 0xffff;
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(&data);
|
||||
for(size_t i = 0; i < sizeof(data); ++i)
|
||||
crc = _crc_ccitt_update(crc, ptr[i]);
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint8_t W433DataReciver::symbolDecode(uint8_t symbol)
|
||||
{
|
||||
switch(symbol)
|
||||
{
|
||||
case 0xe:
|
||||
return 1;
|
||||
}
|
||||
else if(
|
||||
timesBuffer[index] < 0 &&
|
||||
isTime(timesBuffer[index+1], LARGE_TIME, true, LARGE_TIME_TOLERANCE) &&
|
||||
isTime(timesBuffer[index+2], SMALL_TIME, false, SMALL_TIME_TOLERANCE) //&&
|
||||
//isTime(timesBuffer[index+3], SMALL_TIME, true, SMALL_TIME_TOLERANCE)
|
||||
)
|
||||
{
|
||||
case 0x13:
|
||||
return 2;
|
||||
case 0x15:
|
||||
return 3;
|
||||
case 0x16:
|
||||
return 4;
|
||||
case 0x19:
|
||||
return 5;
|
||||
case 0x1a:
|
||||
return 6;
|
||||
case 0x1c:
|
||||
return 7;
|
||||
case 0x23:
|
||||
return 8;
|
||||
case 0x25:
|
||||
return 9;
|
||||
case 0x26:
|
||||
return 10;
|
||||
case 0x29:
|
||||
return 11;
|
||||
case 0x2a:
|
||||
return 12;
|
||||
case 0x2c:
|
||||
return 13;
|
||||
case 0x32:
|
||||
return 14;
|
||||
case 0x34:
|
||||
return 15;
|
||||
case 0xd:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void W433DataReciver::waitForReciveIdle(const uint16_t timeoutMs)
|
||||
void W433DataReciver::pll(bool sample)
|
||||
{
|
||||
uint16_t counter = 0;
|
||||
while(true)
|
||||
// Integrate each sample
|
||||
if(sample)
|
||||
rxIntegrator++;
|
||||
|
||||
if (sample != prevSample)
|
||||
{
|
||||
while(counter < timeoutMs && state != LOOKING_FOR_SYNC)
|
||||
{
|
||||
_delay_ms(1);
|
||||
++counter;
|
||||
}
|
||||
_delay_ms(500);
|
||||
counter+=500;
|
||||
if(state == LOOKING_FOR_SYNC || counter >= timeoutMs) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool W433DataReciver::isTime(int16_t input, const uint16_t time, const bool state, const uint16_t tollerance)
|
||||
{
|
||||
if((state && input < 0) || (!state && input > 0)) return false;
|
||||
input = abs(input);
|
||||
return input < (int16_t)(time+tollerance) && input > (int16_t)(time-tollerance);
|
||||
}
|
||||
|
||||
bool W433DataReciver::reciveSync(const uint16_t elapsedTime)
|
||||
{
|
||||
if(elapsedTime < SYNC_TIME+SYNC_TIME_TOLERANCE && elapsedTime > SYNC_TIME-SYNC_TIME_TOLERANCE)
|
||||
{
|
||||
++syncCount;
|
||||
pllRamp += pllRamp < PLL_RAMP_TRANSITION ? PLL_RAMP_INC_RETARD : PLL_RAMP_INC_ADVANCE;
|
||||
prevSample = sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(syncCount > 4 && syncFailCount < 3) ++syncFailCount;
|
||||
else
|
||||
{
|
||||
//if(syncCount > 7) error(ERR_SYNC_FAIL);
|
||||
setState(LOOKING_FOR_SYNC);
|
||||
}
|
||||
pllRamp += PLL_RAMP_INC_STEP;
|
||||
}
|
||||
if(syncCount > 10) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool W433DataReciver::recivedByte(const uint16_t elapsedTime)
|
||||
{
|
||||
timesBuffer[timesBufferIndex] = readPin(_port, _pin) ? 0-elapsedTime : elapsedTime;
|
||||
++timesBufferIndex;
|
||||
if(timesBufferIndex == 32) writePin(&PORTC, PC0, true);
|
||||
return timesBufferIndex == 32;
|
||||
}
|
||||
|
||||
uint8_t W433DataReciver::assmbleByte()
|
||||
{
|
||||
uint8_t byte = 0;
|
||||
for(uint8_t i = 0; i < 8; ++i)
|
||||
if (pllRamp >= PLL_RAMP_LEN)
|
||||
{
|
||||
int8_t bit = reciveBit(i*4);
|
||||
if(bit >= 0) byte = byte | (bit << (7-i));
|
||||
else
|
||||
rxBits >>= 1;
|
||||
|
||||
if (rxIntegrator >= 5)
|
||||
rxBits |= 0x800;
|
||||
|
||||
pllRamp -= PLL_RAMP_LEN;
|
||||
rxIntegrator = 0;
|
||||
|
||||
if(mode == MODE_RECEIVING)
|
||||
{
|
||||
setState(LOOKING_FOR_SYNC);
|
||||
error(ERR_BYTE_ASM);
|
||||
if (++rxCount >= 12)
|
||||
{
|
||||
uint8_t currentByte = (symbolDecode(rxBits & 0x3f)) | symbolDecode(rxBits >> 6) << 4;
|
||||
rxBuf[PACKET_LENGTH-1-(rxLen++)] = currentByte;
|
||||
|
||||
if (rxLen >= PACKET_LENGTH)
|
||||
{
|
||||
mode = MODE_SEARCHING;
|
||||
uint32_t* packet = reinterpret_cast<uint32_t*>(rxBuf+2);
|
||||
uint16_t crc = rxBuf[0] << 8 | rxBuf[1];
|
||||
uint16_t crcC = calcCrc(*packet);
|
||||
if(crc != crcC)
|
||||
{
|
||||
if(errorCodeHandler)
|
||||
errorCodeHandler(ERROR_CRC, userData);
|
||||
}
|
||||
else
|
||||
{
|
||||
packetCallback(*packet, userData);
|
||||
}
|
||||
}
|
||||
rxCount = 0;
|
||||
}
|
||||
}
|
||||
else if (rxBits == 0xb38)
|
||||
{
|
||||
mode = MODE_RECEIVING;
|
||||
rxCount = 0;
|
||||
rxLen = 0;
|
||||
}
|
||||
}
|
||||
timesBufferIndex = 0;
|
||||
return byte;
|
||||
}
|
||||
|
||||
void W433DataReciver::error(const uint8_t errorCode)
|
||||
{
|
||||
if(_errorCodeHandler != nullptr) (*_errorCodeHandler)(errorCode, _userData);
|
||||
}
|
||||
|
||||
void W433DataReciver::setState(const uint8_t stateIn)
|
||||
{
|
||||
state = stateIn;
|
||||
timesBufferIndex = 0;
|
||||
packetIndex = 0;
|
||||
syncCount = 0;
|
||||
syncFailCount = 0;
|
||||
}
|
||||
|
||||
void W433DataReciver::interrupt()
|
||||
{
|
||||
uint16_t elapsedTime = polarity*(((*_timerOverflowRegister & 0x01) ? *_timerRegister+
|
||||
(UINT16_MAX - previousTime) : *_timerRegister - previousTime)/TICKS_PER_US);
|
||||
|
||||
if(elapsedTime < DISCARD_TIME)
|
||||
{
|
||||
if(timesBufferIndex > 0 && elapsedTime + abs(timesBuffer[timesBufferIndex-1]) < LARGE_TIME+LARGE_TIME_TOLERANCE)
|
||||
{
|
||||
writePin(&PORTC, PC2, true);
|
||||
previousTime = *_timerRegister - elapsedTime - abs(timesBuffer[timesBufferIndex-1]);
|
||||
timesBufferIndex-=1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
previousTime = *_timerRegister;
|
||||
*_timerOverflowRegister = *_timerOverflowRegister | 0x01;
|
||||
|
||||
if(state == LOOKING_FOR_SYNC && reciveSync(elapsedTime))
|
||||
{
|
||||
setState(LOOKING_FOR_SYNC_END);
|
||||
}
|
||||
else if(state == LOOKING_FOR_SYNC_END)
|
||||
{
|
||||
if(elapsedTime > SYNC_TIME + SYNC_END_TIME_TOLERANCE)
|
||||
{
|
||||
if(elapsedTime < LARGE_TIME - LARGE_TIME_TOLERANCE)
|
||||
{
|
||||
setState(LOOKING_FOR_SYNC);
|
||||
error(ERR_NO_SYNC_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
timesBuffer[0] = -LARGE_TIME;
|
||||
setState(LOOKING_FOR_SIGNATURE);
|
||||
++timesBufferIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(state == LOOKING_FOR_SIGNATURE)
|
||||
{
|
||||
if(recivedByte(elapsedTime))
|
||||
{
|
||||
uint8_t recivedSignature = assmbleByte();
|
||||
if( recivedSignature == signature) setState(RECVING_PACKET);
|
||||
else
|
||||
{
|
||||
error(ERR_WRONG_SIG);
|
||||
setState(LOOKING_FOR_SYNC);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( state == RECVING_PACKET )
|
||||
{
|
||||
|
||||
if(recivedByte(elapsedTime))
|
||||
{
|
||||
uint8_t packetByte = assmbleByte();
|
||||
|
||||
packet = packet | ((uint32_t)packetByte) << ((3-packetIndex)*8);
|
||||
++packetIndex;
|
||||
if(packetIndex > 3)
|
||||
{
|
||||
packetIndex = 0;
|
||||
timesBufferIndex = 0;
|
||||
setState(RECVING_PACKET_CHECKSUM);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(state == RECVING_PACKET_CHECKSUM)
|
||||
{
|
||||
if(recivedByte(elapsedTime))
|
||||
{
|
||||
uint8_t recivedChecksum = assmbleByte();
|
||||
|
||||
volatile uint8_t* buffer = reinterpret_cast<volatile uint8_t*>(&packet);
|
||||
|
||||
uint8_t computedChecksum = 0;
|
||||
for(uint8_t j = 0; j < sizeof(packet); j++) for(uint8_t i = 0; i < 8;
|
||||
i++) computedChecksum = computedChecksum + ((buffer[j] & ( 1 << (8 - i))) >> (8 - i));
|
||||
//for(uint8_t j = 0; j < sizeof(packet); j++) for(uint8_t i = 0; i < 8; i++) computedChecksum = computedChecksum + (buffer[j] & ( 1 << (8 - i)));
|
||||
|
||||
if(computedChecksum == recivedChecksum)
|
||||
{
|
||||
#ifdef USE_RINGBUFFER
|
||||
_ringBuffer.write(const_cast<uint8_t*>(buffer), sizeof(packet));
|
||||
#endif
|
||||
if(_packetCallback != nullptr)(*_packetCallback)(packet, _userData);
|
||||
}
|
||||
else error(ERR_CHECKSUM);
|
||||
packet = 0;
|
||||
setState(LOOKING_FOR_SYNC);
|
||||
}
|
||||
}
|
||||
pll(readPin(port, pin));
|
||||
}
|
||||
|
||||
#ifdef USE_RINGBUFFER
|
||||
RingBuffer<W433DataReciver::RINGBUFFER_LENGTH, uint8_t>* W433DataReciver::getRingBuffer()
|
||||
uint16_t W433DataReciver::calculateOverflowRegister(uint16_t bitRate, uint16_t devisor)
|
||||
{
|
||||
return &_ringBuffer;
|
||||
return (F_CPU /(8UL*devisor))/bitRate;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,96 +1,63 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "ringbuffer.h"
|
||||
|
||||
//#define USE_RINGBUFFER
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class W433DataReciver
|
||||
{
|
||||
public:
|
||||
static constexpr int ERROR_CRC = 1;
|
||||
|
||||
static constexpr uint8_t RINGBUFFER_LENGTH = 32;
|
||||
|
||||
//errors
|
||||
static constexpr uint8_t ERR_SYNC_FAIL = 1;
|
||||
static constexpr uint8_t ERR_NO_SYNC_END = 2;
|
||||
static constexpr uint8_t ERR_BYTE_ASM = 3;
|
||||
static constexpr uint8_t ERR_WRONG_SIG = 4;
|
||||
static constexpr uint8_t ERR_CHECKSUM = 5;
|
||||
static constexpr int SAMPLES_PER_BIT = 8;
|
||||
static constexpr int PLL_RAMP_LEN = 160;
|
||||
static constexpr int PLL_RAMP_INC_STEP = PLL_RAMP_LEN/SAMPLES_PER_BIT;
|
||||
static constexpr int PLL_RAMP_TRANSITION = PLL_RAMP_LEN/2;
|
||||
static constexpr int PLL_RAMP_INC_RETARD = PLL_RAMP_INC_STEP-9;
|
||||
static constexpr int PLL_RAMP_INC_ADVANCE = PLL_RAMP_INC_STEP+9;
|
||||
static constexpr int PLL_HEADER_LEN_BITS = 8;
|
||||
static constexpr int PACKET_LENGTH = sizeof(uint32_t)+2;
|
||||
|
||||
private:
|
||||
|
||||
static constexpr int MODE_SEARCHING = 0;
|
||||
static constexpr int MODE_RECEIVING = 1;
|
||||
|
||||
static W433DataReciver* instance;
|
||||
|
||||
//constants
|
||||
static constexpr uint8_t CLOCK_DEVIDER = 1;
|
||||
static constexpr uint16_t LARGE_TIME = 2000;
|
||||
static constexpr uint16_t SMALL_TIME = 500;
|
||||
static constexpr uint16_t SYNC_TIME = 800;
|
||||
static constexpr uint8_t SYNC_TIME_TOLERANCE = SYNC_TIME*0.20;
|
||||
static constexpr uint16_t SYNC_END_TIME_TOLERANCE = SYNC_TIME*0.50;
|
||||
static constexpr uint16_t LARGE_TIME_TOLERANCE = LARGE_TIME*0.30;
|
||||
static constexpr uint8_t SMALL_TIME_TOLERANCE = SMALL_TIME*0.30;
|
||||
static constexpr uint16_t DISCARD_TIME = SMALL_TIME*0.6;
|
||||
static constexpr uint16_t TICKS_PER_US = (F_CPU) / (1000000*CLOCK_DEVIDER);
|
||||
static constexpr uint8_t signature = 0xA5;
|
||||
volatile unsigned char *port;
|
||||
unsigned char pin;
|
||||
|
||||
static constexpr int8_t polarity = 1;
|
||||
bool prevSample = 0;
|
||||
uint8_t pllRamp = 0;
|
||||
uint8_t rxIntegrator = 0;
|
||||
|
||||
static constexpr uint8_t LOOKING_FOR_SYNC = 0;
|
||||
static constexpr uint8_t LOOKING_FOR_SYNC_END = 1;
|
||||
static constexpr uint8_t LOOKING_FOR_SIGNATURE = 2;
|
||||
static constexpr uint8_t RECVING_PACKET = 3;
|
||||
static constexpr uint8_t RECVING_PACKET_CHECKSUM = 4;
|
||||
uint16_t rxBits = 0;
|
||||
|
||||
//variables
|
||||
volatile unsigned char *_port;
|
||||
unsigned char _pin;
|
||||
uint8_t mode = MODE_SEARCHING;
|
||||
|
||||
volatile uint16_t *_timerRegister;
|
||||
volatile uint8_t *_timerOverflowRegister;
|
||||
uint8_t rxBuf[PACKET_LENGTH];
|
||||
uint8_t rxCount = 0;
|
||||
volatile uint8_t rxLen = 0;
|
||||
|
||||
#ifdef USE_RINGBUFFER
|
||||
RingBuffer<RINGBUFFER_LENGTH, uint8_t> _ringBuffer;
|
||||
#endif
|
||||
void (* const packetCallback)(uint32_t, void*);
|
||||
void (* const errorCodeHandler)(uint8_t, void*);
|
||||
void* const userData;
|
||||
|
||||
volatile uint16_t previousTime = 0;
|
||||
volatile uint8_t timesBufferIndex = 0;
|
||||
volatile int16_t timesBuffer[33];
|
||||
private:
|
||||
|
||||
volatile uint8_t packetIndex = 0;
|
||||
volatile uint32_t packet = 0;
|
||||
|
||||
void (* const _packetCallback)(uint32_t, void*);
|
||||
void (* const _errorCodeHandler)(uint8_t, void*);
|
||||
void* const _userData;
|
||||
|
||||
volatile uint8_t syncCount = 0;
|
||||
volatile uint8_t syncFailCount = 0;
|
||||
volatile uint8_t state = 0;
|
||||
|
||||
//private functions
|
||||
int8_t reciveBit(uint8_t index);
|
||||
|
||||
inline uint8_t assmbleByte();
|
||||
inline void setState(const uint8_t stateIn);
|
||||
inline bool recivedByte(const uint16_t elapsedTime);
|
||||
inline bool reciveSync(const uint16_t elapsedTime);
|
||||
|
||||
inline void error(const uint8_t errorCode);
|
||||
|
||||
static inline bool isTime(int16_t input, const uint16_t time, const bool state = true, const uint16_t tollerance = 100);
|
||||
static uint16_t calcCrc(uint32_t data);
|
||||
static uint8_t symbolDecode(uint8_t symbol);
|
||||
void pll(bool sample);
|
||||
|
||||
public:
|
||||
|
||||
W433DataReciver(volatile unsigned char* const port, const unsigned char pin, volatile uint16_t * timerRegister,
|
||||
volatile uint8_t* const timerOverflowRegister, void (*packetCallback)(uint32_t, void*) = nullptr,
|
||||
void* userData = nullptr, void (*errorCodeHandler)(uint8_t, void*) = nullptr );
|
||||
W433DataReciver(volatile unsigned char* const portIn, const unsigned char pinIn, void (*packetCallbackIn)(uint32_t,
|
||||
void*),
|
||||
void* userDataIn = nullptr, void (*errorCodeHandlerIn)(uint8_t, void*) = nullptr );
|
||||
~W433DataReciver();
|
||||
static void initTimer();
|
||||
|
||||
static void staticInterrupt();
|
||||
void waitForReciveIdle(const uint16_t timeoutMs = 10000);
|
||||
void interrupt();
|
||||
#ifdef USE_RINGBUFFER
|
||||
RingBuffer<RINGBUFFER_LENGTH, uint8_t>* getRingBuffer();
|
||||
#endif
|
||||
|
||||
static uint16_t calculateOverflowRegister(uint16_t bitRate, uint16_t devisor);
|
||||
};
|
||||
|
13
main.cpp
13
main.cpp
@ -31,7 +31,7 @@ static volatile bool resendNow = false;
|
||||
static volatile uint8_t resendCounter = 0;
|
||||
static bool resendEnabled = false;
|
||||
|
||||
ISR(PCINT1_vect)
|
||||
ISR(TIMER1_COMPB_vect)
|
||||
{
|
||||
W433DataReciver::staticInterrupt();
|
||||
}
|
||||
@ -450,12 +450,13 @@ int main()
|
||||
RgbLed rgbled( &pwmTc0, &pwmTc2 );
|
||||
loadRGB(&rgbled);
|
||||
|
||||
Pwm16b pwmTc1 ( &TCCR1A, &TCCR1B, &OCR1A, &OCR1B, &ICR1, 0b00000001, true, false);
|
||||
Pwm16b pwmTc1(&TCCR1A, &TCCR1B, &OCR1A, &OCR1B, &ICR1, 0b00000001, true, false);
|
||||
|
||||
setBit(&PCICR, PCIE1, true);
|
||||
setBit(&PCMSK1, PCINT8, true);
|
||||
W433DataReciver reciver(&PINC, PC0, &TCNT1, &TIFR1, &sensorPacketRecived, reinterpret_cast<void*>(&serial),
|
||||
&reciverError);
|
||||
setBit(&TIMSK1, OCIE1B, true);
|
||||
setBit(&TCCR1B, CS10, true);
|
||||
ICR1 = W433DataReciver::calculateOverflowRegister(2000, 1);
|
||||
OCR1B = ICR1-1;
|
||||
W433DataReciver reciver(&PINC, PC0, &sensorPacketRecived, reinterpret_cast<void*>(&serial), &reciverError);
|
||||
W433DataTransmitter transmitter(&PORTB, PB5);
|
||||
UvosItem::transmitter = &transmitter;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user