Update
This commit is contained in:
6
CL56.cpp
6
CL56.cpp
@ -159,6 +159,12 @@ void DualCl56::setString(const char string[], const uint8_t dp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( (1 << i) & dp ) _segments[i] |= 1;
|
if( (1 << i) & dp ) _segments[i] |= 1;
|
||||||
|
else _segments[i] &= ~1;
|
||||||
}
|
}
|
||||||
if(string[i] == '\0') for(; i < 8; i++) _segments[i]&=SEG_DP;
|
if(string[i] == '\0') for(; i < 8; i++) _segments[i]&=SEG_DP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DualCl56::setSegments(const uint8_t segments, const uint8_t place)
|
||||||
|
{
|
||||||
|
_segments[place] = segments;
|
||||||
|
}
|
||||||
|
19
CL56.h
19
CL56.h
@ -3,19 +3,19 @@
|
|||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include "shiftreg.h"
|
#include "shiftreg.h"
|
||||||
|
|
||||||
#define SEG_A 0b10000000
|
|
||||||
#define SEG_B 0b01000000
|
|
||||||
#define SEG_C 0b00100000
|
|
||||||
#define SEG_D 0b00010000
|
|
||||||
#define SEG_E 0b00001000
|
|
||||||
#define SEG_F 0b00000100
|
|
||||||
#define SEG_G 0b00000010
|
|
||||||
#define SEG_DP 0b00000001
|
|
||||||
|
|
||||||
class DualCl56
|
class DualCl56
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static constexpr uint8_t SEG_A = 0b10000000;
|
||||||
|
static constexpr uint8_t SEG_B = 0b01000000;
|
||||||
|
static constexpr uint8_t SEG_C = 0b00100000;
|
||||||
|
static constexpr uint8_t SEG_D = 0b00010000;
|
||||||
|
static constexpr uint8_t SEG_E = 0b00001000;
|
||||||
|
static constexpr uint8_t SEG_F = 0b00000100;
|
||||||
|
static constexpr uint8_t SEG_G = 0b00000010;
|
||||||
|
static constexpr uint8_t SEG_DP= 0b00000001;
|
||||||
|
|
||||||
static constexpr uint8_t COLEN_A = 0b00000010;
|
static constexpr uint8_t COLEN_A = 0b00000010;
|
||||||
static constexpr uint8_t COLEN_B = 0b00100000;
|
static constexpr uint8_t COLEN_B = 0b00100000;
|
||||||
static constexpr uint8_t DP_A = 0b00000000;
|
static constexpr uint8_t DP_A = 0b00000000;
|
||||||
@ -79,5 +79,6 @@ class DualCl56
|
|||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
void setString(const char* string, const uint8_t dp = 0);
|
void setString(const char* string, const uint8_t dp = 0);
|
||||||
|
void setSegments(const uint8_t segments, const uint8_t place);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ set(COMPILE_FLAGS "" CACHE STRING "Additional Compiler Flags")
|
|||||||
|
|
||||||
# Set own source files
|
# Set own source files
|
||||||
# Simply list all your C / C++ source (not header!) files here
|
# Simply list all your C / C++ source (not header!) files here
|
||||||
set(SRC_FILES main.cpp serial.cpp W433DataReciver.cpp CL56.cpp ds1302.cpp)
|
set(SRC_FILES main.cpp serial.cpp W433DataReciver.cpp CL56.cpp ds1302.cpp dht11.cpp WirelessRelay.cpp item.cpp)
|
||||||
|
|
||||||
# Compiler suite specification
|
# Compiler suite specification
|
||||||
set(CMAKE_C_COMPILER /usr/bin/avr-gcc)
|
set(CMAKE_C_COMPILER /usr/bin/avr-gcc)
|
||||||
|
@ -1,231 +1,144 @@
|
|||||||
#include "W433DataReciver.h"
|
#include "W433DataReciver.h"
|
||||||
|
#include <util/crc16.h>
|
||||||
#include "writepin.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::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*) ):
|
W433DataReciver::W433DataReciver(volatile unsigned char* const portIn, const unsigned char pinIn,
|
||||||
_port(port), _pin(pin), _timerRegister(timerRegister), _timerOverflowRegister(timerOverflowRegister), _packetCallback(packetCallback), _errorCodeHandler(errorCodeHandler), _userData(userData)
|
void (*packetCallbackIn)(uint32_t, void*), void* userDataIn,
|
||||||
|
void (*errorCodeHandlerIn)(uint8_t, void*)):
|
||||||
|
port(portIn), pin(pinIn),
|
||||||
|
packetCallback(packetCallbackIn), errorCodeHandler(errorCodeHandlerIn), userData(userDataIn)
|
||||||
{
|
{
|
||||||
instance = this;
|
instance = this;
|
||||||
for(uint8_t i = 0; i < 33; i++) timesBuffer[i] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
W433DataReciver::~W433DataReciver()
|
W433DataReciver::~W433DataReciver()
|
||||||
{
|
{
|
||||||
instance = nullptr;
|
instance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void W433DataReciver::staticInterrupt()
|
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(
|
uint16_t crc = 0xffff;
|
||||||
timesBuffer[index] < 0 &&
|
uint8_t* ptr = reinterpret_cast<uint8_t*>(&data);
|
||||||
isTime(timesBuffer[index+1], SMALL_TIME, true, SMALL_TIME_TOLERANCE) &&
|
for(size_t i = 0; i < sizeof(data); ++i)
|
||||||
isTime(timesBuffer[index+2], LARGE_TIME, false, LARGE_TIME_TOLERANCE) //&&
|
crc = _crc_ccitt_update(crc, ptr[i]);
|
||||||
//isTime(timesBuffer[index+3], SMALL_TIME, true, SMALL_TIME_TOLERANCE)
|
return crc;
|
||||||
)
|
|
||||||
{
|
|
||||||
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)
|
uint8_t W433DataReciver::symbolDecode(uint8_t symbol)
|
||||||
{
|
{
|
||||||
uint16_t counter = 0;
|
switch(symbol)
|
||||||
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;
|
case 0xe:
|
||||||
else
|
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);
|
if (++rxCount >= 12)
|
||||||
setState(LOOKING_FOR_SYNC);
|
{
|
||||||
|
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()
|
void W433DataReciver::interrupt()
|
||||||
{
|
{
|
||||||
uint16_t elapsedTime = polarity*(((*_timerOverflowRegister & 0x01) ? *_timerRegister+(UINT16_MAX - previousTime) : *_timerRegister - previousTime)/TICKS_PER_US);
|
pll(readPin(port, pin));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_RINGBUFFER
|
uint16_t W433DataReciver::calculateOverflowRegister(uint16_t bitRate, uint16_t devisor)
|
||||||
RingBuffer<W433DataReciver::RINGBUFFER_LENGTH, uint8_t>* W433DataReciver::getRingBuffer()
|
|
||||||
{
|
{
|
||||||
return &_ringBuffer;
|
return (F_CPU /(8UL*devisor))/bitRate;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -1,94 +1,63 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
|
||||||
#include "ringbuffer.h"
|
|
||||||
|
|
||||||
//#define USE_RINGBUFFER
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
class W433DataReciver
|
class W433DataReciver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr int ERROR_CRC = 1;
|
||||||
|
|
||||||
static constexpr uint8_t RINGBUFFER_LENGTH = 32;
|
static constexpr int SAMPLES_PER_BIT = 8;
|
||||||
|
static constexpr int PLL_RAMP_LEN = 160;
|
||||||
//errors
|
static constexpr int PLL_RAMP_INC_STEP = PLL_RAMP_LEN/SAMPLES_PER_BIT;
|
||||||
static constexpr uint8_t ERR_SYNC_FAIL = 1;
|
static constexpr int PLL_RAMP_TRANSITION = PLL_RAMP_LEN/2;
|
||||||
static constexpr uint8_t ERR_NO_SYNC_END = 2;
|
static constexpr int PLL_RAMP_INC_RETARD = PLL_RAMP_INC_STEP-9;
|
||||||
static constexpr uint8_t ERR_BYTE_ASM = 3;
|
static constexpr int PLL_RAMP_INC_ADVANCE = PLL_RAMP_INC_STEP+9;
|
||||||
static constexpr uint8_t ERR_WRONG_SIG = 4;
|
static constexpr int PLL_HEADER_LEN_BITS = 8;
|
||||||
static constexpr uint8_t ERR_CHECKSUM = 5;
|
static constexpr int PACKET_LENGTH = sizeof(uint32_t)+2;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static W433DataReciver* instance;
|
static constexpr int MODE_SEARCHING = 0;
|
||||||
|
static constexpr int MODE_RECEIVING = 1;
|
||||||
|
|
||||||
//constants
|
static W433DataReciver* instance;
|
||||||
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;
|
|
||||||
|
|
||||||
static constexpr int8_t polarity = 1;
|
volatile unsigned char *port;
|
||||||
|
unsigned char pin;
|
||||||
|
|
||||||
static constexpr uint8_t LOOKING_FOR_SYNC = 0;
|
bool prevSample = 0;
|
||||||
static constexpr uint8_t LOOKING_FOR_SYNC_END = 1;
|
uint8_t pllRamp = 0;
|
||||||
static constexpr uint8_t LOOKING_FOR_SIGNATURE = 2;
|
uint8_t rxIntegrator = 0;
|
||||||
static constexpr uint8_t RECVING_PACKET = 3;
|
|
||||||
static constexpr uint8_t RECVING_PACKET_CHECKSUM = 4;
|
|
||||||
|
|
||||||
//variables
|
uint16_t rxBits = 0;
|
||||||
volatile unsigned char *_port;
|
|
||||||
unsigned char _pin;
|
|
||||||
|
|
||||||
volatile uint16_t *_timerRegister;
|
uint8_t mode = MODE_SEARCHING;
|
||||||
volatile uint8_t *_timerOverflowRegister;
|
|
||||||
|
|
||||||
#ifdef USE_RINGBUFFER
|
uint8_t rxBuf[PACKET_LENGTH];
|
||||||
RingBuffer<RINGBUFFER_LENGTH, uint8_t> _ringBuffer;
|
uint8_t rxCount = 0;
|
||||||
#endif
|
volatile uint8_t rxLen = 0;
|
||||||
|
|
||||||
volatile uint16_t previousTime = 0;
|
void (* const packetCallback)(uint32_t, void*);
|
||||||
volatile uint8_t timesBufferIndex = 0;
|
void (* const errorCodeHandler)(uint8_t, void*);
|
||||||
volatile int16_t timesBuffer[33];
|
void* const userData;
|
||||||
|
|
||||||
volatile uint8_t packetIndex = 0;
|
private:
|
||||||
volatile uint32_t packet = 0;
|
|
||||||
|
|
||||||
void (* const _packetCallback)(uint32_t, void*);
|
static uint16_t calcCrc(uint32_t data);
|
||||||
void (* const _errorCodeHandler)(uint8_t, void*);
|
static uint8_t symbolDecode(uint8_t symbol);
|
||||||
void* const _userData;
|
void pll(bool sample);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
public:
|
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,
|
||||||
~W433DataReciver();
|
void*),
|
||||||
static void initTimer();
|
void* userDataIn = nullptr, void (*errorCodeHandlerIn)(uint8_t, void*) = nullptr );
|
||||||
static void staticInterrupt();
|
~W433DataReciver();
|
||||||
void waitForReciveIdle(const uint16_t timeoutMs = 10000);
|
|
||||||
void interrupt();
|
static void staticInterrupt();
|
||||||
#ifdef USE_RINGBUFFER
|
void interrupt();
|
||||||
RingBuffer<RINGBUFFER_LENGTH, uint8_t>* getRingBuffer();
|
|
||||||
#endif
|
static uint16_t calculateOverflowRegister(uint16_t bitRate, uint16_t devisor);
|
||||||
};
|
};
|
||||||
|
239
main.cpp
239
main.cpp
@ -15,11 +15,20 @@
|
|||||||
#include "ds1302.h"
|
#include "ds1302.h"
|
||||||
#include "sensor.h"
|
#include "sensor.h"
|
||||||
#include "pwm.h"
|
#include "pwm.h"
|
||||||
|
#include "dht11.h"
|
||||||
|
#include "WirelessRelay.h"
|
||||||
|
|
||||||
|
//#define HAS_DHT
|
||||||
|
#define HAS_TRANSMITTER
|
||||||
|
//#define HAS_RECIVER
|
||||||
|
|
||||||
#define MAX_SENSORS 32
|
#define MAX_SENSORS 32
|
||||||
#define COMMAND_BUFFER_SIZE 64
|
#define COMMAND_BUFFER_SIZE 64
|
||||||
#define SNPRINTF_BUFFER_SIZE 96
|
#define SNPRINTF_BUFFER_SIZE 96
|
||||||
|
|
||||||
|
#define welcomeString "HELO "
|
||||||
|
static constexpr bool bdayMsg = false;
|
||||||
|
|
||||||
void buttonHandler(uint8_t index, uint8_t type, void* data);
|
void buttonHandler(uint8_t index, uint8_t type, void* data);
|
||||||
SVector<Sensor, MAX_SENSORS> sensors;
|
SVector<Sensor, MAX_SENSORS> sensors;
|
||||||
ShiftReg<16> shiftReg(&PORTB, PB3, PB2, PB1);
|
ShiftReg<16> shiftReg(&PORTB, PB3, PB2, PB1);
|
||||||
@ -27,11 +36,30 @@ DS1302 clock(&PORTC, &PINC, &DDRC, PC0, PC2, PC1);
|
|||||||
DualCl56 display(&shiftReg);
|
DualCl56 display(&shiftReg);
|
||||||
Buttons buttons(&buttonHandler);
|
Buttons buttons(&buttonHandler);
|
||||||
|
|
||||||
|
#ifdef HAS_DHT
|
||||||
|
#define DPY_FIXED_ITEMS 4
|
||||||
|
#else
|
||||||
|
#define DPY_FIXED_ITEMS 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static constexpr uint8_t almA = 0b01;
|
||||||
|
static constexpr uint8_t almB = 0b10;
|
||||||
|
|
||||||
uint8_t displaying = 0;
|
uint8_t displaying = 0;
|
||||||
|
uint8_t alm = 0;
|
||||||
|
|
||||||
|
volatile bool setting = false;
|
||||||
|
volatile int8_t settingOffset = 0;
|
||||||
|
|
||||||
|
volatile bool ringging = false;
|
||||||
|
|
||||||
char buffer[SNPRINTF_BUFFER_SIZE];
|
char buffer[SNPRINTF_BUFFER_SIZE];
|
||||||
|
|
||||||
volatile bool sensorsPaused=true;
|
volatile bool sensorsPaused = true;
|
||||||
|
|
||||||
|
volatile bool relaySetting = false;
|
||||||
|
|
||||||
|
volatile uint8_t timer = 0;
|
||||||
|
|
||||||
ISR(INT1_vect)
|
ISR(INT1_vect)
|
||||||
{
|
{
|
||||||
@ -42,15 +70,40 @@ ISR(TIMER2_OVF_vect)
|
|||||||
{
|
{
|
||||||
display.tick();
|
display.tick();
|
||||||
buttons.tick();
|
buttons.tick();
|
||||||
|
if(ringging && ((timer % 4 == 0 && timer < 128) || (timer > 128 && timer % 16 == 0)) ) writePin(&PORTD, PD4, true);
|
||||||
|
else writePin(&PORTD, PD4, false);
|
||||||
|
++timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buttonHandler(uint8_t index, uint8_t type, void* data)
|
void buttonHandler(uint8_t index, uint8_t type, void* data)
|
||||||
{
|
{
|
||||||
if(index == 0 && type == Buttons::RELEASED)
|
if(!setting)
|
||||||
{
|
{
|
||||||
if(++displaying < sensors.count()+2);
|
if(index == 0 && type == Buttons::RELEASED)
|
||||||
else displaying = 0;
|
{
|
||||||
}
|
if(++displaying < sensors.count()+DPY_FIXED_ITEMS);
|
||||||
|
else displaying = 0;
|
||||||
|
}
|
||||||
|
else if(index == 0 && type == Buttons::LONG_PRESSED)
|
||||||
|
{
|
||||||
|
relaySetting = !relaySetting;
|
||||||
|
}
|
||||||
|
else if(index == 1 && type == Buttons::RELEASED )
|
||||||
|
{
|
||||||
|
if(!ringging) if(++alm > 3) alm = 0;
|
||||||
|
else ringging = false;
|
||||||
|
}
|
||||||
|
else if(index == 1 && type == Buttons::LONG_PRESSED )
|
||||||
|
{
|
||||||
|
setting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(index == 1 && type == Buttons::LONG_PRESSED ) setting = false;
|
||||||
|
else if(index == 0 && type == Buttons::RELEASED ) settingOffset += 10;
|
||||||
|
else if(index == 1 && type == Buttons::RELEASED ) settingOffset -= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSensor(const Sensor& sensor, Serial* serial)
|
void printSensor(const Sensor& sensor, Serial* serial)
|
||||||
@ -152,7 +205,7 @@ void serialDispatch(Serial* serial, SVector<Sensor, MAX_SENSORS>* sensors)
|
|||||||
DS1302::Timeval time = {atoi(sec),atoi(min),atoi(hour),atoi(day),atoi(mon),atoi(year)};
|
DS1302::Timeval time = {atoi(sec),atoi(min),atoi(hour),atoi(day),atoi(mon),atoi(year)};
|
||||||
clock.setTime(time);
|
clock.setTime(time);
|
||||||
serial->write_p(PSTR("date and time set\n"));
|
serial->write_p(PSTR("date and time set\n"));
|
||||||
display.setString("SET");
|
display.setString("SET ");
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
}
|
}
|
||||||
else serial->write_p(PSTR("usage: set [yyyy] [mm] [dd] [hh] [mm] [ss]\n"));
|
else serial->write_p(PSTR("usage: set [yyyy] [mm] [dd] [hh] [mm] [ss]\n"));
|
||||||
@ -195,13 +248,11 @@ void serialDispatch(Serial* serial, SVector<Sensor, MAX_SENSORS>* sensors)
|
|||||||
}
|
}
|
||||||
else if(strcmp(token, "beep") == 0)
|
else if(strcmp(token, "beep") == 0)
|
||||||
{
|
{
|
||||||
for(uint16_t i = 0; i < 250; ++i)
|
serial->write_p(PSTR("Beeping\n"));
|
||||||
{
|
ringging = true;
|
||||||
writePin(&PORTD, PD4, true);
|
_delay_ms(1000);
|
||||||
_delay_us(500);
|
serial->write_p(PSTR("Done\n"));
|
||||||
writePin(&PORTD, PD4, false);
|
ringging = false;
|
||||||
_delay_us(1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(strcmp(token, "help") == 0)
|
else if(strcmp(token, "help") == 0)
|
||||||
{
|
{
|
||||||
@ -212,7 +263,7 @@ void serialDispatch(Serial* serial, SVector<Sensor, MAX_SENSORS>* sensors)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayItems(const DS1302::Timeval& time)
|
void displayItems(const DS1302::Timeval& time, int16_t temp, int16_t humid)
|
||||||
{
|
{
|
||||||
switch(displaying)
|
switch(displaying)
|
||||||
{
|
{
|
||||||
@ -220,27 +271,64 @@ void displayItems(const DS1302::Timeval& time)
|
|||||||
writePin(&PORTB, PB4, time.sec % 2);
|
writePin(&PORTB, PB4, time.sec % 2);
|
||||||
snprintf(buffer, 9, " %02u%02u", time.hour, time.min);
|
snprintf(buffer, 9, " %02u%02u", time.hour, time.min);
|
||||||
display.setString(buffer);
|
display.setString(buffer);
|
||||||
|
display.setSegments((alm & almA ? DualCl56::SEG_A : 0) | (alm & almB ? DualCl56::SEG_D : 0), 0);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
writePin(&PORTB, PB4, false);
|
writePin(&PORTB, PB4, false);
|
||||||
snprintf(buffer, 9, "%02u%02u%04u", time.day, time.month, time.year);
|
snprintf(buffer, 9, "%02u%02u%04u", time.day, time.month, time.year);
|
||||||
display.setString(buffer, DualCl56::DP_B | DualCl56::DP_D);
|
display.setString(buffer, DualCl56::DP_B | DualCl56::DP_D);
|
||||||
break;
|
break;
|
||||||
|
#ifdef HAS_DHT
|
||||||
|
case 2:
|
||||||
|
writePin(&PORTB, PB4, false);
|
||||||
|
snprintf(buffer, 9, "0 1%4u", temp);
|
||||||
|
display.setString(buffer, DualCl56::DP_G);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
writePin(&PORTB, PB4, false);
|
||||||
|
snprintf(buffer, 9, "0 2%4u", humid);
|
||||||
|
display.setString(buffer, DualCl56::DP_G);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
if(displaying == 2 && sensors.count() == 0) display.setString("0 SENSOR");
|
writePin(&PORTB, PB4, false);
|
||||||
else
|
snprintf(buffer, 9, "%u%3u%4u",
|
||||||
{
|
sensors[displaying-DPY_FIXED_ITEMS].id,
|
||||||
writePin(&PORTB, PB4, false);
|
sensors[displaying-DPY_FIXED_ITEMS].type,
|
||||||
snprintf(buffer, 9, "%u%3u%4u", sensors[displaying-2].id, sensors[displaying-2].type, sensors[displaying-2].field);
|
sensors[displaying-DPY_FIXED_ITEMS].field);
|
||||||
display.setString(buffer, sensors[displaying-2].type == 1 || sensors[displaying-2].type == 2 ? DualCl56::DP_G : 0);
|
display.setString(buffer, sensors[displaying-DPY_FIXED_ITEMS].type == 1 || sensors[displaying-2].type == 2 ? DualCl56::DP_G : 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAlarm(DS1302::Timeval* alarm, uint8_t leadingSegment = 0)
|
||||||
|
{
|
||||||
|
writePin(&PORTB, PB4, true);
|
||||||
|
while(setting)
|
||||||
|
{
|
||||||
|
if(settingOffset+alarm->min > 59)
|
||||||
|
{
|
||||||
|
if(++alarm->hour > 23) alarm->hour = 0;
|
||||||
|
alarm->min = settingOffset+alarm->min-60;
|
||||||
|
}
|
||||||
|
else if(settingOffset+alarm->min < 0)
|
||||||
|
{
|
||||||
|
if(alarm->hour-1 < 0) alarm->hour = 24;
|
||||||
|
--alarm->hour;
|
||||||
|
alarm->min = settingOffset+alarm->min+60;
|
||||||
|
}
|
||||||
|
else alarm->min += settingOffset;
|
||||||
|
settingOffset = 0;
|
||||||
|
snprintf(buffer, 9, "S %02u%02u", alarm->hour, alarm->min);
|
||||||
|
display.setString(buffer);
|
||||||
|
display.setSegments(leadingSegment, 1);
|
||||||
|
}
|
||||||
|
writePin(&PORTB, PB4, false);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
DDRB = (1 << PB1) | ( 1 << PB2) | ( 1 << PB3) | ( 1 << PB4) | ( 1 << PB5);
|
DDRB = (1 << PB1) | ( 1 << PB2) | ( 1 << PB3) | ( 1 << PB4) | ( 1 << PB5);
|
||||||
DDRD = 1<<PD4;
|
DDRD = (1<<PD4) | (1<<PD2);
|
||||||
PORTD |= (1<<PD6) | (1<<PD7);
|
PORTD |= (1<<PD6) | (1<<PD7);
|
||||||
|
|
||||||
TCCR2B = 1<<CS22;
|
TCCR2B = 1<<CS22;
|
||||||
@ -254,42 +342,127 @@ int main()
|
|||||||
sei();
|
sei();
|
||||||
|
|
||||||
Serial serial;
|
Serial serial;
|
||||||
serial.write_p(PSTR("SensorDisplay v0.1 starting\n"));
|
serial.write_p(PSTR("SensorDisplay v0.4 starting\n"));
|
||||||
|
|
||||||
|
DS1302::Timeval alarmA = EEPROM_read_class<DS1302::Timeval>(128);
|
||||||
|
DS1302::Timeval alarmB = EEPROM_read_class<DS1302::Timeval>(128+64);
|
||||||
DS1302::Timeval time = clock.getTime();
|
DS1302::Timeval time = clock.getTime();
|
||||||
|
alm = EEPROM_read_char(0);
|
||||||
|
uint8_t oldAlm = alm;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAS_TRANSMITTER
|
||||||
|
char name[] = "relay";
|
||||||
|
WirelessRelay relay(0b1011010001000000, name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_DHT
|
||||||
|
Dht11 sensor(&PORTD, &PIND, &DDRD, PD2);
|
||||||
|
#endif
|
||||||
if(time.day == 28 && time.month == 5)
|
if(time.day == 28 && time.month == 5)
|
||||||
{
|
{
|
||||||
display.setString("HAPPY");
|
if constexpr(bdayMsg)
|
||||||
_delay_ms(1000);
|
{
|
||||||
display.setString("b-DAY");
|
display.setString("HAPPY ");
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
display.setString("SASA");
|
display.setString("b-DAY ");
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
|
display.setString("SASA ");
|
||||||
|
_delay_ms(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
display.setString("HELOJANA");
|
display.setString(welcomeString);
|
||||||
_delay_ms(1000);
|
_delay_ms(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_DHT
|
||||||
|
sensor.read();
|
||||||
|
_delay_ms(1000);
|
||||||
|
sensor.read();
|
||||||
|
#endif
|
||||||
|
|
||||||
W433DataReciver reciver(&PIND, PD3, &TCNT1, &TIFR1, &packetHandler, reinterpret_cast<void*>(&serial), &reciverError);
|
W433DataReciver reciver(&PIND, PD3, &TCNT1, &TIFR1, &packetHandler, reinterpret_cast<void*>(&serial), &reciverError);
|
||||||
|
|
||||||
uint8_t deleteDate = 0;
|
uint8_t deleteDate = 0;
|
||||||
|
|
||||||
serial.write_p(PSTR("Ready\n"));
|
serial.write_p(PSTR("Ready\n"));
|
||||||
|
|
||||||
|
uint16_t i = 0;
|
||||||
|
|
||||||
|
bool oldRelaySetting = false;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
time = clock.getTime();
|
#ifdef HAS_DHT
|
||||||
displayItems(time);
|
if((displaying == 2 || displaying == 3) && i%2048 == 0)
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
sensor.read();
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(alm != oldAlm)
|
||||||
|
{
|
||||||
|
oldAlm = alm;
|
||||||
|
EEPROM_write_char(0, alm);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_TRANSMITTER
|
||||||
|
if(oldRelaySetting != relaySetting)
|
||||||
|
{
|
||||||
|
writePin(&PORTB, PB4, false);
|
||||||
|
oldRelaySetting = relaySetting;
|
||||||
|
relay.setValue(relaySetting);
|
||||||
|
display.setString( relaySetting ? "RLY ON " : "RLY OFF ");
|
||||||
|
_delay_ms(1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(setting)
|
||||||
|
{
|
||||||
|
setAlarm(&alarmA, DualCl56::SEG_A);
|
||||||
|
setting = true;
|
||||||
|
setAlarm(&alarmB, DualCl56::SEG_D);
|
||||||
|
EEPROM_write_class(128, alarmA);
|
||||||
|
EEPROM_write_class(128+64, alarmB);
|
||||||
|
}
|
||||||
|
|
||||||
|
time = clock.getTime();
|
||||||
|
|
||||||
|
#ifdef HAS_DHT
|
||||||
|
displayItems(time, sensor.temperature, sensor.humidity);
|
||||||
|
#else
|
||||||
|
displayItems(time, 0, 0);
|
||||||
|
#endif
|
||||||
|
if(time.hour == alarmA.hour && time.min == alarmA.min && time.sec == 0)
|
||||||
|
{
|
||||||
|
ringging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(time.hour == alarmB.hour && time.min == alarmB.min && time.sec == 0)
|
||||||
|
{
|
||||||
|
#ifdef HAS_TRANSMITTER
|
||||||
|
relay.setValue(true);
|
||||||
|
#else
|
||||||
|
ringging = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_RECIVER
|
||||||
serialDispatch(&serial, &sensors);
|
serialDispatch(&serial, &sensors);
|
||||||
if(deleteDate != time.day)
|
if(deleteDate != time.day)
|
||||||
{
|
{
|
||||||
displaying = 0;
|
displaying = 0;
|
||||||
sensors.clear();
|
sensors.clear();
|
||||||
deleteDate = time.day;
|
deleteDate = time.day;
|
||||||
|
display.setString("CLEAR ");
|
||||||
|
_delay_ms(1000);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user