/* ------------- Real Time Clock and 56 byte NVRAM ------------- */ #include <intrins.h> #include "ds1307.h" #include "display.h" #include "serial.h" sbit SDA = 0xE9; /* P4.1 DS1307 serial data */ sbit SCL = 0xEA; /* P4.2 DS1307 serial clock */ #define NOP5() _nop_();_nop_();_nop_();_nop_();_nop_() #define SCL_HIGH(errmsg) {unsigned char i = 10; SCL = 1; while(!SCL)\ if(i-- == 0) halt(13, errmsg);} bit ds1307_send(unsigned char value) { unsigned char i = 8; bit ack; while(i--) { SDA = value & 0x80 ? 1 : 0; value = value << 1; SCL_HIGH("SCL ds1307_send()\n#1"); NOP5(); SCL = 0; NOP5(); } SDA = 1; SCL_HIGH("SCL ds1307_send()\n#2"); ack = SDA; SCL = 0; return ack; } unsigned char ds1307_receive(bit ack) { unsigned char buf, i = 8; SDA = 1; NOP5(); while(i--) { SCL_HIGH("ds1307_receive()\n#1"); NOP5(); buf = buf << 1 | SDA; SCL = 0; NOP5(); } SDA = ack; /* ack */ SCL_HIGH("ds1307_receive()\n#2"); NOP5(); SCL = 0; return buf; } void ds1307_start() { SDA = 1; SCL_HIGH("ds1307_start()\n#1"); if(!SDA) halt(14, "ds1307_start()\n#2 SDA fault"); SDA = 0; NOP5(); SCL = 0; } void ds1307_stop() { SDA = 0; SCL_HIGH("ds1307_stop()\nSCL fault"); NOP5(); SDA = 1; } unsigned char ds1307_get_byte(unsigned char num) { ds1307_start(); if(ds1307_send(0xD0)) halt(23, "DS1307 no ACK\non writing"); if(ds1307_send(num)) halt(24, "DS1307 no ACK\non writing"); ds1307_stop(); NOP5(); ds1307_start(); if(ds1307_send(0xD1)) halt(25, "DS1307 no ACK\non reading"); return ds1307_receive(1); ds1307_stop(); } void ds1307_set_byte(unsigned char addr, unsigned char value) { ds1307_start(); if(ds1307_send(0xD0)) halt(23, "DS1307 no ACK\in set_byte() #1"); if(ds1307_send(addr)) halt(23, "DS1307 no ACK\in set_byte() #2"); if(ds1307_send(value)) halt(23, "DS1307 no ACK\in set_byte() #3"); ds1307_stop(); } void ds1307_set_ulong(unsigned char addr, unsigned long value) { unsigned char i = 4; ds1307_start(); if(ds1307_send(0xD0)) halt(23, "DS1307 no ACK\in set_ulong() #1"); if(ds1307_send(addr)) halt(23, "DS1307 no ACK\in set_ulong() #2"); while (i--) { if(ds1307_send(value & 0xFFUL)) halt(23, "DS1307 no ACK\in set_ulong() #3"); value >>= 8; } ds1307_stop(); } unsigned long ds1307_get_ulong(unsigned char addr) { unsigned long value; ds1307_start(); if(ds1307_send(0xD0)) halt(23, "DS1307 no ACK\non writing"); if(ds1307_send(addr)) halt(24, "DS1307 no ACK\non writing"); ds1307_stop(); NOP5(); ds1307_start(); if(ds1307_send(0xD1)) halt(25, "DS1307 no ACK\non reading"); value = ds1307_receive(0); value |= (unsigned long)ds1307_receive(0) << 8 ; value |= (unsigned long)ds1307_receive(0) << 16 ; value |= (unsigned long)ds1307_receive(1) << 24 ; ds1307_stop(); return value; } void ds1307_set_int(unsigned char addr, int value) { unsigned char i = 2; ds1307_start(); if(ds1307_send(0xD0)) halt(23, "DS1307 no ACK\in set_int() #1"); if(ds1307_send(addr)) halt(23, "DS1307 no ACK\in set_int() #2"); while (i--) { if(ds1307_send(value & 0xFFUL)) halt(23, "DS1307 no ACK\in set_int() #3"); value >>= 8; } ds1307_stop(); } int ds1307_get_int(unsigned char addr) { int value; ds1307_start(); if(ds1307_send(0xD0)) halt(23, "DS1307 no ACK\non writing"); if(ds1307_send(addr)) halt(24, "DS1307 no ACK\non writing"); ds1307_stop(); NOP5(); ds1307_start(); if(ds1307_send(0xD1)) halt(25, "DS1307 no ACK\non reading"); value = ds1307_receive(0); value |= (unsigned long)ds1307_receive(1) << 8 ; ds1307_stop(); return value; } void ds1307_init() { unsigned char tmp; ds1307_receive(1); /* clear the buffer */ SCL_HIGH("ds1307_init()\nSCL FAULT #1"); NOP5(); SDA = 1; NOP5(); if (!SDA) halt(12, "ds1307_init()\nSDA line FAULT"); tmp = ds1307_get_byte(0x02); if (tmp & 0x40) /* 12hr selected ? */ ds1307_set_byte(0x02, tmp & 0x3F); /* 24hr */ tmp = ds1307_get_byte(0x00); if(tmp & 0x80) /* clock running ?*/ ds1307_set_byte(0x00, tmp & 0x7F); ds1307_set_byte(0x07, 0x90); /* enable 1Hz SQW signal */ } void ds1307_set_date_time(char yy, char mm, char dd, char h, char m, char dow) { ds1307_start(); if(ds1307_send(0xD0)) halt(30, "DS1307 no ACK\nset_date() #1"); if(ds1307_send(0x00)) halt(30, "DS1307 no ACK\nset_date() #2"); ds1307_send(0); /* seconds to zero. Start clock also */ ds1307_send(((m/10) << 4) | m%10); ds1307_send(((h/10) << 4) | h%10); ds1307_send(dow); ds1307_send(((dd/10) << 4) | dd%10); ds1307_send(((mm/10) << 4) | mm%10); ds1307_send(((yy/10) << 4) | yy%10); ds1307_stop(); } void show_time(void) { unsigned char h, m, s; ds1307_start(); if(ds1307_send(0xD0)) halt(31, "DS1307 no ACK\nshow_time() #1"); if(ds1307_send(0x00)) halt(31, "DS1307 no ACK\nshow_time() #2"); ds1307_stop(); NOP5(); ds1307_start(); if(ds1307_send(0xD1)) halt(31, "DS1307 no ACK\nshow_time() #3"); s = ds1307_receive(0); m = ds1307_receive(0); h = ds1307_receive(1); ds1307_stop(); lcd_send(0, 0x80 | 0x08); /* set DDRAM address */ lcd_send(1, (h>>4) + '0'); lcd_send(1, (h & 0x0F) + '0'); lcd_send(1, ':'); lcd_send(1, (m >> 4) + '0'); lcd_send(1, (m & 0x0F) + '0'); } /* Fills the buffer with current time and date */ void syslog_time(void) { unsigned char h, m, s; ds1307_start(); if(ds1307_send(0xD0)) halt(31, "DS1307 no ACK\nshow_time() #1"); if(ds1307_send(0x00)) halt(31, "DS1307 no ACK\nshow_time() #2"); ds1307_stop(); NOP5(); ds1307_start(); if(ds1307_send(0xD1)) halt(31, "DS1307 no ACK\nshow_time() #3"); s = ds1307_receive(0); m = ds1307_receive(0); h = ds1307_receive(0); push_char((h>>4) + '0'); push_char((h & 0x0F) + '0'); push_char(':'); push_char((m >> 4) + '0'); push_char((m & 0x0F) + '0'); #ifdef LONG_TIME push_char('.'); push_char((s >> 4) + '0'); push_char((s & 0x0F) + '0'); #endif push_char(' '); ds1307_receive(0); /* DOW */ s = ds1307_receive(0); /* day */ m = ds1307_receive(0); /* month */ h = ds1307_receive(1); /* year */ ds1307_stop(); #ifdef LONG_TIME push_char((h>>4) + '0'); push_char((h & 0x0F) + '0'); push_char('/'); #endif push_char((m >> 4) + '0'); push_char((m & 0x0F) + '0'); push_char('/'); push_char((s >> 4) + '0'); push_char((s & 0x0F) + '0'); push_char(' '); }