#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#define CE PD4 //definitions
#define SCLK PD2
#define IO PD3
#define READ 1
#define WRITE 0
// 0x80 seconds write
// 0x81 seconds read
// 0x82 minutes write
// 0x83 minutes read
// 0x84 hour write
// 0x85 hour read
// 0x86 date write
// 0x87 date read
// 0x88 month write
// 0x89 month read
// 0x90 trick charger write
// 0x91 trickle charger read
// 0x8A day write
// 0x8B day read
// 0x8C day write
// 0x8D day read
// 0x8E write protect bit write
void reset(void); //define the functions
void send(unsigned char);
unsigned char read(void);
void write_byte(unsigned char,unsigned char);
unsigned char read_byte(unsigned char);
unsigned char seconds(unsigned char,unsigned char);
unsigned char minutes(unsigned char,unsigned char);
unsigned char hours(unsigned char, unsigned char);
unsigned char get_day(unsigned char, unsigned char);
void rtc_init(void);
unsigned char get_seconds(void);
void trickle() {
reset();
send(0x90); // tell ds1302 what we want to read/write
send(0xA9); // turn on trickle charger, 1 diode, 2kohm resistor.
}
void rtc_init() {
unsigned char tmp; // temp variable
unsigned char tmp2; // temp variable
reset();
send(0x8E); // tell ds1302 what we want to read/write
send(0x00); // turn off write protect
reset(); // read seconds then write them back. this gets the clock ticking
send(0x81);
tmp = read();
//tmp &= ~(1<<7);
reset();
send(0x80);
send(tmp);
reset(); // read hours and make sure mode is on 24hour
send(0x85);
tmp = read();
tmp2 = (tmp & (1<<7));
if (tmp2) {
reset();
send(0x84);
tmp &= ~(1<<7);
send(tmp);
}
}
unsigned char write_seconds(unsigned char BYTE) {
reset(); // reset pins ready for communication
send(0x80); //tell ds1302 what we want to read/write
if (BYTE > 0x09) {
unsigned char tmp; // temp variable
tmp = BYTE / 0x0A; // copy tens of minutes to tmp
BYTE %= 0x0A; // remove tens of minutes from BYTE
BYTE |= (tmp<<4); //move tens of minutes across 4 bytes
}
send(BYTE); // write BYTE
}
unsigned char read_seconds(unsigned char units) {
reset(); // reset pins ready for communication
unsigned char tmp; // temp variable
send(0x81); // tell ds1302 what we want to read minutes
tmp = read(); // read byte previously requested
if (units == 1) tmp = (tmp & 0x0F); // grab first 4 bits
if (units == 10) tmp = ((tmp & 0x70) >> 4); // grab bits 5-7 and shift right
return tmp;
}
unsigned char write_minutes(unsigned char BYTE) {
reset(); // reset pins ready for communication
send(0x82); //tell ds1302 what we want to read/write
if (BYTE > 0x09) {
unsigned char tmp; // temp variable
tmp = BYTE / 0x0A; // copy tens of minutes to tmp
BYTE %= 0x0A; // remove tens of minutes from BYTE
BYTE |= (tmp<<4); //move tens of minutes across 4 bytes
}
send(BYTE); // write BYTE
}
unsigned char read_minutes(unsigned char units) {
reset(); // reset pins ready for communication
unsigned char tmp; // temp variable
send(0x83); // tell ds1302 what we want to read minutes
tmp = read(); // read byte previously requested
if (units == 1) tmp = (tmp & 0x0F); // grab first 4 bits
if (units == 10) tmp = ((tmp & 0x70) >> 4); // grab bits 5-7 and shift right
return tmp;
}
void write_hours(unsigned char BYTE) {
reset(); // reset pins ready for communication
send(0x84); //tell ds1302 what we want to read/write
if (BYTE > 0x09) {
unsigned char tmp; // temp variable
tmp = BYTE / 0x0A; // copy tens of minutes to tmp
BYTE %= 0x0A; // remove tens of minutes from BYTE
BYTE |= (tmp<<4); //move tens of minutes across 4 bytes
}
send(BYTE); // write BYTE
}
unsigned char read_hours(unsigned char units) {
reset(); // reset pins ready for communication
unsigned char tmp; // temp variable
send(0x85); // tell ds1302 what we want to read minutes
tmp = read(); // read byte previously requested
if (units == 1) tmp = (tmp & 0x0F); // grab first 4 bits
if (units == 10) tmp = ((tmp & 0x70) >> 4); // grab bits 5-7 and shift right
return tmp;
}
unsigned char day(unsigned char RW, unsigned char BYTE) {
reset(); // reset pins ready for communication
send(0x8D); // send ds1302 request for data
if (RW) {
unsigned char day; // temp variable
day = read(); // read byte previously requested
day = (day & 0x07); // grab first 3 bits
return day;
} else {
send(BYTE);
}
}
void send(unsigned char W_Byte) //writes the W_Byte to the DS1302
{
unsigned char i;
//DDRB = 0xFF;
DDRD |= ( (1<<IO) | (1<<SCLK) | (1<<CE) ); // set all 3 pins to output
for(i = 0; i < 8; i++)
{
//cbi(PORTD,io);
PORTD &= ~(1<<IO); // set IO to high
if(W_Byte &0x01) // compare bit 0, if high set IO to high
{
//sbi(PORTD,io);
PORTD |= (1<<IO); // set IO to high
}
//sbi(PORTD,clk);
PORTD |= (1<<SCLK);
//delay_ms(1);
//cbi(PORTD,clk);
PORTD &= ~(1<<SCLK);
//delay_ms(1);
W_Byte >>=1;
}
}
unsigned char read_byte(unsigned char w_byte) //read the byte with register w_byte
{
unsigned char temp;
reset();
send(w_byte);
temp = read();
//cbi(PORTD,rst);
//cbi(PORTD,clk);
PORTD &= ~(1<<CE);
PORTD &= ~(1<<SCLK);
return temp;
}
void reset(void) //sets the pins to begin and end the ds1302 communication
{
DDRD |= (1<<CE); // set as output
PORTD &= ~(1<<SCLK); // set SCLK low
PORTD &= ~(1<<CE); // set CE low
PORTD |= (1<<CE); // set CE high
}
unsigned char read(void) //reads the ds1302 reply
{
unsigned char i;
unsigned char R_Byte, TmpByte;
R_Byte = 0x00;
// initiate communication
DDRD |= (1<<IO); //set IO to output
PORTD &= ~(1<<IO); //set IO low
DDRD &= ~(1<<IO); // set IO to input
for(i = 0; i < 8; i++) //loop 8 times to read whole byte
{
TmpByte = 0; // clear TmpByte
//if(bit_is_set(PINB,io))
if (PIND & (1<<IO)) // if IO is high set TmpByte to 1
TmpByte = 1;
TmpByte <<= 7; // shift TmpByte to 7th
R_Byte >>= 1; // shift all of R_Byte to the right 1 to make room
R_Byte |= TmpByte; // |= to copy byte across if its set to 1
PORTD |= (1<<SCLK); //set SCLK to high
PORTD &= ~(1<<SCLK); // set SCLK to low
}
return R_Byte;
}