full project is here p6008-rg-matrix-clock.zip
sketch is here:
/* -------------------------------------------------------------------------------------
* user configuration
*-------------------------------------------------------------------------------------*/
//#define F_CPU 16000000UL
#define TIMERS_BMP085_UPDATE_SEC 10
#define TIMERS_BATTERY_UPDATE_MIN 120
#define TIMERS_VERA_PRESSURE_UPDATE_MINUTE 5
#define TIMERS_VERA_TEMPERATURE_UPDATE_MINUTE 2
#define TIMERS_VERA_BATTERY_UPDATE_MINUTE 120
#define TIMERS_VERA_LIGHT_UPDATE_SECONDS 240
#define TIMERS_VERA_CLOCK_UPDATE_HOUR 12
#define TIMERS_VERA_STREET_TEMPERATURE_MINUTE 60 // minutes, time for street temperature recieved from vera to be timed out
#define TIMERS_VERA_FAILED_RADIO_MIN 5
#define rus_str_startup "RG Matrix Clock v1.0"
#define rus_str_v_komnate "Local"
#define rus_str_v_kvartire "Inside"
#define rus_str_na_ulitce "Outside"
#define rus_str_davlenie "Preassure"
/* -------------------------------------------------------------------------------------
* hardware configuration
*-------------------------------------------------------------------------------------*/
#define LED_PORT PORTC
#define LED_DATA 3
#define LED_WR 2
#define LED_CLK 1
#define LED_CS 0
#define BUZZER_PORT_OUT PORTE
#define BUZZER_PORT_DDR DDRE
#define BUZZER_PORT_IN PINE
#define BUZZER_PORT_PIN (1 << PE2)
typedef enum {
ADC_LIGHT=3,
ADC_BATTERY=2,
ADC_VREF=30
} enum_adc;
//#define RF24_NOUART
//#define RF24_CE_PORT PORTB
//#define RF24_CE_DDR DDRB
//#define RF24_CE_PIN PB4
//#define RF24_CSN_PORT PORTB
//#define RF24_CSN_DDR DDRB
//#define RF24_CSN_PIN PB5
//#define MAX_PAYLOAD_SIZE 32
#define RF_CE 12
#define RF_CSN 13
//#define BMP085_EOC_PORT PINC
#define BMP085_EOC_PIN (1 << PINC0)
/* -------------------------------------------------------------------------------------
* includes
*-------------------------------------------------------------------------------------*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
//#include <util/delay.h>
#include <stdio.h>
#include <MySensor.h>
#include <SPI.h>
#include "i2c.h"
#include "bmp085.h"
#include "ds3231.h"
#include "ht1632c_c.h"
#include "axlib.h"
#include "incMsg.h"
//#include "uart_printf.h"
/* -------------------------------------------------------------------------------------
* globals
*-------------------------------------------------------------------------------------*/
#define STREET_TEMPERATURE_NONE -2500 // value used to indicate that street temperature was not set or timed outed
enum {
vera_sens_temp=0,
vera_sens_pressure,
vera_sens_light
};
typedef enum {
display_startup=0,
display_clock,
display_clock_date,
display_temperature_pressure,
display_failed_radio
} enum_display;
volatile struct {
uint8_t second;
uint8_t display_sec;
uint8_t display_type_sec;
uint8_t measure_bmp085_sec;
uint16_t measure_battery_sec;
uint8_t vera_preassure_min;
uint8_t vera_temperature_min;
uint8_t vera_battery_min;
uint16_t vera_light_sec;
uint32_t vera_clock_sec;
uint16_t vera_failed_radio_min;
uint8_t vera_street_temperature;
uint8_t vera_apartment_temperature;
} timers;
enum {
radio_ok=0,
radio_failed
};
struct {
int16_t temperature;
uint32_t pressureMM;
uint8_t light;
uint16_t h_light_min;
uint16_t h_light_max;
uint8_t battery;
uint16_t vref;
volatile int16_t street_temperature;
volatile int16_t apartment_temperature;
uint8_t radio_status;
char buff[20];
enum_display cur_display;
bmp085_calibration calibration;
struct {
uint16_t s_pressureMM;
int16_t temperature;
uint8_t battery;
uint8_t light;
} vera_last;
} var;
MySensor gw(RF_CE, RF_CSN);
/* -------------------------------------------------------------------------------------
* function definition
*-------------------------------------------------------------------------------------*/
void buzzerInit() { BUZZER_PORT_DDR |= BUZZER_PORT_PIN; }
uint8_t buzzerCheck() { return BUZZER_PORT_IN & BUZZER_PORT_PIN; }
void buzzerOn() { BUZZER_PORT_OUT |= BUZZER_PORT_PIN; }
void buzzerOff() { BUZZER_PORT_OUT &= ~ BUZZER_PORT_PIN; }
AXLIB_TIMER_BLINK(buzzer, buzzerCheck(), buzzerOn(), buzzerOff())
void init_mcu();
void display_sec(uint8_t what);
uint8_t adc(uint8_t what);
// 20 times each second
ISR(TIMER1_COMPA_vect) {
axlib_timer_blink_buzzer_update();
}
// once a second
ISR(TIMER3_COMPA_vect) {
timers.second++;
if(timers.second == 60) {
timers.second = 0;
// timers with minutes counting
if(timers.vera_preassure_min) timers.vera_preassure_min--;
if(timers.vera_temperature_min) timers.vera_temperature_min--;
if(timers.vera_battery_min) timers.vera_battery_min--;
if(timers.vera_failed_radio_min && timers.vera_failed_radio_min != 1) timers.vera_failed_radio_min--;
if(timers.vera_street_temperature) {
if(!--timers.vera_street_temperature) var.street_temperature = STREET_TEMPERATURE_NONE;
}
if(timers.vera_apartment_temperature) {
if(!--timers.vera_apartment_temperature) var.apartment_temperature = STREET_TEMPERATURE_NONE;
}
}
// timers with seconds counting
if(timers.measure_bmp085_sec) timers.measure_bmp085_sec--;
if(timers.display_sec) timers.display_sec--;
if(timers.display_type_sec) timers.display_type_sec--;
if(timers.vera_clock_sec) timers.vera_clock_sec--;
if(timers.vera_light_sec) timers.vera_light_sec--;
// measurement of RTC battery level
if(timers.measure_battery_sec) --timers.measure_battery_sec;
}
ISR(TIMER2_OVF_vect) {
}
// adc
#define ADC_COUNT_AVG 16
#define ADC_BG 30
#define BATTERY_MIN 250 // V*100, 0%
#define BATTERY_MAX 300 // V*100, 100%
volatile uint16_t adc_count;
volatile uint16_t adc_sum;
uint8_t adc(uint8_t what) {
adc_count = ADC_COUNT_AVG;
adc_sum = 0;
ADMUX = (0 << REFS1) | (1 << REFS0) | what;
ADCSRA |= (1 << ADSC);
return 1;
}
ISR(ADC_vect) {
adc_sum += ADCW;
if(!--adc_count) {
// finished
uint8_t channel = ADMUX & 0x1F;
switch(channel) {
case ADC_LIGHT:
{
// should be between 0% and 100%
// 0% is most dark
if(var.h_light_max < adc_sum) var.h_light_max = adc_sum;
if(var.h_light_min > adc_sum) var.h_light_min = adc_sum;
uint32_t v = adc_sum - var.h_light_min;
v *= 100;
v /= (var.h_light_max - var.h_light_min);
var.light = 100 - v;
break;
}
case ADC_BATTERY:
{
uint32_t v = adc_sum;
v *= var.vref;
v /= 1023;
v /= ADC_COUNT_AVG;
// translate voltage to %
//if(v >= BATTERY_MAX) var.battery = 100;
//else if(v <= BATTERY_MIN) var.battery = 0;
//else {
//v -= BATTERY_MIN;
//v *= 100;
//v /= (BATTERY_MAX - BATTERY_MIN);
//}
//var.battery = v;
var.battery = axlib_convert_volt2percent_lithium_notrechargeable(v);
timers.measure_battery_sec = TIMERS_BATTERY_UPDATE_MIN * 60;
break;
}
case ADC_BG:
{
uint32_t v = 131; // should be 123 (1.23V) but this one is corrected
v *= 1023;
v /= adc_sum;
v *= 16;
var.vref = v;
break;
}
}
// find what next to measure
if(!timers.measure_battery_sec) channel = ADC_BATTERY;
else {
switch(channel) {
case ADC_LIGHT:
channel = ADC_VREF;
break;
case ADC_VREF:
channel = ADC_LIGHT;
break;
case ADC_BATTERY:
channel = ADC_LIGHT;
break;
}
}
adc(channel);
} else {
// next round
ADCSRA |= (1 << ADSC);
}
}
/* -------------------------------------------------------------------------------------
* main functions
*-------------------------------------------------------------------------------------*/
void setup()
{
// variables init
timers.second = 0;
timers.measure_battery_sec = 0;
timers.measure_bmp085_sec = 0;
timers.vera_preassure_min = 0;
timers.vera_clock_sec = 10;
timers.vera_light_sec = 0;
timers.vera_battery_min = 0;
timers.display_sec = 0;
timers.vera_failed_radio_min = 0;
timers.vera_street_temperature = 0;
timers.vera_apartment_temperature = 0;
var.vref = 500;
var.radio_status = radio_ok;
var.street_temperature = STREET_TEMPERATURE_NONE;
var.apartment_temperature = STREET_TEMPERATURE_NONE;
init_mcu();
buzzerInit();
axlib_timer_blink_buzzer_init();
// init uart printing
Serial.begin(115200);
Serial1.begin(9600);
//uart_debug_init(UART_PRINTF_BAUDRATE(115200, F_CPU));
//uart_debugf_1_P(PSTR("\n------------------------------\nRG Matrix clock started v1.0\n"));
gw.debugPrint(PSTR("\n------------------------------\nRG Matrix clock started v1.0\n"));
// init bmp085
i2cInit();
bmp085_readCalibration(&var.calibration);
gw.debugPrint(PSTR("\n1. BMP085 calibration data:\n"));
gw.debugPrint(PSTR("- ac1 = %i\n"), var.calibration.ac1);
gw.debugPrint(PSTR("- ac2 = %i\n"), var.calibration.ac2);
gw.debugPrint(PSTR("- ac3 = %i\n"), var.calibration.ac3);
gw.debugPrint(PSTR("- ac4 = %i\n"), var.calibration.ac4);
gw.debugPrint(PSTR("- ac5 = %i\n"), var.calibration.ac5);
gw.debugPrint(PSTR("- ac6 = %i\n"), var.calibration.ac6);
gw.debugPrint(PSTR("- b1 = %i\n"), var.calibration.b1);
gw.debugPrint(PSTR("- b2 = %i\n"), var.calibration.b2);
gw.debugPrint(PSTR("- mb = %i\n"), var.calibration.mb);
gw.debugPrint(PSTR("- mc = %i\n"), var.calibration.mc);
gw.debugPrint(PSTR("- md = %i\n\n"), var.calibration.md);
// set 24 hour format of RTC
DS3231Set24(1);
gw.debugPrint(PSTR("2. DS3231 init done\n"));
// init rg matrix
//uart_debugf_1_P(PSTR("3. LED init\n"));
gw.debugPrint(PSTR("3. LED init\n"));
ht1632c_init(&LED_PORT, LED_DATA, LED_WR, LED_CLK, LED_CS, HT1632_COLOR_GEOM_32x16, 1);
ht1632c_pwm(15);
// vera init
//uart_debugf_1_P(PSTR("4. Vera inititalization started\n"));
Serial.println("4. Vera initialization started\n");
gw.begin(incomingMessage);
gw.sendSketchInfo("RG Matrix clock", "2.0");
gw.present(vera_sens_temp, S_TEMP);
gw.present(vera_sens_pressure, S_BARO);
gw.present(vera_sens_light, S_LIGHT_LEVEL);
//VeraSensor_sendSensorPresentation(vera_sens_temp, S_TEMP);
//VeraSensor_sendSensorPresentation(vera_sens_pressure, S_BARO);
//VeraSensor_sendSensorPresentation(vera_sens_light, S_LIGHT_LEVEL);
//uart_debugf_2_P(PSTR("- radioId = %i\n"), gw.getNodeId());
axlib_timer_blink_buzzer_run(1, 1);
//wdt_enable(WDTO_2S);
//uart_debugf_1_P(PSTR("5. WDT init done\n\n"));
//uart_debugf_1_P(PSTR("------------------------------\nMain loop initiated\n\n"));
gw.debugPrint(PSTR("------------------------------\nMain loop initiated\n"));
sei();
var.cur_display = display_startup;
timers.display_type_sec = 0;
adc(ADC_VREF);
}
void loop()
{
gw.process();
// request clock synchronization if needed
if(!timers.vera_clock_sec) {
//uart_debugf_1_P(PSTR("- requested clock sync from vera\n"));
gw.debugPrint(PSTR("- requested clock sync from vera\n"));
gw.requestTime(receiveTime);
timers.vera_clock_sec = 30;
if(!timers.vera_failed_radio_min) timers.vera_failed_radio_min = TIMERS_VERA_FAILED_RADIO_MIN;
}
// it is a time to update measurement on bmp085
if(!timers.measure_bmp085_sec) {
int32_t pressure;
bmp085_get(&var.calibration, BMP085_OSS_ULTRAHIGHRESOLUTION, &var.temperature, &pressure);
var.pressureMM = bmp085_convertPAtoMM(pressure);
gw.debugPrint(PSTR("- updated temperature %i.%i, pressure %li.%li mm\n"),
var.temperature/10, var.temperature % 10, var.pressureMM/1000, var.pressureMM%1000);
// check if update on pressure to vera is needed
if(!timers.vera_preassure_min) {
// update vera on pressure only that often
// use for vera only one digit after dot, rounded
uint16_t s_pressureMM = (var.pressureMM + 50) / 100;
if(var.vera_last.s_pressureMM != s_pressureMM) {
// do an update to vera
sprintf_P(var.buff, PSTR("%i.%d"), s_pressureMM / 10, (int)(s_pressureMM % 10));
gw.debugPrint(PSTR("- sending update to Vera pressureMM = %s\n"), var.buff);
MyMessage pressureMsg(vera_sens_pressure, V_PRESSURE);
MyMessage forecastMsg(vera_sens_pressure, V_FORECAST);
gw.send(pressureMsg.set(var.buff));
gw.send(forecastMsg.set("unknown"));
//VeraSensor_sendVariableString(vera_sens_pressure, V_PRESSURE, buff);
var.vera_last.s_pressureMM = s_pressureMM;
timers.vera_preassure_min = TIMERS_VERA_PRESSURE_UPDATE_MINUTE;
}
}
// check if update on temperature to vera is needed
if(!timers.vera_temperature_min || abs(var.vera_last.temperature-var.temperature) > 20) {
// update vera on temperature only that often
if(var.vera_last.temperature != var.temperature) {
// do an update to vera
sprintf_P(var.buff, PSTR("%i.%i"), var.temperature / 10, var.temperature % 10);
gw.debugPrint(PSTR("- sending update to Vera temperature = %s\n"), var.buff);
MyMessage tempMsg(vera_sens_temp, V_TEMP);
gw.send(tempMsg.set(var.buff));
//VeraSensor_sendVariableString(vera_sens_temp, V_TEMP, buff);
var.vera_last.temperature = var.temperature;
timers.vera_temperature_min = TIMERS_VERA_TEMPERATURE_UPDATE_MINUTE;
}
}
timers.measure_bmp085_sec = TIMERS_BMP085_UPDATE_SEC;
}
// update vera on battery
if(!timers.vera_battery_min) {
if(var.vera_last.battery != var.battery) {
gw.debugPrint(PSTR("- sending update to Vera battery = %d%%\n"), var.battery);
gw.sendBatteryLevel(var.battery);
var.vera_last.battery = var.battery;
timers.vera_battery_min = TIMERS_VERA_BATTERY_UPDATE_MINUTE;
}
}
// update vera on light
if(!timers.vera_light_sec || abs(var.vera_last.light - var.light) > 10) {
if(var.vera_last.light != var.light) {
gw.debugPrint(PSTR("- sending update to Vera light = %d%%\n"), var.light);
MyMessage msg(vera_sens_light, V_LIGHT_LEVEL);
gw.send(msg.set(var.light));
var.vera_last.light = var.light;
timers.vera_light_sec = TIMERS_VERA_LIGHT_UPDATE_SECONDS;
}
}
if(timers.vera_failed_radio_min == 1) {
timers.vera_failed_radio_min = TIMERS_VERA_FAILED_RADIO_MIN;
var.cur_display = display_failed_radio;
var.radio_status = radio_failed;
}
if(!timers.display_sec) {
display_sec(var.cur_display);
timers.display_sec = 1;
}
if(!timers.display_type_sec) {
switch(var.cur_display) {
case display_startup:
case display_failed_radio:
case display_temperature_pressure:
var.cur_display = display_clock;
timers.display_type_sec = 10;
//ht1632c_clear();
break;
case display_clock:
var.cur_display = display_clock_date;
timers.display_type_sec = 6;
//ht1632c_clear();
break;
case display_clock_date:
var.cur_display = display_temperature_pressure;
timers.display_type_sec = 6;
//ht1632c_clear();
break;
}
}
wdt_reset();
}
/* -------------------------------------------------------------------------------------
* internal function
*-------------------------------------------------------------------------------------*/
// This is called when a new time value was received
void receiveTime(unsigned long time) {
uint8_t hour, minute, second;
uint8_t month, day;
uint16_t year;
axlib_time_convert(time, &hour, &minute, &second);
axlib_date_convert(time, &day, &month, &year);
gw.debugPrint(PSTR("- new time recieved %02d:%02d.%02d\n"), hour, minute, second);
gw.debugPrint(PSTR("- new date recieved %02d.%02d.%04d\n"), day, month, year);
DS3231SetFullTime24(hour, minute, second);
DS3231SetFullDate(year, month, day, 1);
timers.vera_clock_sec = TIMERS_VERA_CLOCK_UPDATE_HOUR * 3600UL;
}
void setStreetTemp(int t) {
// getting street temperature
var.street_temperature = t;
gw.debugPrint(PSTR("- street temperature received %d\n"), var.street_temperature);
// stupid validity check
if(var.street_temperature > -600 && var.street_temperature < 1000) timers.vera_street_temperature = TIMERS_VERA_STREET_TEMPERATURE_MINUTE;
else var.street_temperature = STREET_TEMPERATURE_NONE;
}
void setRoomTemp(int t) {
// getting apartment temperature
var.apartment_temperature = t;
gw.debugPrint(PSTR("- apartment temperature received %d\n"), var.apartment_temperature);
// stupid validity check
if(var.apartment_temperature > -600 && var.apartment_temperature < 1000) timers.vera_apartment_temperature = TIMERS_VERA_STREET_TEMPERATURE_MINUTE;
else var.apartment_temperature = STREET_TEMPERATURE_NONE;
}
void setTextToShow(char* str) {
// text message received
ht1632c_setfont(FONT_8x13BK);
ht1632c_animate_hscrolltext(1, str, HT1632_COLOR_GREEN, 20, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 8);
}
void setSoundID(int id) {
Serial1.println(id);
}
void clearRadioStatus() {
timers.vera_failed_radio_min = 0;
var.radio_status = radio_ok;
ht1632c_animate_rect_fillfrominside(10, 5, HT1632_COLOR_RED, 5);
ht1632c_animate_rect_fillfrominside(17, 10, HT1632_COLOR_GREEN, 5);
ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_BLACK, 5);
for(uint8_t i=0; i<3; i++) {
ht1632c_setfont(FONT_5x7W);
ht1632c_rect(8, 2, 23, 13, HT1632_COLOR_ORANGE);
ht1632c_putstr(10, 4, "IN", HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK);
ht1632c_sendframe();
wdt_reset();
_delay_ms(100);
ht1632c_clear();
ht1632c_sendframe();
wdt_reset();
_delay_ms(100);
wdt_reset();
}
}
void display_temperature(int16_t temperature, uint8_t color, uint8_t bg_color)
{
uint8_t neg = (temperature<0)?1:0;
if(neg) temperature = -temperature;
uint8_t dig1 = temperature / 100;
uint8_t dig2 = (temperature / 10) % 10;
uint8_t dig3 = temperature % 10;
uint8_t x = (dig1)?0:7;
if(!dig3) x += 4;
ht1632c_setfont(FONT_8x13BK);
if(neg) {
temperature = - temperature;
ht1632c_rect(x, 7, x+2, 8, color);
x += (dig1)?3:4;
} else {
x += 1;
}
ht1632c_setfont(FONT_8x13BK);
if(dig1) {
// ГЙЖТБ ДЕУСФЛПЧ, ОПМШ РТПРХУЛБЕН
ht1632c_putchar(x, 2, dig1 + '0', color, 0, bg_color);
x += 8;
}
// ГЙЖТБ ЕДЙОЙГ, ОПМШ РПЛБЪЩЧБЕН
ht1632c_putchar(x, 2, dig2 + '0', color, 0, bg_color);
x += 8;
if(dig3) {
// ДЕУСФЙЮОБС ФПЮЛБ: ПФПВТБЦБЕН ЕУМЙ ЪОБЮБЪБС ГЙЖТБ РПУМЕ ФПЮЛЙ
ht1632c_rect(x, 11, x+1, 12, color);
x += 3;
ht1632c_putchar(x, 2, dig3 + '0', color, 0, bg_color);
x += 8;
}
// ЪОБЛ ЗТБДХУПЧ
ht1632c_line(x-1, 0, x-1, 2, color);
ht1632c_line(x+1, 0, x+1, 2, color);
ht1632c_line(x-1, 0, x+1, 0, color);
ht1632c_line(x-1, 2, x+1, 2, color);
x += 3;
if(x < 31-8) {
ht1632c_putchar(x, 2, 'C', color, 0, bg_color);
}
ht1632c_sendframe();
/* if(var.street_temperature > 0 || (var.street_temperature > -99)) {
// display with dot if we have space
sprintf_P(buff, PSTR("%d.%d`"), var.street_temperature/10, abs(var.street_temperature)%10);
ht1632c_setfont(FONT_6x13);
ht1632c_putstr(1, 1, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK);
} else {
// duisplay without dot if space is limited
sprintf_P(buff, PSTR("%d`"), var.street_temperature/10);
ht1632c_setfont(FONT_8x13BK);
ht1632c_putstr(4, 2, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK);
}
ht1632c_sendframe();
*/
}
void display_pressure(uint16_t pressure, uint8_t color, uint8_t bg_color) {
uint8_t dig1 = pressure / 100;
uint8_t dig2 = (pressure / 10 ) % 10;
uint8_t dig3 = pressure % 10;
ht1632c_setfont(FONT_8x13BK);
ht1632c_putchar(0, 2, dig1+'0', color, 0, bg_color);
ht1632c_putchar(8, 2, dig2+'0', color, 0, bg_color);
ht1632c_putchar(16, 2, dig3+'0', color, 0, bg_color);
ht1632c_setfont(FONT_4x6);
ht1632c_putchar(24, 8, 'm', color, 0, bg_color);
ht1632c_putchar(28, 8, 'm', color, 0, bg_color);
ht1632c_sendframe();
}
void display_clockf(int8_t x, int8_t y, uint8_t color, uint8_t bg_color) {
uint8_t a, b, c;
ht1632c_setfont(FONT_6x13B);
DS3231GetFullTime24(&a, &b, &c);
x += ht1632c_putchar(x, y, '0'+a/10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
x += ht1632c_putchar(x, y, '0'+a%10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
if(c%2) {
ht1632c_rect(x, y+3, x+1, y+3+2, HT1632_COLOR_ORANGE);
ht1632c_rect(x, y+7, x+1, y+7+2, HT1632_COLOR_ORANGE);
}
x += 6;
x += ht1632c_putchar(x-3, y, '0'+b/10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
ht1632c_putchar(x-3, y, '0'+b%10, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
ht1632c_sendframe();
}
void display_sec(uint8_t what) {
char buff[64];
ht1632c_clear();
switch(what) {
case display_clock:
display_clockf(1, 1, HT1632_COLOR_ORANGE, HT1632_COLOR_BLACK);
break;
case display_clock_date:
{
uint8_t a, b, c, d;
ht1632c_setfont(FONT_5x7W);
DS3231GetFullTime24(&a, &b, &c);
sprintf(buff, "%02d%c%02d", a, (c%2)?':':' ', b);
ht1632c_putstr(1, 1, buff, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
DS3231GetFullDate(&a, &b, &c, &d);
sprintf(buff, "%02d.%02d", c, b);
ht1632c_putstr(1, 9, buff, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
break;
}
case display_startup:
{
ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_GREEN, 10);
//_delay_ms(500);
ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_RED, 10);
//_delay_ms(500);
ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_ORANGE, 10);
//_delay_ms(500);
ht1632c_animate_rect_fillfrominside(15, 7, HT1632_COLOR_BLACK, 10);
ht1632c_setfont(FONT_8x13BK);
ht1632c_animate_hscrolltext(1, rus_str_startup, HT1632_COLOR_ORANGE, 20, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16);
break;
}
case display_temperature_pressure:
// display street temperature
if(var.street_temperature != STREET_TEMPERATURE_NONE) {
ht1632c_setfont(FONT_8x13BK);
sprintf_P(buff, PSTR(rus_str_na_ulitce));
ht1632c_animate_hscrolltext(1, buff, HT1632_COLOR_RED, 5, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16);
/* if(var.street_temperature > 0 || (var.street_temperature > -99)) {
// display with dot if we have space
sprintf_P(buff, PSTR("%d.%d`"), var.street_temperature/10, abs(var.street_temperature)%10);
ht1632c_setfont(FONT_6x13);
ht1632c_putstr(1, 1, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK);
} else {
// duisplay without dot if space is limited
sprintf_P(buff, PSTR("%d`"), var.street_temperature/10);
ht1632c_setfont(FONT_8x13BK);
ht1632c_putstr(4, 2, buff, HT1632_COLOR_RED, 0, HT1632_COLOR_BLACK);
}
ht1632c_sendframe();*/
display_temperature(var.street_temperature, HT1632_COLOR_RED, HT1632_COLOR_BLACK);
ht1632c_delay_ms(3000);
ht1632c_clear();
}
// display room temperature
{
const void* str;
int16_t temp;
if(var.apartment_temperature != STREET_TEMPERATURE_NONE) {
str = PSTR(rus_str_v_kvartire);
temp = var.apartment_temperature;
} else {
str = PSTR(rus_str_v_komnate);
temp = var.temperature;
}
ht1632c_setfont(FONT_8x13BK);
sprintf_P(buff, (const char*)str);
ht1632c_animate_hscrolltext(1, buff, HT1632_COLOR_ORANGE, 5, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16);
// sprintf_P(buff, PSTR("%d.%d`"), temp/10, temp%10);
display_temperature(temp, HT1632_COLOR_ORANGE, HT1632_COLOR_BLACK);
ht1632c_delay_ms(3000);
ht1632c_clear();
}
// ht1632c_setfont(FONT_6x13);
//ht1632c_putstr(1, 1, buff, HT1632_COLOR_ORANGE, 0, HT1632_COLOR_BLACK);
//ht1632c_sendframe();
// display atmosphere preasure
ht1632c_setfont(FONT_8x13BK);
sprintf_P(buff, PSTR(rus_str_davlenie));
ht1632c_animate_hscrolltext(1, buff, HT1632_COLOR_GREEN, 5, 1, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16);
// sprintf(buff, "%dmm", (int)((var.pressureMM+500)/1000));
// ht1632c_setfont(FONT_6x13);
// ht1632c_putstr(1, 1, buff, HT1632_COLOR_GREEN, 0, HT1632_COLOR_BLACK);
// ht1632c_sendframe();
display_pressure(((var.pressureMM+500)/1000), HT1632_COLOR_GREEN, HT1632_COLOR_BLACK);
ht1632c_delay_ms(3000);
break;
case display_failed_radio:
ht1632c_setfont(FONT_8x13BK);
//axlib_timer_blink_buzzer_run(3, 1);
ht1632c_animate_hscrolltext(1, "Тег йбиум й Vera", HT1632_COLOR_RED, 50, 2, HT1632_DIR_LEFT, 0, HT1632_COLOR_BLACK, 16);
break;
}
// radio status
//ht1632c_rect(30, 0, 31, 1, (var.radio_status==radio_ok)?HT1632_COLOR_GREEN:HT1632_COLOR_RED);
ht1632c_plot(31, 0, (var.radio_status==radio_ok)?HT1632_COLOR_GREEN:HT1632_COLOR_RED);
ht1632c_sendframe();
}
void init_mcu() {
// timer 1 - 20 times per second
// CTC mode
// TCCR1A = (0 << WGM11) | (0 << WGM10);
// CTC mode + /64
// TCCR1B = (0 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (1 << CS10);
// OCR1A = 9375;
// timer2
// clock source - T2
TCCR2 = (1 << CS22) | (1 << CS21) | (1 << CS20);
// timer 3 - once a second
// CTC mode
TCCR3A = (0 << WGM31) | (0 << WGM30);
// /256 prescaler + CTC mode
TCCR3B = (0 << WGM33) | (1 << WGM32) | (1 << CS32) | (0 << CS31) | (0 << CS30);
OCR3A = F_CPU / 256;
TIMSK |= (0 << TOIE2);// | (1 << OCIE1A);
ETIMSK = (1 << OCIE3A);
// adc
ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}