/*
* main.c
*
* Created on: 2010-09-25
*
*
* PD7 - 1WIRE
* PA0..PA7 - LD0..LD7 - ledy
* PA7 - LTG - podświetlenie wyświetlacza
* PB0-PB6 - SW0-SW6 - przyciski
* PD0 - R/S
* PD1 - E
* PB6 - D4
* PD3 - D5
* PD4 - D6
* PD5 - D7
* RTC
* PC0 - SCL
* PC1 - SDA
* PD2 - FT
*
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
//#include <avr/pgmspace.h>
//#include <util/delay.h>
#include "LCD/lcd44780.h"
#include "1Wire/ds18x20.h"
#include "twi.h"
#include "rtc_lib.h"
#define LED1 (1<<PA0)
#define LED2 (1<<PA1)
#define LED3 (1<<PA2)
#define LED4 (1<<PA3)
#define LED5 (1<<PA4)
#define LED6 (1<<PA5)
#define LED7 (1<<PA6)
#define LED1_ON PORTA &= ~LED1
#define LED1_OFF PORTA |= LED1
#define LED2_ON PORTA &= ~LED2
#define LED2_OFF PORTA |= LED2
#define LED3_ON PORTA &= ~LED3
#define LED3_OFF PORTA |= LED3
#define LED4_ON PORTA &= ~LED4
#define LED4_OFF PORTA |= LED4
#define LED5_ON PORTA &= ~LED5
#define LED5_OFF PORTA |= LED5
#define LED6_ON PORTA &= ~LED6
#define LED6_OFF PORTA |= LED6
#define LED7_ON PORTA &= ~LED7
#define LED7_OFF PORTA |= LED7
#define LED3_TOG PORTA ^= LED3
#define KL1 (1<<PB0)
#define KL2 (1<<PB1)
#define KL3 (1<<PB2)
#define KL4 (1<<PB3)
//#define NULL 0
#define DEFAULT 0
volatile uint8_t Timer1, Timer2, Timer_podswietlenia, Timer_menu0; /* timery programowe 100Hz */
volatile uint8_t int0_flag; // flaga przerwania INT0 od układu RTC
uint8_t czujniki_cnt; /* ilość czujników na magistrali */
uint8_t subzero, cel, cel_fract_bits;
uint8_t init, X, Y, sekundy;
volatile uint8_t s_sek, m_min, h_hrs;
void display_temp(uint8_t y, uint8_t x);
/************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************/
void SuperDebounce(uint8_t * key_state, volatile uint8_t *KPIN,
uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,
void (*push_proc)(void), void (*rep_proc)(void) );
void rtc_get_czas(void) {
uint8_t temp_s;
uint8_t temp_m;
uint8_t temp_h;
uint8_t time_s[2];
uint8_t time_m[2];
uint8_t time_h[2];
set_reg_pointer(0x3F);
twistart();
twiwrite(0xD1);
s_sek = twiread(ACK);
m_min = twiread(ACK);
h_hrs = twiread(NOACK);
twistop();
if(!(temp_h&0x40)) {
itoa(temp_h,time_h,16);
if(temp_h<0x10) {lcd_char('0'); lcd_str(time_h);}
else {lcd_str(time_h);} lcd_char('-');
itoa(temp_m,time_m,16);
if(temp_m<0x10) {lcd_char('0'); lcd_str(time_m);}
else {lcd_str(time_m);} lcd_char('-');
itoa(temp_s,time_s,16);
if(temp_s<0x10) {lcd_char('0'); lcd_str(time_s);}
else lcd_str(time_s);
}
else
{
itoa((temp_h&0x1F),time_h,16);
if((temp_h&0x1F)<0x10) {lcd_char('0'); lcd_str(time_h);} else lcd_str(time_h);
lcd_char('+');
itoa(temp_m,time_m,16);
if(temp_m<0x10) {lcd_char('0'); lcd_str(time_m);} else lcd_str(time_m);
lcd_char('+');
itoa(temp_s,time_s,16);
if(temp_s<0x10) {lcd_char('0'); lcd_str(time_s);} else lcd_str(time_s);
}
}
void lcd_on(void) {
LED7_ON; /* podświetlenie wyświetlacza LCD */
Timer_podswietlenia = 200; // na 3 sekundy, powinno byc 360
Timer_menu0 = 163;
}
volatile uint16_t licznik;
uint8_t poziom_menu;
uint8_t EEMEM eeTustaw[7];
uint8_t Tustaw[7];
void menu (void){
lcd_on(); /* podświetlenie wyświetlacza LCD */
lcd_cls();
lcd_str("Ustawienia:");
++poziom_menu;
if (poziom_menu==8) poziom_menu=1;
if (poziom_menu==1) {
lcd_locate(1,0);
lcd_str("CEL");
X = 1; Y = 10;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
if (poziom_menu==2) {
lcd_locate(1,0);
lcd_str("T 550 zew.:");
X = 1; Y = 11;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
if (poziom_menu==3) {
lcd_locate(1,0);
lcd_str("T CUT30 zew.:");
X = 1; Y = 13;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
if (poziom_menu==4) {
lcd_locate(1,0);
lcd_str("T grz1:");
X = 1; Y = 7;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
if (poziom_menu==5) {
lcd_locate(1,0);
lcd_str("T grz2:");
X = 1; Y = 7;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
if (poziom_menu==6) {
lcd_locate(1,0);
lcd_str("T grz3:");
X = 1; Y = 7;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
if (poziom_menu==7) {
lcd_locate(1,0);
lcd_str("Lokalizacja");
X = 1; Y = 7;
lcd_locate(X,Y);
Tustaw[poziom_menu-1] = eeprom_read_byte(&eeTustaw[poziom_menu-1]);
lcd_int(Tustaw[poziom_menu-1]);
}
init=1;
}
void menu_w_przod (void) {
if (init) menu();
lcd_on();
Timer_podswietlenia=100; // powinno być 163
}
void licznik_rep(void) {
if(init) {
lcd_locate(X,Y);
lcd_int(++Tustaw[poziom_menu-1]);
eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
lcd_str(" ");
lcd_on(); /* podświetlenie wyświetlacza LCD */
}
}
void licznik_wstecz_rep(void) {
if(init) {
lcd_locate(X,Y);
lcd_int(--Tustaw[poziom_menu-1]);
eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
lcd_str(" ");
lcd_on(); /* podświetlenie wyświetlacza LCD */
}
}
void count_licznik(void){
if(init) {
lcd_locate(X,Y);
lcd_int(++Tustaw[poziom_menu-1]);
eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
lcd_str(" ");
lcd_on(); /* podświetlenie wyświetlacza LCD */
}
}
void count_licznik_wstecz(void){
if(init) {
lcd_locate(X,Y);
lcd_int(--Tustaw[poziom_menu-1]);
eeprom_write_byte(&eeTustaw[poziom_menu-1], Tustaw[poziom_menu-1]);
lcd_str(" ");
lcd_on(); /* podświetlenie wyświetlacza LCD */
}
}
int main(void) {
DDRA |= (1<<PA7); // port PA7 jest wyjściem - podświetlenie wyświetlacza
DDRA |= LED1|LED2|LED3|LED4|LED5|LED6|LED7;
lcd_init();
LED1_OFF;LED2_OFF;LED3_OFF;LED4_OFF;LED5_OFF;LED6_OFF;LED7_OFF;
PORTB |= KL1|KL2|KL3|KL4;
rtc_init();
rtc_control_reg(0,0x01,0,0); // ustawienie RTC wraz z Timerem 1Hz
rtc_set_time(0x00,0x07,0x16,0x00,0x00); //ustawienie godz 16:07:00 - działa !
rtc_set_date(Saturday,0x15,0x05,0x11); // ustawienie daty 15/05/2011 - działa !
/* Timer2 – inicjalizacja Timera0 */
TCCR0 |= (1<<WGM01); // tryb pracy CTC
TCCR0 |= (1<<CS02)|(1<<CS00); // preskaler = 1024 -> 7812Hz -> 0,128ms
OCR0 = 255; // przerwanie porównania -> 30,63Hz -> 32ms
TIMSK |= (1<<OCIE0); // Odblokowanie przerwania CompareMatch
/* Inicjalizacja przerwania INT0 */
MCUCR |= (1<<ISC01); //wyzwolenie zboczem opadającym
GICR |= (1<<INT0); //odblokowanie przerwania
PORTD |= (1<<PD2); // podciągnięcie pinu INT0 do VCC
sei();
int Zm=1;
while(1) {
uint8_t k1, k2, k3;
SuperDebounce(&k1, &PINB, KL1, 36, 36, menu_w_przod, menu );
SuperDebounce(&k2, &PINB, KL2, DEFAULT, DEFAULT, count_licznik, licznik_rep );
SuperDebounce(&k3, &PINB, KL3, DEFAULT, DEFAULT, count_licznik_wstecz, licznik_wstecz_rep );
if( !Timer2 ) {
Timer2=20; //powinno byc 36 to by było 1 sek, na razie przyspieszamy
/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 0 zamieniaj data/godz */
if( 0 == (sekundy%3) ) {
if (!poziom_menu) {
if (Zm && !poziom_menu) { // tu wstawic procedurę wyswietlająca aktualną datę/godzinę
lcd_locate(0,0);lcd_str(" Zm=1 ");
rtc_get_czas();
lcd_int(h_hrs); lcd_str("-");lcd_int(m_min);lcd_str("-"); lcd_int(s_sek);
lcd_locate(1,0);
rtc_get_time(1);
//lcd_str("H-46000 V12000 ");
Zm = 0;
}
else {
lcd_locate(0,0);lcd_str(" Zm=0 ");
//rtc_get_date();
Zm = 1;
}
}
}
/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 1 wysyłaj rozkaz pomiaru do czujników */
//if( 1 == (sekundy%3) ) DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL );
/* co trzy sekundy gdy reszta z dzielenia modulo 3 == 2 czyli jedną sekundę po rozkazie konwersji
* dokonuj odczytu i wyświetlania temperatur z 4 czujników jeśli są podłączone, jeśli nie
* to pokaż komunikat o błędzie*/
// if( 2 == (sekundy%3) ) {
// if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[0], &subzero, &cel, &cel_fract_bits) ) {
// display_temp(0,5);
// if (subzero) znak=-1; else znak=1;
// T[0] = znak*(cel*10 + cel_fract_bits);
// }
// else {
// lcd_locate(0,5);
// lcd_str(" err ");
// LED1_OFF;
// }
//
// if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[1], &subzero, &cel, &cel_fract_bits) ) {
// display_temp(0,11);
// if (subzero) znak=-1; else znak=1;
// T[1] = znak*(cel*10 + cel_fract_bits);
// }
// else {
// lcd_locate(0,11);
// lcd_str(" err ");
// }
// if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[2], &subzero, &cel, &cel_fract_bits) ) {
// display_temp(1,5);
// if (subzero) znak=-1; else znak=1;
// T[2] = znak*(cel*10 + cel_fract_bits);
// }
// else {
// lcd_locate(1,5);
// lcd_str(" err ");
// }
// if( DS18X20_OK == DS18X20_read_meas(gSensorIDs[3], &subzero, &cel, &cel_fract_bits) ) {
// display_temp(1,11);
// if (subzero) znak=-1; else znak=1;
// T[3] = znak*(cel*10 + cel_fract_bits);
// }
// else {
// lcd_locate(1,11);
// lcd_str(" err ");
// }
// }
sekundy++;
if (sekundy>2) sekundy = 0;
};
if( !Timer_podswietlenia ) {
PORTA &= ~(1<<PA7); /* wył. podświetlenia wyświetlacza LCD */
};
if (!Timer_menu0 && poziom_menu) { //timer wyjścia z menu po kilku sekundach
poziom_menu = 0;// wróć do menu 0
lcd_cls();
init = 0;
lcd_str("TRYB NORMALNY ");
}
}
}
/************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************
*
* ZALETY:
* - nie wprowadza najmniejszego spowalnienia
* - posiada funkcję REPEAT (powtarzanie akcji dla dłużej wciśniętego przycisku)
* - można przydzielić różne akcje dla trybu REPEAT i pojedynczego kliknięcia
* - można przydzielić tylko jedną akcję wtedy w miejsce drugiej przekazujemy 0 (NULL)
*
* Wymagania:
* Timer programowy utworzony w oparciu o Timer sprzętowy (przerwanie 100Hz)
*
* Parametry wejściowe:
* *key_state - wskaźnik na zmienną w pamięci RAM (1 bajt)
* *KPIN - nazwa PINx portu na którym umieszczony jest klawisz, np: PINB
* key_mask - maska klawisza np: (1<<PB3)
* rep_time - czas powtarzania funkcji rep_proc w trybie REPEAT
* rep_wait - czas oczekiwania do przejścia do trybu REPEAT
* push_proc - wskaźnik do własnej funkcji wywoływanej raz po zwolenieniu przycisku
* rep_proc - wskaźnik do własnej funkcji wykonywanej w trybie REPEAT
**************************************************************************************/
void SuperDebounce(uint8_t * key_state, volatile uint8_t *KPIN,
uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,
void (*push_proc)(void), void (*rep_proc)(void) ) {
enum {idle, debounce, go_rep, wait_rep, rep};
if(!rep_time) rep_time=3;
if(!rep_wait) rep_wait=6*3.6;
uint8_t key_press = !(*KPIN & key_mask);
if( key_press && !*key_state ) {
*key_state = debounce;
Timer1 = 4;
} else
if( *key_state ) {
if( key_press && debounce==*key_state && !Timer1 ) {
*key_state = 2;
Timer1=4;
} else
if( !key_press && *key_state>1 && *key_state<4 ) {
if(push_proc) push_proc(); /* KEY_UP */
*key_state=idle;
} else
if( key_press && go_rep==*key_state && !Timer1 ) {
*key_state = wait_rep;
Timer1=rep_wait;
} else
if( key_press && wait_rep==*key_state && !Timer1 ) {
*key_state = rep;
} else
if( key_press && rep==*key_state && !Timer1 ) {
Timer1 = rep_time;
if(rep_proc) rep_proc(); /* KEY_REP */
}
}
if( *key_state>=3 && !key_press ) *key_state = idle;
}
ISR(TIMER0_COMP_vect)
{
static uint8_t n;
n = Timer1; /* 100Hz Timer1 */
if (n) Timer1 = --n;
n = Timer2; /* 100Hz Timer2 */
if (n) Timer2 = --n;
n = Timer_podswietlenia;
if (n) Timer_podswietlenia= --n;
n = Timer_menu0;
if (n) Timer_menu0= --n;
}
ISR(INT0_vect) {
int0_flag = 1;
LED3_TOG;
}