This commit is contained in:
2023-04-03 01:06:58 +02:00
parent 7b936642ad
commit 99ba609f6f
6 changed files with 392 additions and 330 deletions

View File

@ -1,231 +1,144 @@
#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;
instance = this;
}
W433DataReciver::~W433DataReciver()
{
instance = nullptr;
instance = nullptr;
}
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)
)
{
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)
)
{
return 0;
}
else return -1;
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;
}
void W433DataReciver::waitForReciveIdle(const uint16_t timeoutMs)
uint8_t W433DataReciver::symbolDecode(uint8_t symbol)
{
uint16_t counter = 0;
while(true)
{
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;
}
else
switch(symbol)
{
if(syncCount > 4 && syncFailCount < 3) ++syncFailCount;
else
case 0xe:
return 1;
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;
}
}
void W433DataReciver::pll(bool sample)
{
// Integrate each sample
if(sample)
rxIntegrator++;
if (sample != prevSample)
{
pllRamp += pllRamp < PLL_RAMP_TRANSITION ? PLL_RAMP_INC_RETARD : PLL_RAMP_INC_ADVANCE;
prevSample = sample;
}
else
{
pllRamp += PLL_RAMP_INC_STEP;
}
if (pllRamp >= PLL_RAMP_LEN)
{
rxBits >>= 1;
if (rxIntegrator >= 5)
rxBits |= 0x800;
pllRamp -= PLL_RAMP_LEN;
rxIntegrator = 0;
if(mode == MODE_RECEIVING)
{
//if(syncCount > 7) error(ERR_SYNC_FAIL);
setState(LOOKING_FOR_SYNC);
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;
}
}
if(syncCount > 10) return true;
else return false;
}
bool W433DataReciver::recivedByte(const uint16_t elapsedTime)
{
timesBuffer[timesBufferIndex] = readPin(_port, _pin) ? 0-elapsedTime : elapsedTime;
++timesBufferIndex;
return timesBufferIndex == 32;
}
uint8_t W433DataReciver::assmbleByte()
{
uint8_t byte = 0;
for(uint8_t i = 0; i < 8; ++i)
{
int8_t bit = reciveBit(i*4);
if(bit >= 0) byte = byte | (bit << (7-i));
else
{
setState(LOOKING_FOR_SYNC);
error(ERR_BYTE_ASM);
}
}
timesBufferIndex = 0;
return byte;
}
void W433DataReciver::error(const uint8_t errorCode)
{
if(_errorCodeHandler != nullptr) (*_errorCodeHandler)(errorCode, _userData);
}
void W433DataReciver::setState(const uint8_t stateIn)
{
TIMSK2 = stateIn == LOOKING_FOR_SYNC;
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)
{
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