typedef struct _ds1305_Time
{
  unsigned char ucSeconds;
  unsigned char ucMinutes;
  unsigned char ucHours;
  unsigned char ucDay;
  unsigned char ucDate;
  unsigned char ucMonth;
  unsigned char ucYear;
} ds1305_Time;

typedef ds1305_Time ds1305_BCDTime;

extern void ds1305_Init();

extern void ds1305_ReadBlock(unsigned char iAddr, unsigned char *pBuffer, unsigned int iCount);
extern void ds1305_WriteBlock(unsigned char iAddr, unsigned char *pBuffer, unsigned int iCount);

#define GetCurrentTime(pds1305_Time) ds1305_ReadBlock( 0, (unsigned char *)pds1305_Time,sizeof(ds1305_Time))
#define SetCurrentTime(pds1305_Time) ds1305_WriteBlock( 0, (unsigned char *)pds1305_Time,sizeof(ds1305_Time))








// PORTS: fixe la pin SS comme une sortie
// désactive le mode détection de faute 
// choix de la phase du signal: CPOL = 0 et  CPHA = 1
//

void ds1305_Init()
{
	PORTD = PORTD | 0x38;
	DDRD = DDRD | 0x38;
		
	ds1305_spi_deselect();
	
	SPCR = 0x54;
}





// Need to insure that this is CPHA = 1 due to the 
// timing requirements of the part. If the SPI bus is shared
// with other devices, their Select routines should reset these
// parameters to their value.
// Raising the line enables the part

void ds1305_spi_select() {
	SPCR = SPCR | 0x04; 
	PORTB = PORTB | 0x01;
}

//
// This routine deselects the device by lowering the CE
// line. Must be done after the xfer is complete
//
void ds1305_spi_deselect() { 
	PORTB = PORTB & 0xFE; 
}

// This routine exchanges 1 byte with the SPI port. 
unsigned char ds1305_spi_xfer(unsigned char cByte)
{
	SPDR = cByte;
	while ((SPSR & 0x80) == 0);
	return SPDR;
}
//
// ReadBlock reads iCount bytes starting at cAddr into the
// buffer pBuffer
//
void ds1305_ReadBlock(unsigned char cAddr, unsigned char *pBuffer, unsigned int iCount)
{
	ds1305_spi_select();
	ds1305_spi_xfer(cAddr);
	while(iCount--)
	{
		*pBuffer++ = ds1305_spi_xfer(0);
	}
	ds1305_spi_deselect();
}

//
// WriteBlock sends iCount bytes from the buffer pBuffer
// to the device at iAddr + 0x80. The device uses a split
// memory map where all write addresses are at address +0x80
//
void ds1305_WriteBlock(unsigned char iAddr, unsigned char *pBuffer, unsigned int iCount)
{
	ds1305_spi_select();
	ds1305_spi_xfer(iAddr + 0x80);
	while(iCount--)
	{
		 ds1305_spi_xfer(*pBuffer++);
	}
	ds1305_spi_deselect();
}








void main()
{
	ds1305_Time dsTime;
	unsigned char LastSeconds;
	unsigned char tc;

	BAUD = 0x30;
	SCCR2 = 0x0c;
		

}


//
// BCDOutput takes a BCD encoded byte (c) and prints the value out. The 
// output is in decimal, and will always consist of two characters. 
//
void BCDOutput(unsigned char c)
{
	putchar( ((c & 0xF0) >> 4) + '0');
	putchar( (c & 0xF) + '0');
}

//
// The pragma here places the data segment inside the text segment. If 
// you have constant strings, this is a good thing to do so they are 
// not placed in RAM.
//
#pragma data:text

char *pDates[] = { "Inv","Sun","Mon","Tue","Wed","Thu","Fri","Sat" };

#pragma data:data


//
// This function outputs a ds1305_Time structure to the console.
//
//
void OutputTimeDate(ds1305_Time *ptd)
{
	// Start by outputting date fields
	
	puts(pDates[(ptd->ucDay) & 0x07 ]);
	putchar(' ');
	BCDOutput(ptd->ucMonth);
	putchar('/');
	BCDOutput(ptd->ucDate);
	putchar('/');
	BCDOutput(ptd->ucYear);
	
	putchar(' ');
	BCDOutput(ptd->ucHours & 0x3F);
	putchar(':');
	BCDOutput(ptd->ucMinutes);
	putchar(':');
	BCDOutput(ptd->ucSeconds);
	putchar('\n');
}

//
// This simple programs job is to initialize the ds1305, then sit
// in a loop and print out the Time/Date every second or so. The seconds
// timer uses the output from the time keeping chip.
//
void main()
{
	ds1305_Time dsTime;
	unsigned char LastSeconds;
	unsigned char tc;

	BAUD = 0x30;
	SCCR2 = 0x0c;
		
	puts("ds1305t\n");
	ds1305_Init();
	//
	// Enable timer and unwrite protect memory
	//
	tc = 0;
	ds1305_WriteBlock(0x0F,&tc,1);
	
	
	do
	{
		GetCurrentTime(&dsTime);
		if(LastSeconds != dsTime.ucSeconds)
		{
			OutputTimeDate(&dsTime);
			LastSeconds = dsTime.ucSeconds;
		}
		
	} while (1);
}

//
// A Reset vector for this program.
//
extern void _start(void);

#pragma abs_address:0xfffe
void (*interrupt_vectors[])(void) =
{
	_start
};

#pragma end_abs_address












PORTS &= ~SS;

DDRS |= (SS|SCK|MOMI); /* sets bit 7,6,5 of DDRS as outputs */

SP0BR = 0x03;            /* set bit rate to 500 kHz */

SP0CR1 = 0x71;          /* Enable,Mstr,WireOR,CPOL:CPHA=00,LSB First*/

SP0CR2 = 0x01;          /* Bidirectional SPI (M0MI) */

 

1.      The SS line is set low to ensure that there is no accidental read or write to the clock.

2.      The ports data direction register sets bit 7, 6 and 5 as outputs.

3.      SP0BR is the SCK baud rate generation register, this is set at 500 kHz.

4.      SP0CR1 sets the 68HC12 as the master device, data transmission in wired or mode (bidirectional), the clock phase and polarity bits are 0, and data is transmitted least significant byte first.

5.      SP0CR2 sets PS5 as MOMI for bidirectional data transmission.