Compare commits

..

10 Commits

Author SHA1 Message Date
9be9ccf044 renable display at hour mark
break out of cal loop
2023-10-12 16:02:32 +02:00
70f0f6e34c unblank display only on button release 2023-10-12 15:35:11 +02:00
71969143a5 add display blanking cli option 2023-10-12 15:34:12 +02:00
dcc3669850 fix some compiler warnings 2023-10-12 14:57:59 +02:00
afeaa9f5a7 reformat source in uvosstyle 2023-10-12 14:56:11 +02:00
9f8b9059f9 add missing files, support display blanking 2023-10-12 14:54:29 +02:00
3fc72514a4 increase cmake version 2023-10-12 14:53:47 +02:00
be10365d9f reformat 2023-10-12 14:38:53 +02:00
1d75a5bc77 Cleanup changes 2023-04-03 18:16:58 +02:00
e268d49c48 update to new reciver type 2023-04-03 01:27:03 +02:00
13 changed files with 989 additions and 628 deletions

320
CL56.cpp
View File

@ -1,170 +1,194 @@
#include "CL56.h" #include "CL56.h"
#include <avr/interrupt.h>
DualCl56::DualCl56(ShiftReg<16>* shiftReg): DualCl56::DualCl56(ShiftReg<16>* shiftReg):
_shiftReg(shiftReg) _shiftReg(shiftReg)
{ {
} }
void DualCl56::tick() void DualCl56::tick()
{ {
++_currentLit; ++_currentLit;
if(_currentLit > 7)_currentLit = 0; if(_currentLit > 7)
unsigned char bits[2] = {0b10000000>>_currentLit, ~(_segments[_currentLit])}; _currentLit = 0;
_shiftReg->write(reinterpret_cast<unsigned char*>(&bits));
unsigned char bits[2] = {static_cast<unsigned char>(0b10000000 >> _currentLit),
static_cast<unsigned char>(~(_segments[_currentLit]))
};
if(!_blank)
_shiftReg->write(reinterpret_cast<unsigned char*>(&bits));
} }
void DualCl56::setString(const char string[], const uint8_t dp) void DualCl56::setString(const char string[], const uint8_t dp)
{ {
uint_fast8_t i = 0; uint_fast8_t i = 0;
for(; i < 8 && string[i] != '\0'; i++) for(; i < 8 && string[i] != '\0'; i++)
{ {
switch (string[i]) switch (string[i])
{ {
case '\0': case '\0':
case '\n': case '\n':
case ' ': case ' ':
_segments[i] = 0; _segments[i] = 0;
break; break;
case '0': case '0':
_segments[i] = ZERO; _segments[i] = ZERO;
break; break;
case '1': case '1':
_segments[i] = ONE; _segments[i] = ONE;
break; break;
case '2': case '2':
_segments[i] = TOW; _segments[i] = TOW;
break; break;
case '3': case '3':
_segments[i] = THREE; _segments[i] = THREE;
break; break;
case '4': case '4':
_segments[i] = FOUR; _segments[i] = FOUR;
break; break;
case '5': case '5':
_segments[i] = FIVE; _segments[i] = FIVE;
break; break;
case '6': case '6':
_segments[i] = SIX; _segments[i] = SIX;
break; break;
case '7': case '7':
_segments[i] = SEVEN; _segments[i] = SEVEN;
break; break;
case '8': case '8':
_segments[i] = EIGT; _segments[i] = EIGT;
break; break;
case '9': case '9':
_segments[i] = NINE; _segments[i] = NINE;
break; break;
case 'a': case 'a':
case 'A': case 'A':
_segments[i] = SIGA; _segments[i] = SIGA;
break; break;
case 'b': case 'b':
case 'B': case 'B':
_segments[i] = SIGB; _segments[i] = SIGB;
break; break;
case 'c': case 'c':
_segments[i] = SIGc; _segments[i] = SIGc;
break; break;
case 'C': case 'C':
_segments[i] = SIGC; _segments[i] = SIGC;
break; break;
case 'd': case 'd':
case 'D': case 'D':
_segments[i] = SIGD; _segments[i] = SIGD;
break; break;
case 'e': case 'e':
case 'E': case 'E':
_segments[i] = SIGE; _segments[i] = SIGE;
break; break;
case 'f': case 'f':
case 'F': case 'F':
_segments[i] = SIGF; _segments[i] = SIGF;
break; break;
case 'g': case 'g':
case 'G': case 'G':
_segments[i] = SIGG; _segments[i] = SIGG;
break; break;
case 'h': case 'h':
_segments[i] = SIGh; _segments[i] = SIGh;
break; break;
case 'H': case 'H':
_segments[i] = SIGH; _segments[i] = SIGH;
break; break;
case 'i': case 'i':
case 'I': case 'I':
_segments[i] = SIGI; _segments[i] = SIGI;
break; break;
case 'j': case 'j':
case 'J': case 'J':
_segments[i] = SIGJ; _segments[i] = SIGJ;
break; break;
case 'l': case 'l':
_segments[i] = SIGl; _segments[i] = SIGl;
break; break;
case 'L': case 'L':
_segments[i] = SIGL; _segments[i] = SIGL;
break; break;
case 'n': case 'n':
case 'N': case 'N':
_segments[i] = SIGN; _segments[i] = SIGN;
break; break;
case 'o': case 'o':
_segments[i] = SIGo; _segments[i] = SIGo;
break; break;
case 'O': case 'O':
_segments[i] = SIGO; _segments[i] = SIGO;
break; break;
case 'p': case 'p':
case 'P': case 'P':
_segments[i] = SIGP; _segments[i] = SIGP;
break; break;
case 'r': case 'r':
case 'R': case 'R':
_segments[i] = SIGR; _segments[i] = SIGR;
break; break;
case 's': case 's':
case 'S': case 'S':
_segments[i] = SIGS; _segments[i] = SIGS;
break; break;
case 't': case 't':
case 'T': case 'T':
_segments[i] = SIGT; _segments[i] = SIGT;
break; break;
case 'u': case 'u':
case 'U': case 'U':
_segments[i] = SIGU; _segments[i] = SIGU;
break; break;
case 'v': case 'v':
case 'V': case 'V':
_segments[i] = SIGV; _segments[i] = SIGV;
break; break;
case 'x': case 'x':
case 'X': case 'X':
_segments[i] = SIGX; _segments[i] = SIGX;
break; break;
case 'y': case 'y':
case 'Y': case 'Y':
_segments[i] = SIGY; _segments[i] = SIGY;
break; break;
case '-': case '-':
_segments[i] = MINUS; _segments[i] = MINUS;
break; break;
default: default:
_segments[i] = INVLD; _segments[i] = INVLD;
break; break;
} }
if( (1 << i) & dp ) _segments[i] |= 1; if( (1 << i) & dp ) _segments[i] |= 1;
else _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) void DualCl56::setSegments(const uint8_t segments, const uint8_t place)
{ {
_segments[place] = segments; _segments[place] = segments;
} }
void DualCl56::setBlank(bool blankIn)
{
_blank = blankIn;
if(_blank)
{
cli();
_shiftReg->clear();
_shiftReg->clear();
sei();
}
}
bool DualCl56::getBlank()
{
return _blank;
}

117
CL56.h
View File

@ -5,7 +5,7 @@
class DualCl56 class DualCl56
{ {
public: public:
static constexpr uint8_t SEG_A = 0b10000000; static constexpr uint8_t SEG_A = 0b10000000;
static constexpr uint8_t SEG_B = 0b01000000; static constexpr uint8_t SEG_B = 0b01000000;
@ -16,69 +16,72 @@ class DualCl56
static constexpr uint8_t SEG_G = 0b00000010; static constexpr uint8_t SEG_G = 0b00000010;
static constexpr uint8_t SEG_DP= 0b00000001; 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;
static constexpr uint8_t DP_B = 0b00000001; static constexpr uint8_t DP_B = 0b00000001;
static constexpr uint8_t DP_C = 0b00000100; static constexpr uint8_t DP_C = 0b00000100;
static constexpr uint8_t DP_D = 0b00001000; static constexpr uint8_t DP_D = 0b00001000;
static constexpr uint8_t DP_E = 0b00000000; static constexpr uint8_t DP_E = 0b00000000;
static constexpr uint8_t DP_F = 0b00010000; static constexpr uint8_t DP_F = 0b00010000;
static constexpr uint8_t DP_G = 0b01000000; static constexpr uint8_t DP_G = 0b01000000;
static constexpr uint8_t DP_H = 0b10000000; static constexpr uint8_t DP_H = 0b10000000;
private: private:
static constexpr uint8_t ZERO = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F; static constexpr uint8_t ZERO = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
static constexpr uint8_t ONE = SEG_B | SEG_C; static constexpr uint8_t ONE = SEG_B | SEG_C;
static constexpr uint8_t TOW = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D; static constexpr uint8_t TOW = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D;
static constexpr uint8_t THREE = SEG_A | SEG_B | SEG_C | SEG_D | SEG_G; static constexpr uint8_t THREE = SEG_A | SEG_B | SEG_C | SEG_D | SEG_G;
static constexpr uint8_t FOUR = SEG_B | SEG_C | SEG_F | SEG_G; static constexpr uint8_t FOUR = SEG_B | SEG_C | SEG_F | SEG_G;
static constexpr uint8_t FIVE =SEG_A | SEG_C | SEG_D | SEG_F | SEG_G; static constexpr uint8_t FIVE =SEG_A | SEG_C | SEG_D | SEG_F | SEG_G;
static constexpr uint8_t SIX = SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G; static constexpr uint8_t SIX = SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t SEVEN= SEG_A | SEG_B | SEG_C; static constexpr uint8_t SEVEN= SEG_A | SEG_B | SEG_C;
static constexpr uint8_t EIGT = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G; static constexpr uint8_t EIGT = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t NINE = SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G; static constexpr uint8_t NINE = SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G;
static constexpr uint8_t MINUS = SEG_G; static constexpr uint8_t MINUS = SEG_G;
static constexpr uint8_t SIGA = SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G; static constexpr uint8_t SIGA = SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t SIGB = SEG_F | SEG_E | SEG_D | SEG_C | SEG_G; static constexpr uint8_t SIGB = SEG_F | SEG_E | SEG_D | SEG_C | SEG_G;
static constexpr uint8_t SIGC = SEG_A | SEG_D | SEG_E | SEG_F; static constexpr uint8_t SIGC = SEG_A | SEG_D | SEG_E | SEG_F;
static constexpr uint8_t SIGc = SEG_G | SEG_D | SEG_E; static constexpr uint8_t SIGc = SEG_G | SEG_D | SEG_E;
static constexpr uint8_t SIGD = SEG_B | SEG_C | SEG_D | SEG_G | SEG_E; static constexpr uint8_t SIGD = SEG_B | SEG_C | SEG_D | SEG_G | SEG_E;
static constexpr uint8_t SIGE = SEG_A | SEG_D | SEG_E | SEG_F | SEG_G; static constexpr uint8_t SIGE = SEG_A | SEG_D | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t SIGF = SEG_A | SEG_E | SEG_F | SEG_G; static constexpr uint8_t SIGF = SEG_A | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t SIGG = NINE; static constexpr uint8_t SIGG = NINE;
static constexpr uint8_t SIGH = SEG_B | SEG_C | SEG_E | SEG_F | SEG_G; static constexpr uint8_t SIGH = SEG_B | SEG_C | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t SIGh = SEG_D | SEG_C | SEG_E | SEG_F | SEG_G; static constexpr uint8_t SIGh = SEG_D | SEG_C | SEG_E | SEG_F | SEG_G;
static constexpr uint8_t SIGI = SEG_E; static constexpr uint8_t SIGI = SEG_E;
static constexpr uint8_t SIGJ = SEG_B | SEG_C | SEG_D; static constexpr uint8_t SIGJ = SEG_B | SEG_C | SEG_D;
static constexpr uint8_t SIGL = SEG_F | SEG_E | SEG_D; static constexpr uint8_t SIGL = SEG_F | SEG_E | SEG_D;
static constexpr uint8_t SIGl = SEG_F | SEG_E; static constexpr uint8_t SIGl = SEG_F | SEG_E;
static constexpr uint8_t SIGN = SEG_C | SEG_E | SEG_G; static constexpr uint8_t SIGN = SEG_C | SEG_E | SEG_G;
static constexpr uint8_t SIGO = ZERO; static constexpr uint8_t SIGO = ZERO;
static constexpr uint8_t SIGo = SEG_E | SEG_G | SEG_C | SEG_D; static constexpr uint8_t SIGo = SEG_E | SEG_G | SEG_C | SEG_D;
static constexpr uint8_t SIGP = SEG_A | SEG_B | SEG_G | SEG_F | SEG_E; static constexpr uint8_t SIGP = SEG_A | SEG_B | SEG_G | SEG_F | SEG_E;
static constexpr uint8_t SIGR = SEG_G | SEG_E; static constexpr uint8_t SIGR = SEG_G | SEG_E;
static constexpr uint8_t SIGS = SEG_A | SEG_C | SEG_D | SEG_F | SEG_G; static constexpr uint8_t SIGS = SEG_A | SEG_C | SEG_D | SEG_F | SEG_G;
static constexpr uint8_t SIGT = SEG_F | SEG_E | SEG_C | SEG_D; static constexpr uint8_t SIGT = SEG_F | SEG_E | SEG_C | SEG_D;
static constexpr uint8_t SIGU = SEG_B | SEG_C | SEG_D | SEG_E | SEG_F; static constexpr uint8_t SIGU = SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
static constexpr uint8_t SIGV = SIGU; static constexpr uint8_t SIGV = SIGU;
static constexpr uint8_t SIGX = SIGH; static constexpr uint8_t SIGX = SIGH;
static constexpr uint8_t SIGY = SEG_F | SEG_B | SEG_G | SEG_E; static constexpr uint8_t SIGY = SEG_F | SEG_B | SEG_G | SEG_E;
static constexpr uint8_t INVLD = SEG_A | SEG_D; static constexpr uint8_t INVLD = SEG_A | SEG_D;
uint8_t _currentLit = 0; uint8_t _currentLit = 0;
uint8_t _segments[8] = {SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_G, SEG_DP, FIVE}; uint8_t _segments[8] = {SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_G, SEG_DP, FIVE};
ShiftReg<16>* _shiftReg; ShiftReg<16>* _shiftReg;
public: bool _blank = false;
DualCl56(ShiftReg<16>* shiftReg); public:
void tick(); DualCl56(ShiftReg<16>* shiftReg);
void setString(const char* string, const uint8_t dp = 0); void tick();
void setBlank(bool blank);
bool getBlank();
void setString(const char* string, const uint8_t dp = 0);
void setSegments(const uint8_t segments, const uint8_t place); void setSegments(const uint8_t segments, const uint8_t place);
}; };

View File

@ -2,11 +2,12 @@
## Adjust the settings according to your board. ## Adjust the settings according to your board.
## The settings here work for the Arduino Uno, Rev. 3. ## The settings here work for the Arduino Uno, Rev. 3.
# CMake version
cmake_minimum_required(VERSION 3.20)
# Project name # Project name
project(SensorDisplay) project(SensorDisplay)
# CMake version
cmake_minimum_required(VERSION 2.6)
# Options # Options
# Adjust to your board # Adjust to your board

85
WirelessRelay.cpp Normal file
View File

@ -0,0 +1,85 @@
#include"WirelessRelay.h"
#include <avr/io.h>
#include <string.h>
volatile unsigned char *_port = &PORTD;
unsigned char _pin = PD2;
void WirelessRelay::sendId()
{
writePin(_port,_pin,true);
_delay_us(SMALL_TIME);
writePin(_port,_pin,false);
_delay_us(LARGE_TIME);
for(short i = 0; i<10; i++)
{
sendBit( id & 1 << (15 - i) );
}
}
void WirelessRelay::sendBit(const bool in)
{
switch(in)
{
case true:
//Der Code fuer '0'
writePin(_port,_pin,true);
_delay_us(SMALL_TIME);
writePin(_port,_pin,false);
_delay_us(LARGE_TIME);
writePin(_port,_pin,true);
_delay_us(SMALL_TIME);
writePin(_port,_pin,false);
_delay_us(LARGE_TIME);
break;
case false:
//Der Code fuer '1'
writePin(_port,_pin,true);
_delay_us(LARGE_TIME);
writePin(_port,_pin,false);
_delay_us(SMALL_TIME);
writePin(_port,_pin,true);
_delay_us(SMALL_TIME);
writePin(_port,_pin,false);
_delay_us(LARGE_TIME);
break;
}
}
void WirelessRelay::sync()
{
writePin(_port,_pin,false);
_delay_us(SMALL_TIME*31);
}
void WirelessRelay::setValue(const uint8_t value)
{
lastValue = value;
for(short z = 0; z<10; z++)
{
sendId();
sendBit(value);
sendBit(!value);
sync();
}
}
void WirelessRelay::resend()
{
setValue(lastValue);
}
WirelessRelay::WirelessRelay(const uint16_t idIn, char nameIn[])
{
id = idIn;
setName(nameIn);
type = 0;
}
WirelessRelay::WirelessRelay(const Item& item)
{
Item::operator=(item);
type = 0;
}

27
WirelessRelay.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef RF433_H
#define RF433_H
#include<util/delay.h>
#include"writepin.h"
#include "item.h"
class WirelessRelay: public Item
{
public:
static constexpr uint16_t LARGE_TIME = 750;
static constexpr uint8_t SMALL_TIME = 250;
static constexpr uint16_t MAX_NAME_LENGTH = 16;
private:
void sendBit(const bool i);
void sync();
void sendId();
public:
WirelessRelay(const uint16_t idIn, char nameIn[]);
WirelessRelay(const Item& item);
void setValue(const uint8_t value);
void resend();
};
#endif

90
dht11.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "dht11.h"
Dht11::Dht11(volatile unsigned char * const port, volatile unsigned char * const inPort,
volatile unsigned char * const port_ctl, const unsigned char pin): _port(port), _port_ctl(port_ctl), _inPort(inPort),
_pin(pin)
{}
uint8_t Dht11::read()
{
// BUFFER TO RECEIVE
uint8_t bits[5];
uint8_t cnt = 7;
uint8_t idx = 0;
// EMPTY BUFFER
for (uint8_t i=0; i< 5; i++) bits[i] = 0;
// REQUEST SAMPLE
setDirection(_port_ctl, _pin, true);
writePin(_port, _pin, false);
_delay_ms(18);
writePin(_port, _pin, true);
setDirection(_port_ctl, _pin, false);
_delay_us(42);
// ACKNOWLEDGE or TIMEOUT
unsigned int loopCnt = LOOP_TIMEOUT_COUNT;
while(!readPin(_inPort, _pin)) if (loopCnt-- == 0) return 1;
loopCnt = LOOP_TIMEOUT_COUNT;
while(readPin(_inPort, _pin) ) if (loopCnt-- == 0) return 2;
PORTD |= 1 << PD1;
PORTD &= ~(1 << PD1);
PORTD |= 1 << PD1;
PORTD &= ~(1 << PD1);
// READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT
for (uint8_t i=0; i<40; i++)
{
loopCnt = LOOP_TIMEOUT_COUNT;
while(!readPin(_inPort, _pin))
if (loopCnt-- == 0)
{
PORTD |= 1 << PD1;
return 3;
}
loopCnt = 0;
while(readPin(_inPort, _pin))
{
_delay_us(10);
if (loopCnt++ > LOOP_TIMEOUT_SMALL_COUNT) return 4;
}
if( loopCnt > BIT_COUNT )
{
PORTD |= 1 << PD1;
PORTD &= ~(1 << PD1);
bits[idx] |= (1 << cnt);
}
if (cnt == 0) // next byte?
{
cnt = 7; // restart at MSB
idx++; // next byte!
}
else cnt--;
}
uint8_t sum;
if constexpr(DHT22) sum= bits[0] + bits[1] + bits[2] + bits[3];
else sum = bits[0] + bits[2];
if((bits[4] == sum && sum != 0) || true)
{
if constexpr(DHT22)
{
humidity = (static_cast<uint16_t>(bits[0]) << 8) + bits[1];
temperature = (static_cast<uint16_t>((bits[2] & 0b01111111) << 8) + bits[3]);
if(bits[2] & 0b10000000) temperature=temperature*-1;
}
else
{
humidity = bits[0]*10;
temperature = bits[2]*10;
}
return 0;
}
else return 5;
}

24
dht11.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
#include<util/delay.h>
#include "writepin.h"
class Dht11
{
static constexpr uint16_t LOOP_TIMEOUT_COUNT = (10000.0 / 16000000.0)*F_CPU;
static constexpr uint8_t LOOP_TIMEOUT_SMALL_COUNT = (100.0 / 16000000.0)*F_CPU;
static constexpr uint8_t BIT_COUNT = 5;//(6.0 / 16000000.0)*F_CPU;
static constexpr bool DHT22 = true;
volatile unsigned char * const _port;
volatile unsigned char * const _port_ctl;
volatile unsigned char * const _inPort;
const unsigned char _pin;
public:
Dht11(volatile unsigned char * const port, volatile unsigned char * const inPort,
volatile unsigned char * const port_ctl, const unsigned char pin);
uint8_t read();
int16_t humidity = 0;
int16_t temperature = 0;
};

9
item.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "item.h"
#include "string.h"
void Item::setName(const char * const nameN)
{
size_t len = strlen(nameN);
if(len < MAX_NAME_LENGTH)memcpy(name, nameN, len+1);
}

14
item.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
class Item
{
public:
static constexpr uint16_t MAX_NAME_LENGTH = 16;
bool lastValue = 0;
uint16_t id;
char name[MAX_NAME_LENGTH]="";
uint8_t type = 0;
void setName(const char * const name);
};

503
main.cpp
View File

@ -18,17 +18,19 @@
#include "dht11.h" #include "dht11.h"
#include "WirelessRelay.h" #include "WirelessRelay.h"
//#define HAS_DHT #define HAS_DHT
#define HAS_TRANSMITTER //#define HAS_TRANSMITTER
//#define HAS_RECIVER #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 " #define welcomeString "HELOJANA"
static constexpr bool bdayMsg = false; static constexpr bool bdayMsg = false;
static constexpr int timeOffsetSeconds = 6;
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);
@ -55,28 +57,41 @@ volatile bool ringging = false;
char buffer[SNPRINTF_BUFFER_SIZE]; char buffer[SNPRINTF_BUFFER_SIZE];
volatile bool sensorsPaused = true; volatile bool sensorsPaused = false;
volatile bool relaySetting = false; volatile bool relaySetting = false;
volatile uint8_t timer = 0; volatile uint8_t timer = 0;
volatile uint8_t displayDevider = 1;
ISR(INT1_vect) ISR(TIMER1_COMPA_vect)
{ {
W433DataReciver::staticInterrupt(); TIMSK2 = 0;
W433DataReciver::staticInterrupt();
writePin(&PORTB, PB5, !readPin(&PORTB, PB5));
TIMSK2 = 1;
} }
ISR(TIMER2_OVF_vect) ISR(TIMER2_OVF_vect)
{ {
display.tick(); if(timer % displayDevider == 0)
buttons.tick(); display.tick();
if(ringging && ((timer % 4 == 0 && timer < 128) || (timer > 128 && timer % 16 == 0)) ) writePin(&PORTD, PD4, true); buttons.tick();
else writePin(&PORTD, PD4, false); if(ringging && ((timer % 4 == 0 && timer < 128) || (timer > 128 && timer % 16 == 0)))
writePin(&PORTD, PD4, true);
else
writePin(&PORTD, PD4, false);
++timer; ++timer;
} }
void buttonHandler(uint8_t index, uint8_t type, void* data) void buttonHandler(uint8_t index, uint8_t type, void* data)
{ {
if(display.getBlank() && type == Buttons::RELEASED)
{
display.setBlank(false);
return;
}
if(!setting) if(!setting)
{ {
if(index == 0 && type == Buttons::RELEASED) if(index == 0 && type == Buttons::RELEASED)
@ -88,10 +103,17 @@ void buttonHandler(uint8_t index, uint8_t type, void* data)
{ {
relaySetting = !relaySetting; relaySetting = !relaySetting;
} }
else if(index == 1 && type == Buttons::RELEASED ) else if(index == 1 && type == Buttons::RELEASED)
{ {
if(!ringging) if(++alm > 3) alm = 0; if(!ringging)
else ringging = false; {
if(++alm > 3)
alm = 0;
}
else
{
ringging = false;
}
} }
else if(index == 1 && type == Buttons::LONG_PRESSED ) else if(index == 1 && type == Buttons::LONG_PRESSED )
{ {
@ -108,40 +130,45 @@ void buttonHandler(uint8_t index, uint8_t type, void* data)
void printSensor(const Sensor& sensor, Serial* serial) void printSensor(const Sensor& sensor, Serial* serial)
{ {
serial->write_p(PSTR("SENSOR TYPE: ")); serial->write_p(PSTR("SENSOR TYPE: "));
serial->write(sensor.type); serial->write(sensor.type);
serial->write_p(PSTR(" ID: ")); serial->write_p(PSTR(" ID: "));
serial->write(sensor.id); serial->write(sensor.id);
if(sensor.type == 1) serial->write_p(PSTR(" TEMPERATURE: ")); if(sensor.type == 1)
else if(sensor.type == 2) serial->write_p(PSTR(" HUMIDITY: ")); serial->write_p(PSTR(" TEMPERATURE: "));
else serial->write_p(PSTR(" FIELD: ")); else if(sensor.type == 2)
serial->write(sensor.field); serial->write_p(PSTR(" HUMIDITY: "));
serial->putChar('\n'); else
serial->write_p(PSTR(" FIELD: "));
serial->write(sensor.field);
serial->putChar('\n');
} }
void packetHandler(uint32_t packet, void* data) void packetHandler(uint32_t packet, void* data)
{ {
Serial* serial = reinterpret_cast<Serial*>(data); Serial* serial = reinterpret_cast<Serial*>(data);
Sensor sensor; Sensor sensor;
sensor.field = packet & 0x0000FFFF; sensor.field = packet & 0x0000FFFF;
sensor.type = packet >> 24; sensor.type = packet >> 24;
sensor.id = (packet & 0x00FF0000) >> 16; sensor.id = (packet & 0x00FF0000) >> 16;
bool found = false; bool found = false;
for(uint8_t i = 0; i < sensors.count() && !found; ++i) for(uint8_t i = 0; i < sensors.count() && !found; ++i)
{ {
if(sensors[i] == sensor) if(sensors[i] == sensor)
{ {
sensors[i] = sensor; sensors[i] = sensor;
found = true; found = true;
} }
} }
if(!found) sensors.push_back(sensor); if(!found)
sensors.push_back(sensor);
if(!sensorsPaused) printSensor(sensor, serial); if(!sensorsPaused)
printSensor(sensor, serial);
} }
void reciverError(uint8_t code, void* userData) void reciverError(uint8_t code, void* userData)
@ -157,19 +184,19 @@ void reciverError(uint8_t code, void* userData)
inline static void printHelp(Serial* serial) inline static void printHelp(Serial* serial)
{ {
serial->write_p(PSTR("Available Commands: \n\ serial->write_p(PSTR("Available Commands: \n"
help : Show this prompt.\n\ "help : Show this prompt.\n"
date : Show current date and time.\n\ "date : Show current date and time.\n"
set [yyyy] [mm] [dd] [hh] [mm] [ss] : Show current date and time.\n\ "set [yyyy] [mm] [dd] [hh] [mm] [ss] : Show current date and time.\n"
pause : pause sensor output.\n\ "pause : pause sensor output.\n"
resume : resume sensor output.\n\ "resume : resume sensor output.\n"
dump : Dump epprom.\n\ "dump : Dump epprom.\n"
free : Show free ram.\n\ "free : Show free ram.\n"
beep : Test buzzer.\n\ "display [on/off] : blank or unblank the display\n"
list : List sensors.\n")); "beep : Test buzzer.\n"
"list : List sensors.\n"));
} }
int freeRAM() int freeRAM()
{ {
extern int __heap_start, *__brkval; extern int __heap_start, *__brkval;
@ -179,132 +206,180 @@ int freeRAM()
void serialDispatch(Serial* serial, SVector<Sensor, MAX_SENSORS>* sensors) void serialDispatch(Serial* serial, SVector<Sensor, MAX_SENSORS>* sensors)
{ {
if(serial->dataIsWaiting()) if(serial->dataIsWaiting())
{ {
char buffer[COMMAND_BUFFER_SIZE]; char buffer[COMMAND_BUFFER_SIZE];
unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE); unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE);
if(length > 2) if(length > 2)
{ {
char* token = strtok(buffer, " \n"); char* token = strtok(buffer, " \n");
if(strcmp(token, "date") == 0) if(strcmp(token, "date") == 0)
{ {
DS1302::Timeval time = clock.getTime(); DS1302::Timeval time = clock.getTime();
snprintf(buffer, SNPRINTF_BUFFER_SIZE, "%04u.%02u.%02u %02u:%02u:%02u\n", time.year, time.month, time.day, time.hour, time.min, time.sec); snprintf(buffer, SNPRINTF_BUFFER_SIZE, "%04u.%02u.%02u %02u:%02u:%02u\n", time.year, time.month, time.day, time.hour,
serial->write(buffer, SNPRINTF_BUFFER_SIZE); time.min, time.sec);
} serial->write(buffer, SNPRINTF_BUFFER_SIZE);
else if(strcmp(token, "set") == 0) }
{ else if(strcmp(token, "set") == 0)
char* year = strtok(NULL, " \n"); {
char* mon = strtok(NULL, " \n"); char* year = strtok(NULL, " \n");
char* day = strtok(NULL, " \n"); char* mon = strtok(NULL, " \n");
char* hour = strtok(NULL, " \n"); char* day = strtok(NULL, " \n");
char* min = strtok(NULL, " \n"); char* hour = strtok(NULL, " \n");
char* sec = strtok(NULL, " \n"); char* min = strtok(NULL, " \n");
if(year != NULL && mon != NULL && day != NULL && hour != NULL && min != NULL && sec != NULL) char* sec = strtok(NULL, " \n");
{ if(year != NULL && mon != NULL && day != NULL && hour != NULL && min != NULL && sec != NULL)
DS1302::Timeval time = {atoi(sec),atoi(min),atoi(hour),atoi(day),atoi(mon),atoi(year)}; {
clock.setTime(time); DS1302::Timeval time = {static_cast<uint8_t>(atoi(sec)),
serial->write_p(PSTR("date and time set\n")); static_cast<uint8_t>(atoi(min)),
display.setString("SET "); static_cast<uint8_t>(atoi(hour)),
_delay_ms(1000); static_cast<uint8_t>(atoi(day)),
} static_cast<uint8_t>(atoi(mon)),
else serial->write_p(PSTR("usage: set [yyyy] [mm] [dd] [hh] [mm] [ss]\n")); static_cast<uint8_t>(atoi(year))};
} clock.setTime(time);
else if(strcmp(token, "pause") == 0) serial->write_p(PSTR("date and time set\n"));
{ display.setString("SET ");
sensorsPaused = true; _delay_ms(1000);
}
else
{
serial->write_p(PSTR("usage: set [yyyy] [mm] [dd] [hh] [mm] [ss]\n"));
}
}
else if(strcmp(token, "pause") == 0)
{
sensorsPaused = true;
serial->write_p(PSTR("Sensors paused\n")); serial->write_p(PSTR("Sensors paused\n"));
} }
else if(strcmp(token, "resume") == 0) else if(strcmp(token, "resume") == 0)
{ {
sensorsPaused = false; sensorsPaused = false;
serial->write_p(PSTR("Sensors resumed\n")); serial->write_p(PSTR("Sensors resumed\n"));
} }
else if(strcmp(token, "list") == 0) else if(strcmp(token, "list") == 0)
{ {
serial->write_p(PSTR("Sensors:\n")); serial->write(sensors->count());
for(uint8_t i = 0; i < sensors->count(); ++i) printSensor(sensors->at(i), serial); serial->putChar(' ');
serial->write('\n'); serial->write_p(PSTR("Sensors:\n"));
} for(uint8_t i = 0; i < sensors->count(); ++i)
else if(strcmp(token, "erase") == 0) printSensor(sensors->at(i), serial);
{ serial->write('\n');
for(uint16_t i = 0; i < 1024; i++) EEPROM_write_char(i, 0); }
serial->write_p(PSTR("EEPROM erased\n")); else if(strcmp(token, "erase") == 0)
} {
else if(strcmp(token, "dump") == 0) for(uint16_t i = 0; i < 1024; i++) EEPROM_write_char(i, 0);
{ serial->write_p(PSTR("EEPROM erased\n"));
for(uint16_t i = 0; i < 1024; i++) }
{ else if(strcmp(token, "dump") == 0)
if(i != 0) serial->putChar(','); {
serial->write((uint16_t)EEPROM_read_char(i)); for(uint16_t i = 0; i < 1024; i++)
} {
serial->putChar('\n'); if(i != 0) serial->putChar(',');
} serial->write((uint16_t)EEPROM_read_char(i));
else if(strcmp(token, "free") == 0) }
{ serial->putChar('\n');
serial->write_p(PSTR("Free Ram: ")); }
else if(strcmp(token, "free") == 0)
{
serial->write_p(PSTR("Free Ram: "));
serial->write(freeRAM()); serial->write(freeRAM());
serial->write_p(PSTR(" Bytes.\n")); serial->write_p(PSTR(" Bytes.\n"));
} }
else if(strcmp(token, "beep") == 0) else if(strcmp(token, "display") == 0)
{ {
char* on = strtok(NULL, " \n");
if(on && strcmp(on, "on") == 0)
{
if(display.getBlank())
{
serial->write_p(PSTR("Display unblanked\n"));
display.setBlank(false);
}
else
{
serial->write_p(PSTR("Display already unblanked\n"));
}
}
else if(on && strcmp(on, "off") == 0)
{
if(!display.getBlank())
{
serial->write_p(PSTR("Display blanked\n"));
display.setBlank(true);
}
else
{
serial->write_p(PSTR("Display already blanked\n"));
}
}
else
{
serial->write_p(PSTR("usage: display [on/off]\n"));
}
}
else if(strcmp(token, "beep") == 0)
{
serial->write_p(PSTR("Beeping\n")); serial->write_p(PSTR("Beeping\n"));
ringging = true; ringging = true;
_delay_ms(1000); _delay_ms(1000);
serial->write_p(PSTR("Done\n")); serial->write_p(PSTR("Done\n"));
ringging = false; ringging = false;
} }
else if(strcmp(token, "help") == 0) else if(strcmp(token, "help") == 0)
{ {
printHelp(serial); printHelp(serial);
} }
else serial->write_p(PSTR("Not a valid command\n")); else
} {
} serial->write_p(PSTR("Not a valid command\n"));
}
}
}
} }
void displayItems(const DS1302::Timeval& time, int16_t temp, int16_t humid) void displayItems(const DS1302::Timeval& time, int16_t temp, int16_t humid)
{ {
switch(displaying) switch(displaying)
{ {
case 0: case 0:
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); display.setSegments((alm & almA ? DualCl56::SEG_A : 0) | (alm & almB ? DualCl56::SEG_D : 0), 0);
break;
case 1:
writePin(&PORTB, PB4, false);
snprintf(buffer, 9, "%02u%02u%04u", time.day, time.month, time.year);
display.setString(buffer, DualCl56::DP_B | DualCl56::DP_D);
break;
#ifdef HAS_DHT
case 2:
writePin(&PORTB, PB4, false);
snprintf(buffer, 9, "0 1%4u", temp);
display.setString(buffer, DualCl56::DP_G);
break; break;
case 3: case 1:
writePin(&PORTB, PB4, false); writePin(&PORTB, PB4, false);
snprintf(buffer, 9, "0 2%4u", humid); snprintf(buffer, 9, "%02u%02u%04u", time.day, time.month, time.year);
display.setString(buffer, DualCl56::DP_G); display.setString(buffer, DualCl56::DP_B | DualCl56::DP_D);
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; break;
#endif #endif
default: default:
writePin(&PORTB, PB4, false); writePin(&PORTB, PB4, false);
snprintf(buffer, 9, "%u%3u%4u", snprintf(buffer, 9, "%u%3u%4u",
sensors[displaying-DPY_FIXED_ITEMS].id, sensors[displaying-DPY_FIXED_ITEMS].id,
sensors[displaying-DPY_FIXED_ITEMS].type, sensors[displaying-DPY_FIXED_ITEMS].type,
sensors[displaying-DPY_FIXED_ITEMS].field); sensors[displaying-DPY_FIXED_ITEMS].field);
display.setString(buffer, sensors[displaying-DPY_FIXED_ITEMS].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) void setAlarm(DS1302::Timeval* alarm, uint8_t leadingSegment = 0)
{ {
writePin(&PORTB, PB4, true); writePin(&PORTB, PB4, true);
while(setting) while(setting)
{ {
if(settingOffset+alarm->min > 59) if(settingOffset+alarm->min > 59)
{ {
if(++alarm->hour > 23) alarm->hour = 0; if(++alarm->hour > 23) alarm->hour = 0;
@ -327,74 +402,62 @@ void setAlarm(DS1302::Timeval* alarm, uint8_t leadingSegment = 0)
int main() int main()
{ {
DDRB = (1 << PB1) | ( 1 << PB2) | ( 1 << PB3) | ( 1 << PB4) | ( 1 << PB5); DDRB |= (1 << PB1) | ( 1 << PB2) | ( 1 << PB3);
DDRD = (1<<PD4) | (1<<PD2); DDRB |= ( 1 << PB4) | ( 1 << PB5);
PORTD |= (1<<PD6) | (1<<PD7); DDRD = (1<<PD4) | (1<<PD2);
PORTD |= (1<<PD6) | (1<<PD7);
TCCR2B = 1<<CS22; TCCR2B = 1<<CS22 | 1<<CS20;
TIMSK2 = 1; TIMSK2 = 1;
TCCR1B = 1<<CS10; TCCR1B = 1<<CS10;
EICRA = 1<<ISC10; EICRA = 1<<ISC10;
EIMSK = 1<<INT1;
sei(); sei();
Serial serial; Serial serial;
serial.write_p(PSTR("SensorDisplay v0.4 starting\n")); serial.write_p(PSTR("SensorDisplay v0.4 starting\n"));
DS1302::Timeval alarmA = EEPROM_read_class<DS1302::Timeval>(128); DS1302::Timeval alarmA = EEPROM_read_class<DS1302::Timeval>(128);
DS1302::Timeval alarmB = EEPROM_read_class<DS1302::Timeval>(128+64); 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); alm = EEPROM_read_char(0);
uint8_t oldAlm = alm; uint8_t oldAlm = alm;
#ifdef HAS_TRANSMITTER #ifdef HAS_TRANSMITTER
char name[] = "relay"; char name[] = "relay";
WirelessRelay relay(0b1011010001000000, name); WirelessRelay relay(0b1011010001000000, name);
#endif #endif
#ifdef HAS_DHT display.setString(welcomeString);
Dht11 sensor(&PORTD, &PIND, &DDRD, PD2); _delay_ms(500);
#endif
if(time.day == 28 && time.month == 5)
{
if constexpr(bdayMsg)
{
display.setString("HAPPY ");
_delay_ms(1000);
display.setString("b-DAY ");
_delay_ms(1000);
display.setString("SASA ");
_delay_ms(1000);
}
}
else
{
display.setString(welcomeString);
_delay_ms(1000);
}
#ifdef HAS_DHT #ifdef HAS_DHT
sensor.read(); Dht11 sensor(&PORTD, &PIND, &DDRD, PD2);
_delay_ms(1000); sensor.read();
_delay_ms(500);
sensor.read(); sensor.read();
#endif #endif
W433DataReciver reciver(&PIND, PD3, &TCNT1, &TIFR1, &packetHandler, reinterpret_cast<void*>(&serial), &reciverError); //enable interrupt
TIMSK1 |= 1 << OCIE1A;
OCR1A = W433DataReciver::calculateOverflowRegister(2000, 1);
TCCR1B = 1<<CS10 | 1<<WGM12;
W433DataReciver reciver(&PIND, PD3, &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; uint16_t i = 0;
#ifdef HAS_TRANSMITTER
bool oldRelaySetting = false; bool oldRelaySetting = false;
#endif
while(true) while(true)
{ {
#ifdef HAS_DHT #ifdef HAS_DHT
if((displaying == 2 || displaying == 3) && i%2048 == 0) if((displaying == 2 || displaying == 3) && i%2048 == 0)
{ {
@ -433,38 +496,56 @@ int main()
time = clock.getTime(); time = clock.getTime();
#ifdef HAS_DHT #ifdef HAS_DHT
displayItems(time, sensor.temperature, sensor.humidity); displayItems(time, sensor.temperature, sensor.humidity);
#else #else
displayItems(time, 0, 0); displayItems(time, 0, 0);
#endif #endif
if(time.hour == alarmA.hour && time.min == alarmA.min && time.sec == 0)
if((alm & almA) && time.hour == alarmA.hour && time.min == alarmA.min && time.sec == 0)
{ {
ringging = true; ringging = true;
} }
if(time.hour == alarmB.hour && time.min == alarmB.min && time.sec == 0) if((alm & almB) && time.hour == alarmB.hour && time.min == alarmB.min && time.sec == 0)
{ {
#ifdef HAS_TRANSMITTER #ifdef HAS_TRANSMITTER
relay.setValue(true); relay.setValue(true);
#else #else
ringging = true; ringging = true;
#endif #endif
} }
serialDispatch(&serial, &sensors);
#ifdef HAS_RECIVER #ifdef HAS_RECIVER
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 "); display.setString("CLEAR ");
_delay_ms(1000); _delay_ms(500);
} }
#endif #endif
++i;
}
return 0; if(time.min == 45 && time.sec == 0)
display.setBlank(true);
else if(time.min == 0 && time.sec == 0)
display.setBlank(false);
if(time.hour == 0 && time.min == 0 && time.sec == timeOffsetSeconds+10)
{
DS1302::Timeval timeSet = time;
timeSet.sec = 10;
clock.setTime(timeSet);
while(clock.getTime().sec <= timeOffsetSeconds+10)
{
display.setString("CAL ");
_delay_ms(500);
}
}
++i;
}
return 0;
} }

156
ringbuffer.h Executable file → Normal file
View File

@ -23,103 +23,103 @@ class RingBuffer
{ {
private: private:
volatile uint_fast16_t _headIndex = 0; volatile uint_fast16_t _headIndex = 0;
volatile uint_fast16_t _tailIndex = 0; volatile uint_fast16_t _tailIndex = 0;
volatile bool _overrun = false; volatile bool _overrun = false;
volatile T _buffer[BUFFER_SIZE]; volatile T _buffer[BUFFER_SIZE];
public: public:
RingBuffer() RingBuffer()
{ {
flush(); flush();
} }
uint_fast16_t remaining() const volatile uint_fast16_t remaining() const volatile
{ {
return (_headIndex-_tailIndex); return (_headIndex-_tailIndex);
} }
uint_fast16_t remainingCapacity() const volatile uint_fast16_t remainingCapacity() const volatile
{ {
return BUFFER_SIZE - (_headIndex-_tailIndex); return BUFFER_SIZE - (_headIndex-_tailIndex);
} }
bool isOverun() volatile bool isOverun() volatile
{ {
bool returnVal = _overrun; bool returnVal = _overrun;
_overrun = false; _overrun = false;
return returnVal; return returnVal;
} }
bool isEmpty() const volatile bool isEmpty() const volatile
{ {
return _tailIndex >= _headIndex; return _tailIndex >= _headIndex;
} }
T read() volatile T read() volatile
{ {
if(!isEmpty()) if(!isEmpty())
{ {
_tailIndex++; _tailIndex++;
return _buffer[(_tailIndex - 1) % BUFFER_SIZE]; return _buffer[(_tailIndex - 1) % BUFFER_SIZE];
} }
else return '\0'; else return '\0';
} }
unsigned int read( T* buffer, unsigned int length ) volatile unsigned int read( T* buffer, unsigned int length ) volatile
{ {
unsigned int i = 0; unsigned int i = 0;
for(; i < length && !isEmpty(); i++) for(; i < length && !isEmpty(); i++)
{ {
buffer[i] = read(); buffer[i] = read();
} }
return i; return i;
} }
void write( T in ) volatile void write( T in ) volatile
{ {
if (_headIndex - BUFFER_SIZE > 0 && _tailIndex - BUFFER_SIZE > 0) if (_headIndex - BUFFER_SIZE > 0 && _tailIndex - BUFFER_SIZE > 0)
{ {
_headIndex -= BUFFER_SIZE; _headIndex -= BUFFER_SIZE;
_tailIndex -= BUFFER_SIZE; _tailIndex -= BUFFER_SIZE;
} }
_buffer[_headIndex % BUFFER_SIZE] = in; _buffer[_headIndex % BUFFER_SIZE] = in;
_headIndex++; _headIndex++;
if(remaining() > BUFFER_SIZE) if(remaining() > BUFFER_SIZE)
{ {
_overrun = true; _overrun = true;
_tailIndex = _headIndex - BUFFER_SIZE; _tailIndex = _headIndex - BUFFER_SIZE;
} }
} }
void write( T* buffer, const unsigned int length ) volatile void write( T* buffer, const unsigned int length ) volatile
{ {
for(unsigned int i = 0; i < length; i++) write(buffer[i]); for(unsigned int i = 0; i < length; i++) write(buffer[i]);
} }
void flush(T flushCharacter = ' ') volatile void flush(T flushCharacter = ' ') volatile
{ {
_headIndex = 0; _headIndex = 0;
_tailIndex = 0; _tailIndex = 0;
for(int i = 0; i < BUFFER_SIZE; i++) _buffer[i] = flushCharacter; for(int i = 0; i < BUFFER_SIZE; i++) _buffer[i] = flushCharacter;
} }
unsigned int getString(T terminator, T* buffer, const unsigned int bufferLength) volatile unsigned int getString(T terminator, T* buffer, const unsigned int bufferLength) volatile
{ {
unsigned int i = 0; unsigned int i = 0;
for(; i <= remaining() && i <= BUFFER_SIZE && _buffer[(_tailIndex+i) % BUFFER_SIZE] != terminator; i++); for(; i <= remaining() && i <= BUFFER_SIZE && _buffer[(_tailIndex+i) % BUFFER_SIZE] != terminator; i++);
if( i < remaining() && i > 0) if( i < remaining() && i > 0)
{ {
if(i > bufferLength-1) i = bufferLength-1; if(i > bufferLength-1) i = bufferLength-1;
read(buffer, i); read(buffer, i);
buffer[i]='\0'; buffer[i]='\0';
_tailIndex++; _tailIndex++;
} }
else if(i == 0) _tailIndex++; else if(i == 0) _tailIndex++;
else i = 0; else i = 0;
return i; return i;
} }
}; };

View File

@ -5,7 +5,7 @@ volatile RingBuffer<SERIAL_BUFFER_SIZE, volatile uint8_t> rxBuffer;
bool stopped = false; bool stopped = false;
ISR(USART_RX_vect) //I have seen worse interrupt sintax ISR(USART_RX_vect)
{ {
rxBuffer.write(UDR0); rxBuffer.write(UDR0);
if(serialFlowControl && !stopped && rxBuffer.remainingCapacity() < 32) if(serialFlowControl && !stopped && rxBuffer.remainingCapacity() < 32)
@ -18,111 +18,114 @@ ISR(USART_RX_vect) //I have seen worse interrupt sintax
Serial::Serial() Serial::Serial()
{ {
UBRR0H = UBRRH_VALUE; UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE; UBRR0L = UBRRL_VALUE;
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
UCSR0B = _BV(RXEN0) | _BV(TXEN0); //Enable RX and TX UCSR0B = _BV(RXEN0) | _BV(TXEN0); //Enable RX and TX
UCSR0B |= (1 << RXCIE0); //Enable Rx interuppt UCSR0B |= (1 << RXCIE0); //Enable Rx interuppt
sei(); sei();
} }
void Serial::putChar(const char c) void Serial::putChar(const char c)
{ {
loop_until_bit_is_set(UCSR0A, UDRE0); loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c; UDR0 = c;
} }
void Serial::write(const char* in, const unsigned int length) void Serial::write(const char* in, const unsigned int length)
{ {
for(unsigned int i = 0; i < length && in[i] != '\0'; i++) for(unsigned int i = 0; i < length && in[i] != '\0'; i++)
{ {
putChar(in[i]); putChar(in[i]);
} }
} }
void Serial::write_p(const char in[]) void Serial::write_p(const char in[])
{ {
cli(); cli();
char ch = pgm_read_byte(in); char ch = pgm_read_byte(in);
while (ch != '\0') while (ch != '\0')
{ {
putChar(ch); putChar(ch);
in++; in++;
ch = pgm_read_byte(in); ch = pgm_read_byte(in);
} }
sei(); sei();
} }
void Serial::write(const char in[]) void Serial::write(const char in[])
{ {
for(unsigned int i = 0; i < strlen(in); i++) for(unsigned int i = 0; i < strlen(in); i++)
{ {
putChar(in[i]); putChar(in[i]);
} }
} }
void Serial::write(int32_t in) void Serial::write(int32_t in)
{ {
if(in == 0) if(in == 0)
{ {
putChar('0'); putChar('0');
} }
else else
{ {
bool flag = false; bool flag = false;
char str[64] = { 0 }; char str[64] = { 0 };
int16_t i = 62; int16_t i = 62;
if (in < 0) if (in < 0)
{ {
flag = true; flag = true;
in = abs(in); in = abs(in);
} }
while (in != 0 && i > 0) while (in != 0 && i > 0)
{ {
str[i--] = (in % 10) + '0'; str[i--] = (in % 10) + '0';
in /= 10; in /= 10;
} }
if (flag) str[i--] = '-'; if (flag) str[i--] = '-';
write(str + i + 1, 64-(i+1)); write(str + i + 1, 64-(i+1));
} }
} }
bool Serial::dataIsWaiting() bool Serial::dataIsWaiting()
{ {
return !rxBuffer.isEmpty(); return !rxBuffer.isEmpty();
} }
char Serial::getChar() char Serial::getChar()
{ {
if(!rxBuffer.isEmpty()) if(!rxBuffer.isEmpty())
{ {
if(serialFlowControl && stopped && rxBuffer.remainingCapacity() > 32 ) if(serialFlowControl && stopped && rxBuffer.remainingCapacity() > 32 )
{ {
loop_until_bit_is_set(UCSR0A, UDRE0); loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = 0x11; UDR0 = 0x11;
stopped = false; stopped = false;
} }
return rxBuffer.read(); return rxBuffer.read();
} }
else return '\0'; else return '\0';
} }
unsigned int Serial::getString(char* buffer, const int bufferLength) unsigned int Serial::getString(char* buffer, const int bufferLength)
{ {
return rxBuffer.getString(_terminator, (uint8_t*)buffer, bufferLength); return rxBuffer.getString(_terminator, (uint8_t*)buffer, bufferLength);
} }
unsigned int Serial::read(char* buffer, const unsigned int length ) unsigned int Serial::read(char* buffer, const unsigned int length )
{ {
return rxBuffer.read((uint8_t*)buffer, length); return rxBuffer.read((uint8_t*)buffer, length);
} }
void Serial::flush() void Serial::flush()
{ {
rxBuffer.flush(); rxBuffer.flush();
} }
void Serial::setTerminator(char terminator){_terminator = terminator;} void Serial::setTerminator(char terminator)
{
_terminator = terminator;
}

View File

@ -16,21 +16,21 @@ const bool serialFlowControl = false;
class Serial class Serial
{ {
private: private:
char _terminator = '\n'; char _terminator = '\n';
public: public:
Serial(); Serial();
void putChar(const char c); void putChar(const char c);
void write(const char* in, const unsigned int length); void write(const char* in, const unsigned int length);
void write(const char in[]); void write(const char in[]);
void write_p(const char in[]); //for flash space strigns void write_p(const char in[]); //for flash space strigns
void write(const int32_t in); void write(const int32_t in);
unsigned int read( char* buffer, const unsigned int length ); unsigned int read( char* buffer, const unsigned int length );
bool dataIsWaiting(); bool dataIsWaiting();
char getChar(); char getChar();
unsigned int getString(char* buffer, const int bufferLength); unsigned int getString(char* buffer, const int bufferLength);
void flush(); void flush();
void setTerminator(const char terminator); void setTerminator(const char terminator);
}; };
#endif #endif