SparkFun Forums 

Where electronics enthusiasts find answers.

Everything ARM and LPC
By fsalas10
#183703
Hello all,

I have posted here a few times about my problems with the logomatic. Anyways, I am trying to obviously log data, but first I want to logomatic to respond to specific characters sent over serial. I want it to receive some characters, let's say $$ for example, and then respond with, let's say #1 for example. All it does is echo back what is sent. Here is the main.c code. Pay attention to the initialize function with rprintf_devopen. I think that this is where I need to focus. I did find another thread where a guy was trying to transmit. He said that he figured it out, but his suggestion did not work for me.
Code: Select all
/*********************************************************************************
 * Logomatic V2 Firmware
 * Sparkfun Electronics 2008
 * ******************************************************************************/

 //Notice the comments in the UART0ISR_2 and mode_action functions


/*******************************************************
 * 		     Header Files
 ******************************************************/
 
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "LPC21xx.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"


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

#define ON	1
#define OFF	0

char RX_array1[512];
char RX_array2[512];
char TX_array1[3] = "DL1";
char query1 [3] = "ID?";
char query2 [7] = "protov?";
char stop [2] = "$$";       //I created this array in case we wanted something to stop logging, the '$$' characters are completely 
                             //arbitrary and only put there to ensure that the stop mechanism works
int trig = 13;
char log_array1 = 0;
char log_array2 = 0;
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
short RX_in = 0;
int flag1 = 0;
int flag2 = 0;
int flagstop = 0;

unsigned char flag = 0;

signed int stringSize;
struct fat_file_struct* handle;
struct fat_file_struct * fd;
char stringBuf[256];

// Default Settings
static char mode = 1;
static char asc = 'Y';
static int baud = 9600;

/*******************************************************
 * 		 Function Declarations
 ******************************************************/
//void power_down(void);

void set_time(void);

void Initialize(void);

void setup_uart0(int newbaud, char want_ints);

void mode_0(void);
void mode_1(void);
void mode_2(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);

static void IRQ_Routine(void) __attribute__ ((interrupt("IRQ")));
static void UART0ISR(void); //__attribute__ ((interrupt("IRQ")));
static void UART0ISR_2(void); //__attribute__ ((interrupt("IRQ")));

void rtc_int(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);

void delay_ms(int count);


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

int main (void)
{
	int i;
	//power_down();
	set_time ();
	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();
	sd_raw_sync();		
	if(mode == 0){ mode_0(); }
	else if(mode == 1){ mode_1(); }

    return 0;
}


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

#define PLOCK 0x400

/*Function for setting the date and time*/
void set_time(void)
{
	PCONP |= (1<<9); //Ensure RTC is powered
	CCR = 0x13; //Turn off RTC
	YEAR = 2015;
	MONTH = 07;
	DOM = 27; //Day of Month
	HOUR = 23;
	MIN = 59;
	SEC = 0;
	CCR = 0x11; //Turn RTC back on
}

void Initialize(void)
{
	rprintf_devopen(putc_serial0);//This function can be found in rprintf.c in 'GitHub\Logomatic\Firmware\lib'. I cannot understand it, but it
	                                 //is important and may hold the key to transmitting characters.
	
	PINSEL0 = 0xCF351505;
	PINSEL1 = 0x15441801;
	IODIR0 |= 0x00000884;
	IOSET0 = 0x00000080;

	S0SPCR = 0x08;  // SPI clk to be pclk/8
	S0SPCR = 0x30;  // master, msb, first clk edge, active high, no ints

}

void feed(void)
{
	PLLFEED=0xAA;
	PLLFEED=0x55;
}

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

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

		if(RX_in == 1024)
		{
			log_array2 = 1;
			RX_in = 0;
		}
	}

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

/*This function was changed a lot from the original Github version
  This function describes a mode that requires a trigger character to log data.
  Data will be stored in a temporary register until the trigger is seen, at 
  that point, the data will be logged to the sd-card*/
static void UART0ISR_2(void)
{
	char temp;
	trig = 13; //This is where you set the trigger character in decimal, in this case a carriage return.
	temp = U0RBR; //U0RBR is the receive buffer on the chip, refer to datasheet.

	if(temp == query1[counter1]) //This segment looks for the characters "ID?" from the U0RBR
	{                             //query1 is defined at the top of the program
		counter1++;
		if(counter1 >= 3)
		{
			flag1 = 1;           //This keeps track of whether or not query1 was found
			counter1 = 0;
			
			stat(1,ON);
			delay_ms(50);
			stat(1,OFF);
			
			RX_in = 0;
			temp = 0;
			putc_serial1(49); //This function is in the following path within the Github folder 'GitHub\Logomatic\Firmware\lib'.
		}                        //It is in the 'serial C file'. I am attempting to transmit a specific character upon receiving
		                         //query1. It is not yet working, but you can notice the 'stat' section refers to the onboard leds
								 //so, the led turns on upon receiving query1, but no transmission. This needs to be worked on
	}
	
	if(temp == query2[counter2] && flag1 == 1) //This segment looks for "protov?" from the U0RBR, but only after query1 has been found
	{
		counter2++;
		if(counter2 >= 7)
		{
			flag2 = 1;             //This keeps track of whether or not query2 was found
			counter2 = 0;
			
			stat(1,ON);
			delay_ms(50);
			stat(1,OFF);
			
			RX_in = 0;
			temp = 0;
			putc_serial1(49);//This function is in the following path within the Github folder 'GitHub\Logomatic\Firmware\lib'.
		}                        //It is in the 'serial C file'. I am attempting to transmit a specific character upon receiving
		                         //query2. It is not yet working, but you can notice the 'stat' section refers to the onboard leds
								 //so, the led turns on upon receiving query2, but no transmission. This needs to be worked on
	}
	
	if(temp == stop[counter3]) //This if segment looks for certain characters in the receive buffer to stop logging
	{
		counter3++;
		if(counter3 >= 2)
		{
			flagstop = 1;       //This flagstop keeps track of whether or not stop was found. When the stop characters are found,
			flag1 = 0;          //the query1 and query2 flags will be reset. So, in order to log again these queries must be sent again
			flag2 = 0;          //this may seem obvious, but deserves mention.
			counter3 = 0;
			
			stat(1,ON);
			delay_ms(500);
			stat(1,OFF);
			
			RX_in = 0;
			temp = 0;
		}
		flagstop = 0;           //Reset the stop flag in order to wait once again for the query 1&2
	}

	if(RX_in == 0)
	{
		memset (RX_array1, 0, 512); // This clears the RX_array to make way for new data
		memset (RX_array2, 0, 512);
	}	
	
	if(RX_in < 512 && flag1 == 1 && flag2 == 1) //We cannot log data until we see both flags 1&2 and after we see these flags,
	{                                             //we must then see the trigger character "carriage return
	    RX_array1[RX_in] = temp;
		RX_in++;
				
		if(temp == trig)
		{
			RX_array1[RX_in] = 10; // delimiters
			log_array1 = 1;
			RX_in = 0;
		}
	}	
	else if(RX_in >= 512 && flag1 == 1 && flag2 == 1) //This else if is here in case the RX_in is greater than 512 because the RX_arrays are defined to
	{                                                   //be of size 512. If this happens we don't want to lose data, so we must put the overflow into another register. 
		RX_array2[RX_in - 512] = temp;
		RX_in++;
		RX_array1[512] = 10; // delimiters
		RX_array1[512 + 1] = 13;
		log_array1 = 1;
		
		if(RX_in == 1024 || temp == trig)
		{
			RX_array2[RX_in - 512] = 10; // delimiters
			log_array2 = 1;
			RX_in = 0;
		}
	}
	
	temp = U0IIR; // have to read this to clear the interrupt

	VICVectAddr = 0;
}

void FIQ_Routine(void)
{
	char a;
	int j;

	stat(0,ON);
	for(j = 0; j < 5000000; j++);
	stat(0,OFF);
	a = U0RBR;
	a = U0IIR;  // have to read this to clear the interrupt
}

void SWI_Routine(void)
{
	while(1);
}

void UNDEF_Routine(void)
{
	stat(0,ON);
}

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;  //DLAB = 0 

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

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
	}
}

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

	if(root_file_exists("LOGCON.txt"))
	{
		//rprintf("\n\rFound LOGcon.txt\n");
		fd = root_open("LOGCON.txt");
		stringSize = fat_read_file(fd, (unsigned char *)stringBuf, 512);
		stringBuf[stringSize] = '\0';
		fat_close_file(fd);
	}
	else
	{
		//rprintf("Couldn't find LOGcon.txt, creating...\n");
		fd = root_open_new("LOGCON.txt");
		if(fd == NULL)
		{
		 	rprintf("Error creating LOGCON.txt, 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 = 1\r\nASCII = Y\r\nBaud = 4\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
				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);
			}
		}
	}
}

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

void mode_1(void)
{
	rprintf("MODE 1\n\r");	
	setup_uart0(baud,2);
	stringSize = 512;
	mode_action();
}

void mode_action(void)
{
	int j;
	char output[1024];
	char name[32];
	
	/*An unsolved issue that I was having is that the first log does not get logged. The time stamp gets created, and the second time stamp is created 
	  where the first log should be and the second log is after the second time stamp. All logs after this are as they should be. 
	  Example:
	  "Time stamp 1:" "Time stamp 2: logged data"
	  "Time stamp 3: logged data"
	  .
	  .
	  .
	  "Time stamp N: logged data"
	  
	  Here is how it should be:
	  "Time stamp 1: logged data" 
	  "Time stamp 2: logged data"
	  "Time stamp 3: logged data"
	  .
	  .
	  .
	  "Time stamp N: logged data"
	  
	  It has something to do with creating a new file, because the appending is working out fine
	*/
	while(1)
	{
		uint32_t ctime0_val = CTIME0;                               
		uint32_t ctime1_val = CTIME1;                               
		unsigned int seconds = (0x0000003f & ctime0_val);         // Bit masking to read the time values from the appropriate
		unsigned int minutes = (0x00003f00 & ctime0_val) >> 8;    // registers, and also placing those values in the correct
		unsigned int hours = (0x001f0000 & ctime0_val) >> 16;     // slot to display a readable time and date
		unsigned int dom = (0x0000001f & ctime1_val);               
		unsigned int month = (0x00000f00 & ctime1_val) >> 8;       
		unsigned int year = (0x0fff0000 & ctime1_val) >> 16; 
		string_printf(name,"%04d-%02d-%02d.txt", YEAR, MONTH, DOM);  //This is the name of the file to be logged with a date stamp, but not a time stamp
		                                                              //The log itself has date and time stamps, so only the date is necessary for a file name
		
		if(!root_file_exists(name))
		{
			handle = root_open_new(name);
			if(log_array1 == 1)
			{
				stringSize = sprintf(output, "%04d-%02d-%02d %02d:%02d:%02d, %s", year, month, dom, hours, minutes, seconds, (unsigned char *)RX_array1);
				stat(0,ON);
				if(fat_write_file(handle, output, 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)
			{
				stringSize = sprintf(output, "%s", (unsigned char *)RX_array2);
				stat(1,ON);
				if(fat_write_file(handle, output, 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;
			}
			fat_close_file(handle);
		}
		else 
		{
			handle = root_open_append(name); //In order to append, I created the struct on line 2576 in the fat.c file that can be found in GitHub\Logomatic\Firmware\lib
			if(log_array1 == 1)              //My motivation for doing this can be found at this address https://forum.sparkfun.com/viewtopic.php?f=11&t=15890
			{
				stringSize = sprintf(output, "%04d-%02d-%02d %02d:%02d:%02d, %s", year, month, dom, hours, minutes, seconds, (unsigned char *)RX_array1);
				stat(0,ON);
				if(fat_write_file(handle, output, 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)
			{
				stringSize = sprintf(output, "%s",(unsigned char *)RX_array2);
				stat(1,ON);
				if(fat_write_file(handle, output, 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;
			}
			fat_close_file(handle);
		}
		
	}
}

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

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

void delay_ms(int count)
{
	int i;
	count *= 10000;
	for(i = 0; i < count; i++)
		asm volatile ("nop");
}
Now, below is the code where the rprintf_devopen comes from. I honestly do not understand this function
Code: Select all
//#########################################################################
// printf.c
//
// *** printf() based on sprintf() from gcctest9.c Volker Oth
//
// *** Changes made by Holger Klabunde
// Now takes format strings from FLASH (was into RAM ! before)
// Fixed bug for %i, %I. u_val was used before it had the right value
// Added %d, %D (is same as %i, %I)
// Support for long variables %li, %ld, %Lu, %LX ....
// %x, %X now gives upper case hex characters A,B,C,D,E,F
// Output can be redirected in a single function: myputchar()
// Make printf() smaller by commenting out a few #defines
// Added some SPACE and ZERO padding %02x or % 3u up to 9 characters
//
// Todo:
// %f, %F for floating point numbers
//
// *** Changes made by Martin Thomas for the efsl debug output:
// - removed AVR "progmem"
// - added function pointer for "putchar"
// - devopen function
//
//#########################################################################

#include <stdarg.h>
#include <string.h>
#include "rprintf.h"
//#include "system.h" //Needed for delay_ms

#define SCRATCH 12  //32Bits go up to 4GB + 1 Byte for \0

//Spare some program space by making a comment of all not used format flag lines
#define USE_LONG    // %lx, %Lu and so on, else only 16 bit integer is allowed
//#define USE_OCTAL // %o, %O Octal output. Who needs this ?
#define USE_STRING      // %s, %S Strings as parameters
#define USE_CHAR    // %c, %C Chars as parameters
#define USE_INTEGER // %i, %I Remove this format flag. %d, %D does the same
#define USE_HEX     // %x, %X Hexadezimal output
#define USE_UPPERHEX    // %x, %X outputs A,B,C... else a,b,c...
#ifndef USE_HEX
    #undef USE_UPPERHEX    // ;)
#endif
#define USE_UPPER   // uncommenting this removes %C,%D,%I,%O,%S,%U,%X and %L..
// only lowercase format flags are used
#define PADDING         //SPACE and ZERO padding


static int (*putcharfunc)(int c);

void rprintf_devopen( int(*put)(int) )
{
    putcharfunc = put;
}

static void myputchar(unsigned char c)
{
    if(c == '\n') putcharfunc('\r');
    putcharfunc(c);
}

void rprintf(char const *format, ...)
{
    unsigned char scratch[SCRATCH];
    unsigned char format_flag;
    unsigned short base;
    unsigned char *ptr;
    unsigned char issigned=0;
    va_list ap;

    #ifdef USE_LONG
        // #warning "use long"
        unsigned char islong=0;
        unsigned long u_val=0;
        long s_val=0;
    #else
        unsigned int u_val=0;
        int s_val=0;
    #endif

    unsigned char fill;
    unsigned char width;

    va_start (ap, format);
    for (;;)
    {
		delay_ms(1); //Added for VCOM testing - without it, rprintf will overrun the VCOM buffer causing it to crash
		
        while ((format_flag = *(format++)) != '%')
        {      // Until '%' or '\0'
            if (!format_flag){va_end (ap); return;}
                myputchar(format_flag);
        }

        issigned=0; //default unsigned
        base = 10;

        format_flag = *format++; //get char after '%'

        #ifdef PADDING
            width=0; //no formatting
            fill=0;  //no formatting
            if(format_flag=='0' || format_flag==' ') //SPACE or ZERO padding  ?
            {
                fill=format_flag;
                format_flag = *format++; //get char after padding char
                if(format_flag>='0' && format_flag<='9')
                {
                    width=format_flag-'0';
                    format_flag = *format++; //get char after width char
                }
            }
        #endif

        #ifdef USE_LONG
            islong=0; //default int value
            #ifdef USE_UPPER
            if(format_flag=='l' || format_flag=='L') //Long value
            #else
            if(format_flag=='l') //Long value
            #endif
        {
            islong=1;
            format_flag = *format++; //get char after 'l' or 'L'
        }
        #endif

        switch (format_flag)
        {
            #ifdef USE_CHAR
                case 'c':
                    #ifdef USE_UPPER
                    case 'C':
                #endif
                format_flag = va_arg(ap,int);
                // no break -> run into default
            #endif

            default:
                myputchar(format_flag);
                continue;

                #ifdef USE_STRING
                    #ifdef USE_UPPER
                    case 'S':
                #endif
                case 's':
                ptr = (unsigned char*)va_arg(ap,char *);
                while(*ptr) { myputchar(*ptr); ptr++; }
                    continue;
                #endif

                #ifdef USE_OCTAL
                    case 'o':
                    #ifdef USE_UPPER
                    case 'O':
                #endif
                base = 8;
                myputchar('0');
                goto CONVERSION_LOOP;
                #endif

                #ifdef USE_INTEGER //don't use %i, is same as %d
                    case 'i':
                    #ifdef USE_UPPER
                    case 'I':
                #endif
                #endif
                case 'd':
                #ifdef USE_UPPER
                    case 'D':
                #endif
                issigned=1;
                // no break -> run into next case
            case 'u':
                #ifdef USE_UPPER
                    case 'U':
                #endif

                //don't insert some case below this if USE_HEX is undefined !
                //or put       goto CONVERSION_LOOP;  before next case.
                #ifdef USE_HEX
                    goto CONVERSION_LOOP;
                    case 'x':
                    #ifdef USE_UPPER
                    case 'X':
                #endif
                base = 16;
                #endif

                CONVERSION_LOOP:

                if(issigned) //Signed types
                {
                    #ifdef USE_LONG
                        if(islong) { s_val = va_arg(ap,long); }
                            else { s_val = va_arg(ap,int); }
                        #else
                        s_val = va_arg(ap,int);
                    #endif

                    if(s_val < 0) //Value negativ ?
                    {
                        s_val = - s_val; //Make it positiv
                        myputchar('-');    //Output sign
                    }

                    u_val = (unsigned long)s_val;
                }
                else //Unsigned types
                {
                    #ifdef USE_LONG
                        if(islong) { u_val = va_arg(ap,unsigned long); }
                            else { u_val = va_arg(ap,unsigned int); }
                        #else
                        u_val = va_arg(ap,unsigned int);
                    #endif
                }

                ptr = scratch + SCRATCH;
                *--ptr = 0;
                do
                {
                    char ch = u_val % base + '0';
                    #ifdef USE_HEX
                        if (ch > '9')
                        {
                            ch += 'a' - '9' - 1;
                            #ifdef USE_UPPERHEX
                            ch-=0x20;
                        #endif
                    }
                    #endif
                    *--ptr = ch;
                    u_val /= base;

                    #ifdef PADDING
                        if(width) width--; //calculate number of padding chars
                    #endif
                }
                while (u_val);

                #ifdef PADDING
                    while(width--) *--ptr = fill; //insert padding chars
                #endif

                while(*ptr) { myputchar(*ptr); ptr++; }
                    }
        }
    }
Finally here is the code with the putchar functions.
Code: Select all
/******************************************************************************/
/*  This file is part of the uVision/ARM development tools                    */
/*  Copyright KEIL ELEKTRONIK GmbH 2002-2004                                  */
/******************************************************************************/
/*                                                                            */
/*  SERIAL.C:  Low Level Serial Routines                                      */
/*  modified and extended by Martin Thomas                                    */
/*                                                                            */
/******************************************************************************/

#include "LPC214x.h"
#include "target.h"
#include "serial.h"

#define CR     0x0D

/* Initialize Serial Interface UART0 */
void init_serial0 ( unsigned long baudrate )
{
    unsigned long Fdiv;

    PINSEL0 = 0x00000005;                  /* Enable RxD0 and TxD0              */
    U0LCR = 0x83;                          /* 8 bits, no Parity, 1 Stop bit     */
    Fdiv = ( Fcclk / 16 ) / baudrate ;     /* baud rate                        */
    U0DLM = Fdiv / 256;
    U0DLL = Fdiv % 256;
    U0LCR = 0x03;                           /* DLAB = 0                         */
}

/* Initialize Serial Interface UART0 */
void init_serial1 ( unsigned long baudrate )
{
    unsigned long Fdiv;

    PINSEL0 |= (1<<16) | (1<<18);         /* Enable RxD1 and TxD1              */
    U1LCR = 0x83;                          /* 8 bits, no Parity, 1 Stop bit     */
    Fdiv = ( Fcclk / 16 ) / baudrate ;     /* baud rate                        */
    U1DLM = Fdiv / 256;
    U1DLL = Fdiv % 256;
    U1LCR = 0x03;                           /* DLAB = 0                         */
}

// Write character to Serial Port 0 with \n -> \r\n  
int putchar_serial0 (int ch)
{
    if (ch == '\n')
    {
        while (!(U0LSR & 0x20));
        U0THR = CR;                  // output CR 
    }
    while (!(U0LSR & 0x20));
    return (U0THR = ch);
}

// Write character to Serial Port 0 without \n -> \r\n  
int putc_serial0 (int ch)
{
    while (!(U0LSR & 0x20));
    return (U0THR = ch);
}

// Write character to Serial Port 1 without \n -> \r\n  
int putc_serial1 (int ch)
{
    while (!(U1LSR & 0x20));
    return (U1THR = ch);
}

void putstring_serial0 (const char *string)
{
    char ch;

    while ((ch = *string))
    {
        putchar_serial0(ch);
        string++;
    }
}


// Read character from Serial Port   
int getkey_serial0 (void)
{
	if (U0LSR & 0x01)
    {
        return (U0RBR);
    }
    else
    {
        return 0;
    }
}

// Read character from Serial Port   
int getc0 (void)
{
	while ( (U0LSR & 0x01) == 0 ); //Wait for character
	return U0RBR;
}
Now, keep in mind that my programming skills are mediocre at best. Before attempting this project I took a C class for non computer science majors. I have learned a ton trying to tackle this code, but this problem has plagued me for some time now. Any help would be much appreciated.