//******************************************************************************
// Demo - MSP430F169, I2C, Read/Store Time from Maxim DS 1337
//
// Description:  This code will configure a TI MSP430F169 to read time-keeping
// registers from a Maxim DS 1337 real-time clock. First the I2C module will be
// disabled in order to allow correct configuration.  The module will use the
// ACLK (external 32.768 kHz crystal required) and set up the high and low
// periods of the SCL signal for 6.6kHz (max for DS1337 normal mode is 100kHz).
// The module is then configured to read/write one byte at a time.  The DS1337
// will be the slave in this case with address 0x68.  Once all settings have
// been configured the I2C module is then enabled, set to master mode and writes
// to the RTC in order to reset the register pointer to read the seconds
// register first.  Once this is complete the seconds, minutes, hours, date,
// month and year registers are read and stored into the corresponding variable.
// The day register is not stored since this can be determined from the date but
// must be read in order to increment the register pointer. The time is then 
// printed in the format "Month/Date/Year Hour:Min:Sec".  Open up the terminal 
// I/O under the View menu while debugging to see the printed time.  The program 
// will then loop around to read time and print time continuously.  Various I2C 
// flags are used for flow control.
//
// Stefan Gadomski
// UC Santa Cruz
// June 2, 2007
// Senior Design 123B
// Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************


#include <msp430x16x.h>
#include <stdio.h>

unsigned int i = 0;
unsigned char second;
unsigned char minute;
unsigned char hour;
unsigned char day;
unsigned char date;
unsigned char month;
unsigned char year;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                         // Stop watchdog
  P3SEL |= 0x0A;                                    // Assign I2C pins to module
  U0CTL |= I2C + SYNC;                              // Switch USART0 to I2C mode (Reccommended I2C init procedure)
  U0CTL &= ~I2CEN;                                  // Disable the I2C module (Recommended I2C init procedure)
  
  // Now configure I2C Module with I2CEN  = 0
  
  I2CTCTL |= I2CSSEL_1;                             // Use ACLK
  I2CSCLH = 0x00;                                   // High period of SCL
  I2CSCLL = 0x00;                                   // Low period of SCL
  I2CNDAT = 0x01;                                   // Read/Write 1 byte (byte = 8 bits) 
  I2CSA = 0x0068;                                   // Slave address is 0x68 (from RTC data sheet)
  
  // Now enable I2C Module

  U0CTL |= I2CEN;                                   // Enable I2C using a 7-bit address

  while (1)
  {
    while ((I2CDCTL & I2CBUSY) == I2CBUSY);         // If I2C is busy do nothing
    I2CIFG &= ~TXRDYIFG;                            // Reset TXRDYIFG bit
    U0CTL |= MST;                                   // Master mode
    I2CIFG &= ~ARDYIFG;                             // Reset ARDYIFG bit
    I2CTCTL |= I2CTRX + I2CSTT + I2CSTP;            // Transmit, ST, SP (clears MST)
    while ((I2CIFG & ARDYIFG) != ARDYIFG)           // Check if all data has been sent
    {
      while (( I2CIFG & TXRDYIFG) != TXRDYIFG);      // Do nothing if I2C is not ready to transmit data
      I2CDRB = 0x00;                                // Reset register pointer to read seconds first
      I2CIFG |= ARDYIFG;                            // All data has been sent
      }
    while ((I2CDCTL & I2CBUSY) == I2CBUSY);          // If I2C is still busy do nothing
    while ( i < 7)
    {
      I2CIFG &= ~ARDYIFG;                           // Reset ARDYIFG bit
      I2CTCTL &= ~I2CTRX;                           // Reset I2CTRX bit
      U0CTL |= MST;                                 // Master mode
      I2CTCTL |= I2CSTT + I2CSTP;                   // Read, ST, SP (clears MST)
      while ((I2CIFG & ARDYIFG) != ARDYIFG)         // Check if all data has been read
      {
        while (( I2CIFG & RXRDYIFG) != RXRDYIFG);    // Do nothing if I2C is not ready to read data
        switch (i)
		{
		case 0:
			second = I2CDRB;         // Read and store seconds
                        I2CIFG |= ARDYIFG;          // All data has been read
			break;
		case 1:
			minute = I2CDRB;         // Read and store minutes
                        I2CIFG |= ARDYIFG;
			break;
		case 2:
			hour = I2CDRB;           // Read and store hours
                        I2CIFG |= ARDYIFG;
			break;
		case 3:
			day = I2CDRB;               // Read but don't store day (must read to increment pointer)
                        I2CIFG |= ARDYIFG;
			break;
		case 4:
			date = I2CDRB;           // Read and store date
                        I2CIFG |= ARDYIFG;
			break;
		case 5:
			month = I2CDRB;          // Read and store month
                        I2CIFG |= ARDYIFG;
			break;
		case 6:
			year = I2CDRB;           // Read and store year
                        I2CIFG |= ARDYIFG;
			break;
		}
        i++;
      }
    }
    i = 0;
    
    // Now print time in format Month/Date/Year Hour:Min:Sec
        
    printf ("%x/", month);
    printf ("%x/", date);
    printf ("200%x ", year);
    printf ("%x:", hour);
    printf ("%x:", minute);
    printf ("%x\n\n", second);
  }
}
