SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By jaydel325
#194551
Hi! I'm trying to name datafiles with the DeadOn RTC time and populate that file with data streamed over UART0. I was able to echo time (YY_MO_DD_hh_mm_ss) from the RTC every 1 second to my computer COM port using UART1 and name files using this received time, but this was only accomplished by inserting delay_ms(...) statements throughout the code. Without these delays, the RTC time would be "00FF00FFFFFF" instead of the actual time ("170422172310" for example). What's even more strange is that adding variables or deleting unused code elsewhere in the program would also result in the "00FF00FFFFFF" output...even if the added/deleted code had nothing to do with SPI1 or the RTC. I tried playing with interrupt declarations, SPI1 functions implementations, RTC function implementations, etc. but nothing worked. Searching online for clarity yielded nothing as well, and the LPC2148 and DS3234 manuals didn't provide me with a good idea at where the problem is coming from in my implementation. I want to get this working, but I really want to understand WHY my firmware is behaving in this way.

the SPI1 code and main.c code are below:
Code: Select all
/*****************************************************************************
 *   ssp.h:  Header file for Philips LPC214x Family Microprocessors
 *
 *   Copyright(C) 2006, Philips Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2005.10.01  ver 1.00    Prelimnary version, first Release
 *
******************************************************************************/
#ifndef __SSP_H__
#define __SSP_H__

#include <stdint.h>

#define SSP_SS_PIN	20

/* SPI read and write buffer size */
#define BUFSIZE		256
#define FIFOSIZE	8

/* don't use CS, set CS as GPIO that you have total control
of the sequence */
#define USE_CS		0

/* SPI select pin */
#define SPI1_SEL	0x00100000

/* Chip Select Defines for SSP */
#define	SSP_SS_IOCLR	IOCLR0
#define	SSP_SS_IOSET	IOSET0

#define select_ssp()   	SSP_SS_IOCLR |= (1<<SSP_SS_PIN)
#define unselect_ssp() 	SSP_SS_IOSET |= (1<<SSP_SS_PIN)

/* SPI Status register */
#define SSPSR_TFE	1 << 0
#define SSPSR_TNF	1 << 1 
#define SSPSR_RNE	1 << 2
#define SSPSR_RFF	1 << 3 
#define SSPSR_BSY	1 << 4

/* SPI 1 CR0 register */
#define SSPCR0_DSS	1 << 0
#define SSPCR0_FRF	1 << 4
#define SSPCR0_CPOL	1 << 6
#define SSPCR0_CPHA	1 << 7
#define SSPCR0_SCR	1 << 8

/* SPI 1 CR1 register */
#define SSPCR1_LBM	1 << 0
#define SSPCR1_NM	0 << 0
#define SSPCR1_SSE	1 << 1
#define SSPCR1_MS	1 << 2
#define SSPCR1_SOD	1 << 3

/* SPI 1 Interrupt Mask Set/Clear register */
#define SSPIMSC_RORIM	1 << 0
#define SSPIMSC_RTIM	1 << 1
#define SSPIMSC_RXIM	1 << 2
#define SSPIMSC_TXIM	1 << 3

/* SPI 1 Interrupt Status register */
#define SSPRIS_RORRIS	1 << 0
#define SSPRIS_RTRIS	1 << 1
#define SSPRIS_RXRIS	1 << 2
#define SSPRIS_TXRIS	1 << 3

/* SPI 1 Masked Interrupt register */
#define SSPMIS_RORMIS	1 << 0
#define SSPMIS_RTMIS	1 << 1
#define SSPMIS_RXMIS	1 << 2
#define SSPMIS_TXMIS	1 << 3

/* SPI 1 Interrupt clear register */
#define SSPICR_RORIC	1 << 0
#define SSPICR_RTIC		1 << 1

extern void SPI1Init( void );
extern void SPI1Send(  uint8_t wbyte ); 
extern uint8_t SPI1Receive( void ); 

#endif  /* __SSP_H__ */
/*****************************************************************************
**                            End Of File
******************************************************************************/
Code: Select all
/*****************************************************************************
 *   ssp.c:  SSP C file for Philips LPC214x Family Microprocessors
 *
 *   Copyright(C) 2006, Philips Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2005.10.01  ver 1.00    Prelimnary version, first Release
 *
*****************************************************************************/
#include "LPC214x.h"			/* LPC21XX Peripheral Registers	*/
#include "type.h"
#include "irq.h"
#include "ssp.h"

extern BYTE SPIWRData[BUFSIZE];
extern BYTE SPIRDData[BUFSIZE];
extern unsigned int CurrentTxIndex;
extern unsigned int CurrentRxIndex;




/*****************************************************************************
** Function name:		SPI1Init
**
** Descriptions:		SPI1(SSP) port initialization routine
**				
** parameters:			None
** Returned value:		true or false, if the interrupt handler
**				can't be installed correctly, return false.
** 
*****************************************************************************/
void SPI1Init( void )
{
    BYTE i, Dummy;

    /* Configure PIN connect block */
    /* bit 32, 54, 76 are 0x10, bit 98 are 0x00 */
    /* port 0 bits 17, 18, 19, 20 are SSP port SCK1, MISO1, MOSI1, and SSEL1 */
    /* set SSEL to GPIO pin that you will have the totoal freedom to set/reset 
    the SPI chip-select pin */
   
    SSPCR1 = SSPCR1_NM; 			/* SSP master in normal operation mode */

    IODIR0 = SPI1_SEL;				/* SSEL is output */
    unselect_ssp();					/* set SSEL to high */

		
    //VPBDIV = 0x02;  				/* Set PCLK to the same as CCLK */
    

   									/* Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 1, and SCR is 15 */
    SSPCR0 = 0x0787;

    SSPCPSR = 0x02;					/* SSPCPSR clock prescale register, master mode, minimum divisor is 0x02 */
    

    for ( i = 0; i < FIFOSIZE; i++ )
    {
	Dummy = SSPDR;					/* clear the RxFIFO */
    }
       
    								/* Device select as master, SSP Enabled, normal operational mode */
    SSPCR1 = SSPCR1_NM | SSPCR1_SSE;

}

/*****************************************************************************
** Function name:		SPI1Send
**
** Descriptions:		Send a block of data to the SPI1(SSP) port
**
** parameters:			unsigned int
** Returned value:		None
** 
*****************************************************************************/
void SPI1Send( uint8_t wbyte )
{	
									
	
	SSPDR = wbyte;
	while ( !(SSPSR & SSPSR_BSY) );	// Wait for byte to be shifted out
	
}

/*****************************************************************************
** Function name:		SPI1Receive
** Descriptions:		the module will receive a block of data from 
**				        the SPI1(SSP) port. 
**				
** parameters:			none
** Returned value:		unsigned int
** 
*****************************************************************************/
uint8_t SPI1Receive( void )
{

									
							
	while ( !(SSPSR & SSPSR_BSY) ); 	
	return SSPDR;

}

/******************************************************************************
**                            End Of File
******************************************************************************/
Code: Select all
/*********************************************************************************
 * Logomatic V2 Firmware
 * Sparkfun Electronics 2008
 * Modified by JayDel325
 * ******************************************************************************/

/*******************************************************
 *         Header Files
 ******************************************************/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "LPC214x.h"
#include "ssp.h"
#include <string.h>

//UART0 Debugging
#include "serial.h"
#include "rprintf.h"

//Needed for main function calls
#include "main_msc.h"
#include "fat.h"
#include "armVIC.h" 
#include "itoa.h"
#include "rootdir.h"
#include "sd_raw.h"
#include "string_printf.h"
#include "delay.h"


/*******************************************************
 *         Global Variables
 ******************************************************/

#define ON  1
#define OFF 0

#define THRE (1<<5) // Transmit Holding Register Empty
#define RDR (1<<0) // Receiver Data Ready

#define BUF_SIZE 512

char RX_array1[BUF_SIZE];
char RX_array2[BUF_SIZE];
char log_array1 = 0;
char log_array2 = 0;
short RX_in = 0;
char get_frame = 0;
int u = 0;

signed int stringSize;
struct fat_file_struct* handle;
struct fat_file_struct * fd;
char stringBuf[256];
//int time[7] = {2,17,2017,0,11,34,40};
uint8_t rtc_time[30];
uint8_t day;
uint8_t month;
uint8_t year;
uint8_t hour;
uint8_t minute;
uint8_t second;


// Default Settings
static char   mode = 0;
static char    asc = 'N';
static int    baud = 9600;
static int    freq = 100;
static char   trig = '$';
static short frame = 100;
static char  ad1_7 = 'N';
static char  ad1_6 = 'N';
static char  ad1_3 = 'N';
static char  ad1_2 = 'N';
static char  ad0_4 = 'N';
static char  ad0_3 = 'N';
static char  ad0_2 = 'N';
static char  ad0_1 = 'N';
static char  rtc_set = 'N';

/*******************************************************
 *     Function Declarations
 ******************************************************/

void Initialize(void);

void setup_uart0(int newbaud, char want_ints);
void setup_uart1(int newbaud, char want_ints);

void mode_0(void);
void mode_1(void);
void mode_2(void);
void mode_3(void);
void mode_4(void);
void mode_action(void);

void Log_init(void);
void test(void);
void stat(int statnum, int onoff);
void AD_conversion(int regbank);

void feed(void);

//UART1 Functions
char U1Read(void);
void U1Write(char data);

//Real-time Clock Functions for DS3234
void setTime(uint8_t mo, uint8_t d, uint8_t y, uint8_t h, uint8_t mi, uint8_t s);
void readTime(void);
void RTC_Init(void);

//BHW Never defined... static void IRQ_Routine(void) __attribute__ ((interrupt("IRQ")));
static void UART0ISR(void); //__attribute__ ((interrupt("IRQ")));
static void UART1ISR(void);
static void UART0ISR_2(void); //__attribute__ ((interrupt("IRQ")));
static void MODE2ISR(void); //__attribute__ ((interrupt("IRQ")));

void FIQ_Routine(void); //__attribute__ ((interrupt("FIQ")));
void SWI_Routine(void); //__attribute__ ((interrupt("SWI")));
void UNDEF_Routine(void); //__attribute__ ((interrupt("UNDEF")));

void fat_initialize(void);

int modulo(int num, int div);
uint8_t uint2bcd(uint8_t ival);



/*******************************************************
 *          MAIN
 ******************************************************/

int main (void)
{
  int i;
  char name[32];
  int count = 0;
  
  enableFIQ();
  
  Initialize();
  
  setup_uart0(9600, 0);

  fat_initialize();   

	

  // Flash Status Lights
  for(i = 0; i < 5; i++)
  {
    stat(0,ON);
    delay_ms(50);
    stat(0,OFF);
    stat(1,ON);
    delay_ms(50);
    stat(1,OFF);
  }
  
  Log_init();

  count++;  //BHW TODO: this makes the count start from 1, not 0 to match docs
  string_printf(name,"LOG%02d.txt",count);
  while(root_file_exists(name))
  {
    count++;
    if(count == 250)  //BHW TODO: This less than 250 limit doesn't match docs
    {
      rprintf("Too Many Logs!\n\r");
      while(1)
      {
        stat(0,ON);
        stat(1,ON);
        delay_ms(1000);
        stat(0,OFF);
        stat(1,OFF);
        delay_ms(1000);
      }

    }
    string_printf(name,"LOG%02d.txt",count);
  }
  
	delay_ms(10);					//inserted only because it helped get proper output from DS3234
  
  if (rtc_set == 'Y') 
  {
	//RTC_Init();					//only need to initialize DS3234 once
	day = uint2bcd(day);
	month = uint2bcd(month);
	year = uint2bcd(year);
	second = uint2bcd(second);
	minute = uint2bcd(minute);
	hour = uint2bcd(hour);
	
	setTime(day,month,year,hour,minute,second);
  }
    
  if(mode == 0){ mode_0(); }
  else if(mode == 1){ mode_1(); }
  else if(mode == 2){ mode_2(); }
  else if(mode == 3){ mode_3(); }
  else if(mode == 4){ mode_4(); }

      return 0;
}


/*******************************************************
 *         Initialize
 ******************************************************/

#define PLOCK 0x400

void Initialize(void)
{
  rprintf_devopen(putc_serial0);
  rprintf_devopen(putc_serial1);  //JD
  
  // 0xCF351505 = 0b 11 00 11 11 00 11 01 01 00 01 01 01 00 00 01 01
  // 0x154418A9 = 0b 00 01 01 01 01 00 01 00 00 01 10 00 10 10 10 01
  //
  // Symbol | Value | Function
  // -------|-------|----------------------------------
  // PINSEL0|       |
  // P0.0   | 01    | TXD (UART0)
  // P0.1   | 01    | RxD (UART0)
  // P0.2   | 00    | GPIO Port 0.2
  // P0.3   | 00    | GPIO Port 0.3
  // P0.4   | 01    | SCK0 (SPI0)
  // P0.5   | 01    | MISO0 (SPI0)
  // P0.6   | 01    | MOSI0 (SPI0)
  // P0.7   | 00    | GPIO Port 0.7
  // P0.8   | 01    | TXD (UART1)
  // P0.9   | 01    | RXD (UART1)
  // P0.10  | 11    | AD1.2
  // P0.11  | 00    | GPIO Port 0.11
  // P0.12  | 11    | AD1.3
  // P0.13  | 11    | AD1.4
  // P0.14  | 00    | GPIO Port 0.14
  // P0.15  | 11    | AD1.5
  // PINSEL1|       |
  // P0.16  | 01    | EINT0
  // P0.17  | 10    | SCK1 (SSP)
  // P0.18  | 10    | MISO1 (SSP)
  // P0.19  | 10    | MOSI1 (SSP)
  // P0.20  | 00    | GPIO Port 0.20
  // P0.21  | 10    | AD1.6
  // P0.22  | 01    | AD1.7
  // P0.23  | 00    | GPIO Port 0.23
  // P0.24  | 00    | Reserved
  // P0.25  | 01    | AD0.4
  // P0.26  | 00    | Reserved
  // P0.27  | 01    | Reserved
  // P0.28  | 01    | AD0.1
  // P0.29  | 01    | AD0.2
  // P0.30  | 01    | AD0.3
  // P0.31  | 00    | GPO Port only

  PINSEL0 = 0xCF351505;
  PINSEL1 = 0x154418A9;

  // P0.0  = INPUT  | TXD (UART0)
  // P0.1  = INPUT  | RxD (UART0)
  // P0.2  = OUTPUT | STAT0 LED
  // P0.3  = INPUT  | STOP Button
  // P0.4  = INPUT  | SCK0 (SPI0)
  // P0.5  = INPUT  | MISO0 (SPI0)
  // P0.6  = INPUT  | MOSI0 (SPI0)
  // P0.7  = OUTPUT | Chip Select 0
  // P0.8  = INPUT  | TXD (UART1)
  // P0.9  = INPUT  | RXD (UART1)
  // P0.10 = INPUT  | AD1.2
  // P0.11 = OUTPUT | STAT1 LED
  // P0.12 = INPUT	| AD1.3
  // P0.13 = INPUT	| AD1.4
  // P0.14 = INPUT	| GPIO Port 0.14
  // P0.15 = INPUT	| AD1.5
  // P0.16 = INPUT	| EINT0
  // P0.17 = INPUT	| SCK1 (SSP)
  // P0.18 = INPUT	| MISO1 (SSP)
  // P0.19 = INPUT	| MOSI1 (SSP)
  // P0.20 = OUTPUT	| GPIO Port 0.20
  // P0.21 = INPUT	| AD1.6
  // P0.22 = INPUT	| AD1.7
  // P0.23 = INPUT	| GPIO Port 0.23
  // P0.24 = INPUT	| Reserved
  // P0.25 = INPUT	| AD0.4
  // P0.26 = INPUT	| Reserved
  // P0.27 = INPUT	| Reserved
  // P0.28 = INPUT	| AD0.1
  // P0.29 = INPUT	| AD0.2
  // P0.30 = INPUT	| AD0.3
  // P0.31 = INPUT	| GPO Port only
  // Rest of Port 0 are inputs
  IODIR0 |= 0x00000884;
  IOSET0 = 0x00000080;  // Set P0.7 HIGH | CS0 HIGH

  S0SPCCR = 0x08;  // SPI clk to be pclk/8
  S0SPCR = 0x30;  // master, msb, first clk edge, active high, no ints
  
  SPI1Init(); // ssp.c

}

// Make values in PLL control & configure registers take effect 
void feed(void)
{
  // Interrupts must be disabled to make consecutive APB bus cycles
  PLLFEED=0xAA;
  PLLFEED=0x55;
}

/*******************************************************************************
*	Function: 		UART0ISR();
*
*	Description: 	UART0ISR is the routine that runs every time the UART0
*					interrupt triggers. This trigger happens whenever the 
*					uart0 read buffer is not empty. This function is designed
*					to collect data from a serial device attached to UART0 of
*					the Logomatic.
*				
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

static void UART0ISR(void)
{
  if(RX_in < BUF_SIZE)
  {
    RX_array1[RX_in] = U0RBR;
  
    RX_in++;

    if(RX_in == BUF_SIZE) log_array1 = 1;
  }
  else if(RX_in >= BUF_SIZE)
  {
    RX_array2[RX_in-BUF_SIZE] = U0RBR;
    RX_in++;

    if(RX_in == 2 * BUF_SIZE)
    {
      log_array2 = 1;
      RX_in = 0;
    }
  }


  U0IIR; // Have to read this to clear the interrupt 

  VICVectAddr = 0;  // Acknowledge interrupt
}

/*******************************************************************************
*	Function: 		UART1ISR();
*
*	Description: 	UART1ISR is the routine that runs every time the UART1
*					interrupt triggers. This trigger happens whenever the 
*					uart1 transmit buffer is empty. This function echos the
*					RTC time to the UART1 so engineers can verify RTC was
*					properly set.
*				
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

/*Unused interrupt routine*/
static void UART1ISR(void)
{
	
	int TimeDate [7]={0,0,0,0,0,0,0};
	delay_ms(500);

	
	char test_spi[15];
	
	
	
	select_ssp();
	
	SPI1Send(0x00);
	SPI1Receive();
	SPI1Send(0x00);
	unsigned char n = SPI1Receive();
	
	unselect_ssp();
	
	unsigned char a = (n & 0x0F);
	
	unsigned char b = (n & 0x70)>>4;
	TimeDate[0]=a+b*10;
	
	string_printf(test_spi,"%x",n);
	
	int c = 0;

	
	while (test_spi[c] != '\0')
	{
		U1Write(test_spi[c]);
		U1Write(0x80);
		c++;
		
	}
	
	U1Write('\n');
	c=0;
	
  U1IIR; // Have to read this to clear the interrupt 

  VICVectAddr = 0;  // Acknowledge interrupt
  
}


/*******************************************************************************
*	Function: 		UART0ISR_2();
*
*	Description: 	UART0ISR_2 is the routine that runs every time the UART0
*					interrupt triggers. This interrupt happens whenever the 
*					uart0 read buffer is not empty. This function is designed
*					to collect data from a serial device attached to UART0 of
*					the Logomatic, once an ASCII trigger is sent over UART0.
*				
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

static void UART0ISR_2(void)
{
  char temp;
  temp = U0RBR; // Read a byte from UART0 receive buffer

  if(temp == trig)
  {
    get_frame = 1;
  }
  
  if(get_frame)
  {
    if(RX_in < frame)
    {
      RX_array1[RX_in] = temp;
      RX_in++;

      if(RX_in == frame)
      {
        // Delimiters
        RX_array1[RX_in] = '\n';
        RX_array1[RX_in + 1] = '\r';
        log_array1 = 1;
        get_frame = 0;
      }
    }
    else if(RX_in >= frame)
    {
      RX_array2[RX_in - frame] = temp;
      RX_in++;

      if(RX_in == 2*frame)
      {
        // Delimiters
        RX_array2[RX_in - frame] = '\n';
        RX_array2[RX_in + 1 - frame] = '\r';
        log_array2 = 1;
        get_frame = 0;
        RX_in = 0;
      }
    }
  }

  temp = U0IIR; // Have to read this to clear the interrupt

  VICVectAddr = 0;  // Acknowledge interrupt
}

//pushValue is needed for the "sample" function, exact operation not understood
static inline int pushValue(char* q, int ind, int value)
{
  char* p = q + ind;

  if(asc == 'Y') // ASCII
  {
    // itoa returns the number of bytes written excluding
    // trailing '\0', hence the "+ 1"
    return itoa(value, p, 10) + ind + 1;
  }
  else if(asc == 'N') // binary
  {
    p[0] = value >> 8;
    p[1] = value;
    return ind + 2;
  }
  else // invalid
  {
    return ind;
  }
}


//sample is used in the MODE2ISR routine. used to perform ADC operations
static int sample(char* q, int ind, volatile unsigned long* ADxCR,
                  volatile unsigned long* ADxGDR, int mask, char adx_bit)
{
  if(adx_bit == 'Y')
  {
    int value = 0;

    *ADxCR = 0x00020FF00 | mask;
    *ADxCR |= 0x01000000;  // start conversion
    while((value & 0x80000000) == 0)
    {
      value = *ADxGDR;
    }
    *ADxCR = 0x00000000;

    // The upper ten of the lower sixteen bits of 'value' are the
    // result. The result itself is unsigned. Hence a cast to
    // 'unsigned short' yields the result with six bits of
    // noise. Those are removed by the following shift operation.
    return pushValue(q, ind, (unsigned short)value >> 6);
  }
  else
  {
    return ind;
  }
}

/*******************************************************************************
*	Function: 		MODE2ISR();
*
*	Description: 	MODE2ISR is the routine that runs every time the timer
*					interrupt for the ADC triggers. This function is designed
*					to collect data from analog channels at the user specified
*					data rate.
*				
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

static void MODE2ISR(void)
{
  int ind = 0;
  int j;
  char q[50];


  T0IR = 1; // reset TMR0 interrupt
  
  for(j = 0; j < 50; j++)
  {
    q[j] = 0;
  }


#define SAMPLE(X, BIT) ind = sample(q, ind, &AD##X##CR, &AD##X##GDR, 1 << BIT, ad##X##_##BIT)
  SAMPLE(1, 3);
  SAMPLE(0, 3);
  SAMPLE(0, 2);
  SAMPLE(0, 1);
  SAMPLE(1, 2);
  SAMPLE(0, 4);
  SAMPLE(1, 7);
  SAMPLE(1, 6);
#undef SAMPLE
  
  for(j = 0; j < ind; j++)
  {
    if(RX_in < BUF_SIZE)
    {
      RX_array1[RX_in] = q[j];
      RX_in++;

      if(RX_in == BUF_SIZE) log_array1 = 1;
    }
    else if(RX_in >= BUF_SIZE)
    {
      RX_array2[RX_in - BUF_SIZE] = q[j];
      RX_in++;

      if(RX_in == 2 * BUF_SIZE)
      {
        log_array2 = 1;
        RX_in = 0;
      }
    }
  }
  if(RX_in < BUF_SIZE)
  {
    if(asc == 'N') { RX_array1[RX_in] = '$'; }
    else if(asc == 'Y'){ RX_array1[RX_in] = 13; }
    RX_in++;

    if(RX_in == BUF_SIZE) log_array1 = 1;
  }
  else if(RX_in >= BUF_SIZE)
  {
    
    if(asc == 'N') RX_array2[RX_in - BUF_SIZE] = '$';
    else if(asc == 'Y'){ RX_array2[RX_in - BUF_SIZE] = 13; }
    RX_in++;
    
    if(RX_in == 2 * BUF_SIZE)
    {
      log_array2 = 1;
      RX_in = 0;
    }
  }
  if(RX_in < BUF_SIZE)
  {
    if(asc == 'N') RX_array1[RX_in] = '$';
    else if(asc == 'Y'){ RX_array1[RX_in] = 10; }
    RX_in++;

    if(RX_in == BUF_SIZE) log_array1 = 1;
  }
  else if(RX_in >= BUF_SIZE)
  {
    
    if(asc == 'N') RX_array2[RX_in - BUF_SIZE] = '$';
    else if(asc == 'Y'){ RX_array2[RX_in - BUF_SIZE] = 10; }
    RX_in++;
    
    if(RX_in == 2 * BUF_SIZE)
    {
      log_array2 = 1;
      RX_in = 0;
    }
  }

  VICVectAddr = 0;  // Acknowledge interrupt
}

//This function is for fast interrupt requests, but is not used in this program
void FIQ_Routine(void)
{
  int j;

  stat(0,ON);
  for(j = 0; j < 5000000; j++); // TODO: Why are we using a blocking delay n ISR
  stat(0,OFF);
  U0RBR;  // Trash oldest byte in UART0 Rx FiFO Why??

  U0IIR;  // Have to read this to clear the interrupt

  // TODO: Should we be acking int here?
}

//This is a software interrupt routine. Not used.
void SWI_Routine(void)
{
  while(1);
}

//Undefined routine. Not used.
void UNDEF_Routine(void)
{
  stat(0,ON);
}

/*******************************************************************************
*	Function: 		setup_uart0(int newbaud, char want_ints)
*
*	Description: 	setup_uart0 is the routine that is called to define the uart0
*					port. Baud rate is established, and interrupts are addressed
*					and enabled. 
*				
*	Inputs:			int newbaud: 	the user defined baud rate
*					char want_ints: desired interrupt priority
*
*	Outputs:		None	
**********************************************************************************/

void setup_uart0(int newbaud, char want_ints)	
{
  baud = newbaud;
  U0LCR = 0x83;   // 8 bits, no parity, 1 stop bit, DLAB = 1
  
  if(baud == 1200)
  {
    U0DLM = 0x0C;
    U0DLL = 0x00;
  }
  else if(baud == 2400)
  {
    U0DLM = 0x06;
    U0DLL = 0x00;
  }
  else if(baud == 4800)
  {
    U0DLM = 0x03;
    U0DLL = 0x00;
  }
  else if(baud == 9600)
  {
    U0DLM = 0x01;
    U0DLL = 0x80;
  }
  else if(baud == 19200)
  {
    U0DLM = 0x00;
    U0DLL = 0xC0;
  }
  else if(baud == 38400)
  {
    U0DLM = 0x00;
    U0DLL = 0x60;
  }
  else if(baud == 57600)
  {
    U0DLM = 0x00;
    U0DLL = 0x40;
  }
  else if(baud == 115200)
  {
    U0DLM = 0x00;
    U0DLL = 0x20;
  }

  U0FCR = 0x01;
  U0LCR = 0x03;   

  if(want_ints == 1)
  {
    enableIRQ();
    VICIntSelect &= ~0x00000040;
    VICIntEnable |= 0x00000040;
    VICVectCntl1 = 0x26;
    VICVectAddr1 = (unsigned int)UART0ISR;
    U0IER = 0x01;
  }
  else if(want_ints == 2)
  {
    enableIRQ();
    VICIntSelect &= ~0x00000040;
    VICIntEnable |= 0x00000040;
    VICVectCntl2 = 0x26;
    VICVectAddr2 = (unsigned int)UART0ISR_2;
    U0IER = 0X01;
  }
  else if(want_ints == 0)
  {
    VICIntEnClr = 0x00000040;
    U0IER = 0x00;
  }
}

/*******************************************************************************
*	Function: 		setup_uart1(int newbaud, char want_ints)
*
*	Description: 	setup_uart1 is the routine that is called to define the uart1
*					port. Baud rate is established, and interrupts are addressed
*					and enabled. 
*							
*	Inputs:			int newbaud: 	the user defined baud rate
*					char want_ints: desired interrupt priority
*
*	Outputs:		None	
**********************************************************************************/

void setup_uart1(int newbaud, char want_ints)
{
  baud = newbaud;
  U1LCR = 0x83;   // 8 bits, no parity, 1 stop bit, DLAB = 1
  
  if(baud == 1200)
  {
    U1DLM = 0x0C;
    U1DLL = 0x00;
  }
  else if(baud == 2400)
  {
    U1DLM = 0x06;
    U1DLL = 0x00;
  }
  else if(baud == 4800)
  {
    U1DLM = 0x03;
    U1DLL = 0x00;
  }
  else if(baud == 9600)
  {
    U1DLM = 0x01;
    U1DLL = 0x80;
  }
  else if(baud == 19200)
  {
    U1DLM = 0x00;
    U1DLL = 0xC0;
  }
  else if(baud == 38400)
  {
    U1DLM = 0x00;
    U1DLL = 0x60;
  }
  else if(baud == 57600)
  {
    U1DLM = 0x00;
    U1DLL = 0x40;
  }
  else if(baud == 115200)
  {
    U1DLM = 0x00;
    U1DLL = 0x20;
  }

  U1FCR = 0x01;
  U1LCR = 0x03;   

  if(want_ints == 3)
  {
    enableIRQ();
    VICIntSelect &= ~0x00000080;
    VICIntEnable |= 0x00000080;
    VICVectCntl3 = 0x27;
    VICVectAddr3 = (unsigned int)UART1ISR;
    U1IER = 0X02;
  }
  else if(want_ints == 0)
  {
    VICIntEnClr = 0x00000080;
    U1IER = 0x00;
  }
}

/*******************************************************************************
*	Function: 		stat(int statnum, int onoff)
*
*	Description: 	stat is the routine that drives the status lights on the
*					Logomatic.
*									
*	Inputs:			int statnum:	desired status light (0 or 1)
*					int onoff: 		status light state (ON or OFF)
*
*	Outputs:		None	
**********************************************************************************/

void stat(int statnum, int onoff)
{
  if(statnum) // Stat 1
  {
    if(onoff){ IOCLR0 = 0x00000800; } // On
    else { IOSET0 = 0x00000800; } // Off
  }
  else // Stat 0 
  {
    if(onoff){ IOCLR0 = 0x00000004; } // On
    else { IOSET0 = 0x00000004; } // Off
  }
}

/*******************************************************************************
*	Function: 		Log_init()
*
*	Description: 	Log_init either creates a _LOGCON.ini file or reads the
*					_LOGCON.ini already on the microSD card inserted in the 
*					Logomatic. Configuration parameters are extracted from the 
*					_LOGCON.ini file.
*							
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void Log_init(void)
{
  int x, mark = 0, ind = 0;
  char temp, temp2 = 0, safety = 0;
//  signed char handle;

  if(root_file_exists("_LOGCON.ini"))
  {
    //rprintf("\n\rFound _LOGCON.ini\n");
    fd = root_open("_LOGCON.ini");
    stringSize = fat_read_file(fd, (unsigned char *)stringBuf, 512);
    stringBuf[stringSize] = '\0';
    fat_close_file(fd);
  }
  else
  {
    //rprintf("Couldn't find _LOGCON.ini, creating...\n");
    fd = root_open_new("_LOGCON.ini");
    if(fd == NULL)
    {
      rprintf("Error creating _LOGCON.ini, locking up...\n\r");
      while(1)
      {
        stat(0,ON);
        delay_ms(50);
        stat(0,OFF);
        stat(1,ON);
        delay_ms(50);
        stat(1,OFF);
      }
    }

    strcpy(stringBuf, "MODE = 0\r\nASCII = N\r\nBaud = 4\r\nFrequency = 100\r\nTrigger Character = $\r\nText Frame = 100\r\nAD1.3 = N\r\nAD0.3 = N\r\nAD0.2 = N\r\nAD0.1 = N\r\nAD1.2 = N\r\nAD0.4 = N\r\nAD1.7 = N\r\nAD1.6 = N\r\nSet RTC = N\r\nDate_Time = 000101_000000\r\nSafety On = Y\r\n");
    stringSize = strlen(stringBuf);
    fat_write_file(fd, (unsigned char*)stringBuf, stringSize);
    sd_raw_sync();
  }

  for(x = 0; x < stringSize; x++)
  {
    temp = stringBuf[x];
    if(temp == 10)
    {
      mark = x;
      ind++;
      if(ind == 1)
      {
        mode = stringBuf[mark-2]-48; // 0 = auto uart, 1 = trigger uart, 2 = adc
        rprintf("mode = %d\n\r",mode);
      }
      else if(ind == 2)
      {
        asc = stringBuf[mark-2]; // default is 'N'
        rprintf("asc = %c\n\r",asc);
      }
      else if(ind == 3)
      {
        if(stringBuf[mark-2] == '1'){ baud = 1200; }
        else if(stringBuf[mark-2] == '2'){ baud = 2400; }
        else if(stringBuf[mark-2] == '3'){ baud = 4800; }
        else if(stringBuf[mark-2] == '4'){ baud = 9600; }
        else if(stringBuf[mark-2] == '5'){ baud = 19200; }
        else if(stringBuf[mark-2] == '6'){ baud = 38400; }
        else if(stringBuf[mark-2] == '7'){ baud = 57600; }
        else if(stringBuf[mark-2] == '8'){ baud = 115200; }

        rprintf("baud = %d\n\r",baud);
      }
      else if(ind == 4)
      {
        freq = (stringBuf[mark-2]-48) + (stringBuf[mark-3]-48) * 10;
        if((stringBuf[mark-4] >= 48) && (stringBuf[mark-4] < 58))
        {
          freq+= (stringBuf[mark-4]-48) * 100;
          if((stringBuf[mark-5] >= 48) && (stringBuf[mark-5] < 58)){ freq += (stringBuf[mark-5]-48)*1000; }
        }
        rprintf("freq = %d\n\r",freq);
      }
      else if(ind == 5)
      {
        trig = stringBuf[mark-2]; // default is $
        
        rprintf("trig = %c\n\r",trig);
      }
      else if(ind == 6)
      {
        frame = (stringBuf[mark-2]-48) + (stringBuf[mark-3]-48) * 10 + (stringBuf[mark-4]-48)*100;
        if(frame > 510){ frame = 510; } // up to 510 characters
        rprintf("frame = %d\n\r",frame);
      }
      else if(ind == 7)
      {
        ad1_3 = stringBuf[mark-2]; // default is 'N'
        if(ad1_3 == 'Y'){ temp2++; }
        rprintf("ad1_3 = %c\n\r",ad1_3);
      }
      else if(ind == 8)
      {
        ad0_3 = stringBuf[mark-2]; // default is 'N'
        if(ad0_3 == 'Y'){ temp2++; }
        rprintf("ad0_3 = %c\n\r",ad0_3);
      }
      else if(ind == 9)
      {
        ad0_2 = stringBuf[mark-2]; // default is 'N'
        if(ad0_2 == 'Y'){ temp2++; }
        rprintf("ad0_2 = %c\n\r",ad0_2);
      }
      else if(ind == 10)
      {
        ad0_1 = stringBuf[mark-2]; // default is 'N'
        if(ad0_1 == 'Y'){ temp2++; }
        rprintf("ad0_1 = %c\n\r",ad0_1);
      }
      else if(ind == 11)
      {
        ad1_2 = stringBuf[mark-2]; // default is 'N'
        if(ad1_2 == 'Y'){ temp2++; }
        rprintf("ad1_2 = %c\n\r",ad1_2);
      }
      else if(ind == 12)
      {
        ad0_4 = stringBuf[mark-2]; // default is 'N'
        if(ad0_4 == 'Y'){ temp2++; }
        rprintf("ad0_4 = %c\n\r",ad0_4);
      }
      else if(ind == 13)
      {
        ad1_7 = stringBuf[mark-2]; // default is 'N'
        if(ad1_7 == 'Y'){ temp2++; }
        rprintf("ad1_7 = %c\n\r",ad1_7);
      }
      else if(ind == 14)
      {
        ad1_6 = stringBuf[mark-2]; // default is 'N'
        if(ad1_6 == 'Y'){ temp2++; }
        rprintf("ad1_6 = %c\n\r",ad1_6);
      }
      else if(ind == 17)
      {
        safety = stringBuf[mark-2]; // default is 'Y'
        rprintf("safety = %c\n\r",safety);
      }
	  else if(ind == 15)
	  {
		rtc_set = stringBuf[mark-2]; // default if 'N'
		rprintf("rtc display = %c\n\r",rtc_set);
	  }
	  else if(ind == 16)
	  {
		second = (stringBuf[mark-2]-48) + (stringBuf[mark-3]-48)*10;
		minute = (stringBuf[mark-4]-48) + (stringBuf[mark-5]-48)*10;
		hour = (stringBuf[mark-6]-48) + (stringBuf[mark-7]-48)*10;
		day = (stringBuf[mark-9]-48) + (stringBuf[mark-10]-48)*10;
		month = (stringBuf[mark-11]-48) + (stringBuf[mark-12]-48)*10;
		year = (stringBuf[mark-13]-48) + (stringBuf[mark-14]-48)*10;
	  }
    }
  }

  if(safety == 'Y')
  {
    if((temp2 ==10) && (freq > 150)){ freq = 150; }
    else if((temp2 == 9) && (freq > 166)){ freq = 166; }
    else if((temp2 == 8) && (freq > 187)){ freq = 187; }
    else if((temp2 == 7) && (freq > 214)){ freq = 214; }
    else if((temp2 == 6) && (freq > 250)){ freq = 250; }
    else if((temp2 == 5) && (freq > 300)){ freq = 300; }
    else if((temp2 == 4) && (freq > 375)){ freq = 375; }
    else if((temp2 == 3) && (freq > 500)){ freq = 500; }
    else if((temp2 == 2) && (freq > 750)){ freq = 750; }
    else if((temp2 == 1) && (freq > 1500)){ freq = 1500; }
    else if((temp2 == 0)){ freq = 100; }
  }
  
  if(safety == 'T'){ test(); }

}

/*******************************************************************************
*	Function: 		mode_0()
*
*	Description: 	mode_0 is the routine that runs if Auto UART (mode 0) 
*					operation is desired by the user. The UART0 port is setup 
*					and the primary data logging routine is entered.
*					
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void mode_0(void) // Auto UART mode
{
  rprintf("MODE 0\n\r");
  setup_uart0(baud,1);
  stringSize = BUF_SIZE;
  mode_action();
}

/*******************************************************************************
*	Function: 		mode_1()
*
*	Description: 	mode_1 is the routine that runs if Triggered UART0 (mode 1) 
*					operation is desired by the user. The UART0 port is setup 
*					and the primary data logging routine is entered.
*							
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void mode_1(void) // Triggered UART Logging
{
  rprintf("MODE 1\n\r");  

  setup_uart0(baud,2);
  stringSize = frame + 2;

  mode_action();
}

/*******************************************************************************
*	Function: 		mode_2()
*
*	Description: 	mode_2 is the routine that runs if ADC Logging (mode 2) 
*					operation is desired by the user. Interrupts are enabled and 
*					rate of interrupts are set. The primary data logging routine
*					is entered once interrupt setup is complete.
*							
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void mode_2(void) // ADC Logging
{
  rprintf("MODE 2\n\r");  
  enableIRQ();
  // Timer0  interrupt is an IRQ interrupt
  VICIntSelect &= ~0x00000010;
  // Enable Timer0 interrupt
  VICIntEnable |= 0x00000010;
  // Use slot 2 for UART0 interrupt
  VICVectCntl2 = 0x24;
  // Set the address of ISR for slot 1
  VICVectAddr2 = (unsigned int)MODE2ISR;

  T0TCR = 0x00000002; // Reset counter and prescaler
  T0MCR = 0x00000003; // On match reset the counter and generate interrupt
  T0MR0 = 58982400 / freq;

  T0PR = 0x00000000;

  T0TCR = 0x00000001; // enable timer

  stringSize = BUF_SIZE;
  mode_action();
}

/*******************************************************************************
*	Function: 		mode_3()
*
*	Description: 	mode_3 is the routine that runs if Auto UART with RTC (mode 3) 
*					operation is desired by the user. The UART0 port is setup 
*					and the primary data logging routine is entered. This mode 
*					should only be run if the user is certain the RTC has been
*					intialized and is set to the desired time.
*							
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void mode_3(void) // UART w/ RTC
{
  rprintf("MODE 3\n\r");
  setup_uart0(baud,1);
  stringSize = BUF_SIZE;
  mode_action();

}

/*******************************************************************************
*	Function: 		mode_4()
*
*	Description: 	mode_4 is the routine that runs if RTC setup (mode 4) 
*					operation is desired by the user. The UART1 port is setup, 
*					the RTC is initialized, the desired time is entered, and 
*					the primary data logging routine is entered.
*						
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void mode_4(void) // Set RTC Time
{
  rprintf("MODE 4\n\r");
  
  setup_uart1(baud,0);
  
  stringSize = BUF_SIZE;

  
  mode_action();

}

/*******************************************************************************
*	Function: 		mode_action()
*
*	Description: 	mode_action is the primary data collect routine. It writes
*					data to the SD card and flashes lights as the data buffers
*					fill up. It also handles data dumping when the reset button
*					is pressed.
*						
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void mode_action(void)
{
  int j;
  int c = 0;
 
  while(1)
  {
	if (mode > 2 )
	{	
		if (u==0)
		{
			delay_ms(1000); //echo DS3234 output every second
			delay_ms(1); 	//terminal would display 00FF00FFFF00 or 00FF00FFFFFF without this additional delay
		
			readTime();
			
			while (rtc_time[c] != '\0')
				{
					U1Write(rtc_time[c]);
					c++;
				}
				c=0; 
			
			U1Write('\n');
			
		}
		
		
	}
	else
	{
		
		if(log_array1 == 1)
		{
		  stat(0,ON);
			
		  if(fat_write_file(handle,(unsigned char *)RX_array1, stringSize) < 0)
		  {
			while(1)
			{
			  stat(0,ON);
			  for(j = 0; j < 500000; j++);
			  stat(0,OFF);
			  stat(1,ON);
			  for(j = 0; j < 500000; j++);
			  stat(1,OFF);
			}
		  }
		  
		  sd_raw_sync();
		  stat(0,OFF);
		  log_array1 = 0;
		}
	
		if(log_array2 == 1)
		{
		  stat(1,ON);
		  
		  if(fat_write_file(handle,(unsigned char *)RX_array2, stringSize) < 0)
		  {
			while(1)
			{
			  stat(0,ON);
			  for(j = 0; j < 500000; j++);
			  stat(0,OFF);
			  stat(1,ON);
			  for(j = 0; j < 500000; j++);
			  stat(1,OFF);
			}
		  }
		  
		  sd_raw_sync();
		  stat(1,OFF);
		  log_array2 = 0;
		}
	
		if((IOPIN0 & 0x00000008) == 0) // if button pushed, log file & quit
		{
		  VICIntEnClr = 0xFFFFFFFF;
	
		  if(RX_in < BUF_SIZE)
		  {
			fat_write_file(handle, (unsigned char *)RX_array1, RX_in);
			sd_raw_sync();
		  }
		  else if(RX_in >= BUF_SIZE)
		  {
			fat_write_file(handle, (unsigned char *)RX_array2, RX_in - BUF_SIZE);
			sd_raw_sync();
		  }
		  while(1)
		  {
			stat(0,ON);
			for(j = 0; j < 500000; j++);
			stat(0,OFF);
			stat(1,ON);
			for(j = 0; j < 500000; j++);
			stat(1,OFF);
		  }
		}
	}	
  }
}


/*******************************************************************************
*	Function: 		test()
*
*	Description: 	test is the routine that runs if the system is in test mode. 
*					Users can watch the ADC lines change slowly over UART0 at
*					a rate of 9600 baud.
*					
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void test(void)
{

  rprintf("\n\rLogomatic V2 Test Code:\n\r");
  rprintf("ADC Test will begin in 5 seconds, hit stop button to terminate the test.\r\n\n");

  delay_ms(5000);

  while((IOPIN0 & 0x00000008) == 0x00000008)
  {
    // Get AD1.3
    AD1CR = 0x0020FF08;
    AD_conversion(1);

    // Get AD0.3
    AD0CR = 0x0020FF08;
    AD_conversion(0);
    
    // Get AD0.2
    AD0CR = 0x0020FF04;
    AD_conversion(0);

    // Get AD0.1
    AD0CR = 0x0020FF02;
    AD_conversion(0);

    // Get AD1.2
    AD1CR = 0x0020FF04;
    AD_conversion(1);
    
    // Get AD0.4
    AD0CR = 0x0020FF10;
    AD_conversion(0);

    // Get AD1.7
    AD1CR = 0x0020FF80;
    AD_conversion(1);

    // Get AD1.6
    AD1CR = 0x0020FF40;
    AD_conversion(1);

    delay_ms(1000);
    rprintf("\n\r");
  }

  rprintf("\n\rTest complete, locking up...\n\r");
  while(1);
    
}

/*******************************************************************************
*	Function: 		AD_conversion(int regbank)
*
*	Description: 	AD_conversion is the routine that digitizes analog data in
*					in the register "regbank".
*					
*	Inputs:			int regbank: register user wants to digitize data from
*
*	Outputs:		None	
**********************************************************************************/

void AD_conversion(int regbank)
{
  int temp = 0, temp2;

  if(!regbank) // bank 0
  {
    AD0CR |= 0x01000000; // start conversion
    while((temp & 0x80000000) == 0)
    {
      temp = AD0GDR;
    }
    temp &= 0x0000FFC0;
    temp2 = temp / 0x00000040;

    AD0CR = 0x00000000;
  }
  else      // bank 1
  {
    AD1CR |= 0x01000000; // start conversion
    while((temp & 0x80000000) == 0)
    {
      temp = AD1GDR;
    }
    temp &= 0x0000FFC0;
    temp2 = temp / 0x00000040;

    AD1CR = 0x00000000;
  }

  rprintf("%d", temp2);
  rprintf("   ");
  
}

/*******************************************************************************
*	Function: 		fat_initialize()
*
*	Description: 	fat_initialize checks to see if the SD card was properly 
*					initialized, and if the root directory on the SD card is 
*					accessible.
*					
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void fat_initialize(void)
{
  if(!sd_raw_init())
  {
    rprintf("SD Init Error\n\r");
    while(1);
  }

  if(openroot())
  { 
    rprintf("SD OpenRoot Error\n\r");
  }
}

/*******************************************************************************
*	Function: 		setTime(int d, int mo, int y, int h, int mi, int s)
*
*	Description: 	setTime is the routine that sets the time in the RTC.
*					
*	Inputs:			int d:  day value to be set
*					int mo: month value to be set
*					int y:	 year value to be set
*					int h: hour value to be set
*					int mi: minute value to be set
*					int s:	 seconds value to be set
*
*	Outputs:		None	
**********************************************************************************/

void setTime(uint8_t d, uint8_t mo, uint8_t y, uint8_t h, uint8_t mi, uint8_t s)
{
	uint8_t TimeDate [6]={s,mi,h,d,mo,y};
	int v[6] = {0,1,2,4,5,6};
	
	for(int i=0; i<6;i++){
		select_ssp();
		
		SPI1Send(v[i]+0x80);
		SPI1Receive();
		SPI1Send(TimeDate[i]);
		SPI1Receive();

		delay_ms(5);
		unselect_ssp();
	}
	
}
/*******************************************************************************
*	Function: 		readTime();
*
*	Description: 	readTime() uses spi communication to receive date information
*					from the DS3234. 
*					The values of the DS3234 reads are. After the last read has been completed, the 
*					values are placed into a (uint8_t) array called rtc_time.
*					
*				
*				
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/
void readTime(void)
{
	int i = 0;
	uint8_t dummy;
	
	uint8_t ss = 0;
	uint8_t mm = 0;
	uint8_t hh = 0;
	uint8_t dd = 0;
	uint8_t mo = 0;
	uint8_t yy = 0;

	int order[6] = {5,4,2,1,0,6};  //displays DS3234 time as YYMMDDhhmmss, may not be ncessary
	
	
	for (i=0; i<6; i++)
	{

		select_ssp();
		
		SPI1Send(order[i]+0x00);
		SPI1Receive();
		SPI1Send(order[i]+0x00);
		dummy = SPI1Receive();
		
		if (i == 0) {mo = dummy;}
		else if (i == 1) {dd = dummy;}
		else if (i==2) {hh = dummy;}
		else if (i==3) {mm = dummy;}
		else if (i==4) {ss = dummy;}
		else if (i==5) {yy = dummy;}

		
		delay_ms(10);					//needed to properly read DS3234 time...not sure why
		unselect_ssp();
	}
	
	string_printf((char *)rtc_time,"%02x%02x%02x%02x%02x%02x",mo,dd,hh,mm,ss,yy); //sets time as YYMMDDhhmmss

}

/*******************************************************************************
*	Function: 		RTC_Init()
*
*	Description: 	RTC_Init initializes the RTC.
*					
*	Inputs:			None
*
*	Outputs:		None	
**********************************************************************************/

void RTC_Init(void)
{ 
	  //set control register 
	  select_ssp();
  
	  SPI1Send(0x8E);
	  SPI1Receive();
	  SPI1Send(0x60); //60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled
	  SPI1Receive();
	  delay_ms(10);		//needed to properly read DS3234 time...not sure why
	  unselect_ssp();
	  
	  //delay_ms(10);
}

/*******************************************************************************
*	Function: 		U1Read()
*
*	Description: 	U1Read reads a byte of data from UART1 port.
*					
*	Inputs:			None
*
*	Outputs:		char (1 byte of data)	
**********************************************************************************/

char U1Read(void)
{
	while( !(U1LSR & RDR)); // wait for data to arrive in FIFO
	return U1RBR;
}

/*******************************************************************************
*	Function: 		U1Write(char data)
*
*	Description: 	U1Write writes a byte of data over UART1 port.
*					
*	Inputs:			char data: data to be send over UART1 port
*
*	Outputs:		None	
**********************************************************************************/

void U1Write(char data)
{
	while (!(U1LSR & THRE)); // wait for THR to be emtpy
	
	U1THR = data;
}

/*******************************************************************************
*	Function: 		modulo(int num, int div)
*
*	Description: 	modulo returns the remainder of the quotient num / div
*					
*	Inputs:			int num:	numerator
*					int div:	denominator
*
*	Outputs:		int (the remiainder)	
**********************************************************************************/

int modulo(int num, int div)
{
	while (num >= div) num -= div;
	
	return num;
}

uint8_t uint2bcd(uint8_t ival)
{
	return ((ival/10)<<4) | (modulo(ival,10));
}