
#define  control_reg 0x07
#define  p     30         // Delay for I2C (10 @ 20MHz/30 @ 40MHz)
#bit     ds_i2c_scl  =  0x0F82.3
#bit     ds_i2c_sda  =  0x0F82.4
#bit     i2c_scl_tris   =  0x0F94.3
#bit     i2c_sda_tris   =  0x0F94.4
#bit     SSPEN    =  0x0FC6.5
#define STATUS 0x0FD8
#define  Z     2
#define  C     0
#define  NVR_offset  8
byte day,mth,year,hr,min;
//==============================

byte  ds_i2c_read();			// I2C read function
//BOOLEAN  ds_i2c_waitack(void);	
boolean  ds_i2c_write(int8  bytetosend);// I2C Write function
void  ds_i2c_sendack();			// I2C ACK
void  ds_i2c_sendnack();		// I2C NACK
void  ds_i2c_stop();			// I2C Stop
void  ds_i2c_start(void);		// I2C start
void  ds_i2c_in(void);			// Make I2C (SDA) float
void  ds_i2c_out(void);			// Make I2C (SDA) as output
void rtc_write_nvr(BYTE address, BYTE data);  // Write byte into DS1307 memory
BYTE rtc_read_nvr(BYTE address);	      // Read byte from  DS1307 memory
void get_datetime();			      // Get the time
int8 timetoi(int8 tm);			      // BCD to Int


BOOLEAN ds1307_ready() {
 int1 ack;
   ds_i2c_start();            // If the write command is acknowledged,
   ack = ds_i2c_write(0xD0);  // then the device is ready.
   ds_i2c_stop();
   return ack;
}

void write_ds1307(BYTE address, BYTE data) {
   while(!ds1307_ready());
   ds_i2c_start();
   ds_i2c_write(0xD0);
   ds_i2c_write(address);
   ds_i2c_write(data);
   ds_i2c_stop();
}

BYTE read_ds1307(BYTE address) {
   BYTE data;
//   while(!ds1307_ready());
   ds_i2c_start();
   ds_i2c_write(0xD0);
   ds_i2c_write(address);
   ds_i2c_start();
   ds_i2c_write(0xD1);
   data=ds_i2c_read();
   ds_i2c_stop();
   return(data);
}


void init_ds1307() {
   write_ds1307(0x00,0x00);  // Start Clock
   delay_us(250);
   write_ds1307(0x07,0b10010000); //Init Outputs (pin out outputs 1Hz)
}

void rtc_set_datetime(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min) {
   write_ds1307(0x04,day);
   write_ds1307(0x05,mth);
   write_ds1307(0x06,year);
   write_ds1307(0x03,dow);
   write_ds1307(0x02,hr);
   write_ds1307(0x01,min);
}

void rtc_get_date(BYTE& day, BYTE& mth, BYTE& year, BYTE& dow) {
   day = read_ds1307(0x04);
   mth = read_ds1307(0x05);
   year = read_ds1307(0x06);
   dow = read_ds1307(0x03);
}


void rtc_get_time(BYTE& hr, BYTE& min) {
   hr = read_ds1307(0x02);
   min = read_ds1307(0x01);
//   sec = read_ds1307(0x00);
}

void get_datetime()
{  //day = read_ds1307(0x04);
   //mth = read_ds1307(0x05);
   //year = read_ds1307(0x06);
   //hr = read_ds1307(0x02);
   //min = read_ds1307(0x01);
   ds_i2c_start();
   ds_i2c_write(0xD0);
   ds_i2c_write(0x01);  //minutes
   ds_i2c_start();
   ds_i2c_write(0xD1);
   min = ds_i2c_read();
   ds_i2c_sendack();
   hr =  ds_i2c_read();
   ds_i2c_sendack();   
   day = ds_i2c_read();
   ds_i2c_sendack();   
   day = ds_i2c_read();
   ds_i2c_sendack();
   mth = ds_i2c_read();
   ds_i2c_sendack();
   year = ds_i2c_read();
   ds_i2c_stop();   
}

void rtc_write_nvr(BYTE address, BYTE data) {
   write_ds1307(address,data); //+0x08
}

BYTE rtc_read_nvr(BYTE address) {
    return(read_ds1307(address)); //+0x08
}



//==================== I2C ROUTINES ====================
void ds_i2c_in(void)
{  SSPEN = 0;
   i2c_scl_tris = FALSE;
   i2c_sda_tris = TRUE;
}

void  ds_i2c_out(void)
{  SSPEN = 0;
   i2c_scl_tris = FALSE;
   i2c_sda_tris = FALSE;
}

void  ds_i2c_start(void)
{  ds_i2c_out();
   ds_i2c_scl = TRUE;
   ds_i2c_sda = TRUE;
   delay_us(p);
   ds_i2c_sda = FALSE;
   delay_us(p);
   ds_i2c_scl = FALSE;
   delay_us(p);
}

void  ds_i2c_stop()
{  ds_i2c_out();
   ds_i2c_scl  =  FALSE;
   ds_i2c_sda  =  FALSE;
   delay_us(p);
   ds_i2c_scl  =  TRUE;
   delay_us(p);
   ds_i2c_sda  =  TRUE;
   delay_us(p);
   SSPEN = 1;
}

void  ds_i2c_sendnack()
{  ds_i2c_out();
   ds_i2c_sda  =  TRUE;
   ds_i2c_scl  =  TRUE;
   delay_us(p);
   ds_i2c_scl  =  FALSE;
}

void  ds_i2c_sendack()
{  ds_i2c_out();
   ds_i2c_sda  =  FALSE;
   ds_i2c_scl  =  TRUE;
   delay_us(p);
   ds_i2c_scl  =  FALSE;
}

//############## Converts BCD to integer #################
int8 timetoi(int8 tm)
//########################################################
{int8 returntime;
//Result := Ord(Ch) - (Ord(Ch) div 16)*6;
 returntime = tm - (tm/16)*6;
 return returntime;
}

boolean  ds_i2c_write(int8  bytetosend)
{  int8  i;
   int1 ack;
   ds_i2c_out();
#ASM
   movlw	0x08
   movwf	i
nextbitout:
    rlcf  bytetosend,f
    btfss   STATUS,C
    goto	i2cbitout0
i2cbitout1:
	bsf		ds_i2c_sda
	goto	i2cbitoutcnt
i2cbitout0:
	bcf		ds_i2c_sda
i2cbitoutcnt:
	bsf		ds_i2c_scl
#ENDASM
    delay_us(p);
#ASM
	bcf		ds_i2c_scl
	decfsz	i,f
	goto	nextbitout
#ENDASM
	ds_i2c_in();
#ASM
i2cwaitack:
	bsf		ds_i2c_scl
	clrf		i
waitack:
	decfsz	i,f
	goto	chksda
	bcf		ack
	bcf		ds_i2c_scl
	goto	endcheck
chksda:
	btfsc	ds_i2c_sda			; Wait till SDA goes LOW
	goto	waitack
	bcf		ds_i2c_scl			; Clock goes LOW
	bsf		ack
#ENDASM
endcheck:
   return   ack ;
}

byte  ds_i2c_read()
{int8 byteread,i;

   ds_i2c_in();
#ASM
   movlw 8
   movwf i
#ENDASM
nextbitin:
   ds_i2c_scl = True;
   delay_us(p);
#ASM
 	btfss	ds_i2c_sda		// if SDA is high then skip next cmd
	goto	iicbitin0
iicbitin1:
	bsf	STATUS,C			// Carry set to 1
	goto	iicbitincnt
iicbitin0:
	bcf	STATUS,C			// Carry set to 0
iicbitincnt:
	rlcf	byteread,f		// Increase IIC bit count to next bit
#ENDASM
   ds_i2c_scl = False;	// Clock goes LOW

   delay_us(p);
#ASM

	decfsz	i,f		    // buffer down 1 step
	goto	nextbitin
#ENDASM
   return byteread;
}
