#include "W433DataReciver.h" #include "writepin.h" #include #include #include #include #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) { instance = this; for(uint8_t i = 0; i < 33; i++) timesBuffer[i] = 0; } W433DataReciver::~W433DataReciver() { instance = nullptr; } void W433DataReciver::staticInterrupt() { if(instance != nullptr) instance->interrupt(); } int8_t W433DataReciver::reciveBit(uint8_t index) { 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; } void W433DataReciver::waitForReciveIdle(const uint16_t timeoutMs) { 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 { if(syncCount > 4 && syncFailCount < 3) ++syncFailCount; else { //if(syncCount > 7) error(ERR_SYNC_FAIL); setState(LOOKING_FOR_SYNC); } } 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(&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(buffer), sizeof(packet)); #endif if(_packetCallback != nullptr)(*_packetCallback)(packet, _userData); } else error(ERR_CHECKSUM); packet = 0; setState(LOOKING_FOR_SYNC); } } } #ifdef USE_RINGBUFFER RingBuffer* W433DataReciver::getRingBuffer() { return &_ringBuffer; } #endif