Monday, 11 August 2014

Creating a 5 bit successive approximation (sar) ADC using the LPC810's Comparator

The only analog peripheral the LPC810 has it the analog comparator which can compare various external and internal voltages. The analogs pin are fixed pins in the LPC800 series of micro-controllers and exist on the same pins as PIO0_0 and PIO0_1


 In this example we are going to use the PIO0_1 pin which is ACMP_I2


and we have the potentiometer connected to PIO0_1.A word of warning, be careful not to have the POT turned to ground when you try to restart the LPC810 after programming or the LPC810 will boot into ISP mode again.

The steps in setting up the comparator is similar to the other peripherals, first we must turn on the clock to the comparator then select it in the switch matrix. We also need to power up the comparator like so:

LPC_SYSCON->PDRUNCFG &= ~(( 1  <<  15 )); // power up ACMP

Again replace the main.c in from the previous project with the one below :-


#include "LPC8xx.h"

#define BAUDRATE 57600
#define UART_CFG_DATALEN_8      (0x01 << 2)  /* UART 8 bit length mode */
#define UART_CFG_PARITY_NONE    (0x00 << 4)  /* No parity */
#define UART_CFG_STOPLEN_1      (0x00 << 6)  /* UART One Stop Bit Select */
#define UART_STAT_RXRDY         (0x01 << 0)  /* Receiver ready */
#define UART_STAT_TXRDY         (0x01 << 2)  /* Transmitter ready for data */
#define UART_CFG_ENABLE         (0x01 << 0)

uint32_t SystemCoreClock = 12000000; /* Value @ Reset */
uint32_t SystemMainClock = 12000000; /* Value @ Reset */

#define halt_clk(c) LPC_MRT->Channel[3].INTVAL = (c-3)

int uart0PollChar() {
 if (!(LPC_USART0->STAT & UART_STAT_RXRDY))
  return -1;
 return LPC_USART0->RXDATA;
}
void uart0putc(unsigned char c) {
 /* Wait until we're ready to send */
 while (!(LPC_USART0->STAT & UART_STAT_TXRDY))
  ;
 LPC_USART0->TXDATA = c;
}

void uart0puti(unsigned int n) {
 unsigned int rem = n % 10;
 unsigned int quot = n / 10;
 if (quot > 0)
  uart0puti(quot);
 uart0putc(rem + '0');
}

/* Use ACMP_2 as a simple 5 bit SAR adc */
int read_adc2() {
 int min = 0, max = 63, value = 31, count, compstat, laststat;
 LPC_CMP->CTRL = (0x2 << 8) | (0x3 << 25); /* positive input ACMP0_I2 , negative input voltage ladder , 20mV hysteresis */
 while (!((value == min) || (value == max))) {
  count = 0;
  LPC_CMP->LAD = 1 | (value); /* ladder Enable | Vref=Vdd | value */
  halt_clk(12 * 15); /* 15us worst case for ladder to settle */
  laststat = (LPC_CMP->CTRL >> 21) & 1;
  /* wait till reading is the same 3 times in row */
  do {
   halt_clk(6); /* wait 0.5us */
   compstat = (LPC_CMP->CTRL >> 21) & 1;
   if (compstat == laststat)
    count++;
   else
    count = 0;
   laststat = compstat;
  } while (count < 3);
  /* Binary divide */
  if (compstat) {
   min = value;
   value = value + ((max - value) >> 1);
  } else {
   max = value;
   value = value - ((value - min) >> 1);
  }
 }
 return value >> 1;
}

int main(void) {
 /* Enable AHB clock to the Switch Matrix , UART0 , GPIO , IOCON, MRT , ACMP */
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7) | (1 << 14) /*| (1 << 6)*//* | (1 << 18)*/
   | (1 << 10) | (1 << 19);

 /* Configure Switch Matrix so that Pin2 = U0_TXD and Pin8 = U0_RXD */
 LPC_SWM->PINASSIGN0 = 0xffff0004UL;

 /* On reset pio_2(swdio), pio_3(swclk) , pio_5(reset) are selected as fixed function.
  * We disable all fixed functions here so they will become GPIO unless a movable function
  * has been assigned in the switch matrix by the line above */
 LPC_SWM->PINENABLE0 = 0xffffffffUL & (~0x2); /* Enable fixed function ACMP_I2. This function is enabled on pin PIO0_1 */

 /* Set the UART clock divisor to 1  */
 LPC_SYSCON->UARTCLKDIV = 1; // note on reset the value is 0. i.e clock is disabled
 /* Configure UART0 baud rate */
 LPC_USART0->BRG = ((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4)
   / BAUDRATE - 1;
 LPC_SYSCON->UARTFRGMULT =
   ((((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4) * (0x100))
     / (BAUDRATE * (LPC_USART0->BRG + 1))) - (0x100);
 LPC_SYSCON->UARTFRGDIV = 0xFF; //note on reset the value is 0

 /* Set UART0 to 8N1 and finally enable */
 LPC_USART0->CFG = UART_CFG_DATALEN_8 | UART_CFG_PARITY_NONE
   | UART_CFG_STOPLEN_1 | UART_CFG_ENABLE;

 LPC_MRT->Channel[3].CTRL = (0x02 << 1); /* MRT3 (halt_clk) bus stall mode , no interrupts */

 /* Initialise the comparator ICMP_2 */
 LPC_SYSCON->PDRUNCFG &= ~((1 << 15)); // power up ACMP

 /* wait for the keypress 'a' */
 while (1) {
  switch (uart0PollChar()) {
  case 'a': {
   int v = read_adc2();
   uart0puti(v);
   uart0putc('\n');
   uart0putc('\r');
  }
   break;
  }
 }
 return 0;
}


The function read_adc2() does most of the work here and implements a simple 5 bit SAR ADC using the programmable voltage divider of the LPC800 series mcu's. It should be noted that theoretically this routine could get into an infinite loop if there was to much noise but it seems to work well for me.


Sunday, 10 August 2014

Control a relay module from a PC via a TTL UART with a LPC810

Previously a simple program was created to read the input from a simple comparator based light sensor, now we focus attention on LPC810 GPIO's again to drive a relay module with some simple UART commands sent from a PC.

The module has a green LED for power and a red LED that lights when the relay is active

Using the LPC810's Physical Pin 4 which is pio_2 to drive the relay.

The relay module was wired up as below:-


These modules appear to be slightly different , the one I purchased from ebay operated on 5v and did not have an opto-isolator and so is only suitable for low voltages (In fact i would be vary careful with any of these cheap non-ce devices  from china with  mains level voltages,  just because the relay may-be rated at 240v does not imply the entire module has been designed for 240v,  if your intent is on controlling mains voltages then get a CE certified one) . The relay's active led was lit when IN1 was logic 0 and was off when IN1 was logic 1.For it to work it required that the GPIO output was driven in open drain mode and the required 5v Vcc was obtained from the 5v pin on the USB TTL UART adapter,

To use the GPIO port to drive the relay module he following needs to be done:

  1. Enable the Clock to the GPIO and IOCON with LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 6) | (1 << 18 )
  2. Reset all Fixed pins with LPC_SWM->PINENABLE0 = 0xffffffffUL;
  3. Put the GPIO in open drain mode and disable the internal pull up resistor with LPC_IOCON->PIO0_2 = (1 << 10) ;
  4. Set the PIO_2 direction to output with LPC_GPIO_PORT->DIR0 |= (1 << 2);

The GPIO port can be set or reset by putting a 1 or 0 in

 LPC_GPIO_PORT->B0[2]

when the index , two in this case is the index of the GPIO.


#include "LPC8xx.h"

#define BAUDRATE 57600
#define UART_CFG_DATALEN_8      (0x01 << 2)  /* UART 8 bit length mode */
#define UART_CFG_PARITY_NONE    (0x00 << 4)  /* No parity */
#define UART_CFG_STOPLEN_1      (0x00 << 6)  /* UART One Stop Bit Select */
#define UART_STAT_RXRDY         (0x01 << 0)  /* Receiver ready */
#define UART_STAT_TXRDY         (0x01 << 2)  /* Transmitter ready for data */
#define UART_CFG_ENABLE         (0x01 << 0)

uint32_t SystemCoreClock = 12000000; /* Value @ Reset */
uint32_t SystemMainClock = 12000000; /* Value @ Reset */

int uart0PollChar() {
 if (!(LPC_USART0->STAT & UART_STAT_RXRDY))
  return -1;
 return LPC_USART0->RXDATA;
}
void uart0putc(unsigned char c) {
 /* Wait until we're ready to send */
 while (!(LPC_USART0->STAT & UART_STAT_TXRDY));
 LPC_USART0->TXDATA = c;
}
int main(void) {
 /* Enable AHB clock to the Switch Matrix , UART0 , GPIO , IOCON*/
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7) | (1 << 14) | (1 << 6) | (1 << 18 );

 /* Configure Switch Matrix so that Pin2 = U0_TXD and Pin8 = U0_RXD */
 LPC_SWM->PINASSIGN0 = 0xffff0004UL;

 /* On reset pio_2(swdio), pio_3(swclk) , pio_5(reset) are selected as fixed function.
  * We disable all fixed functions here so they will become GPIO unless a movable function
  * has been assigned in the switch matrix by the line above */
 LPC_SWM->PINENABLE0 = 0xffffffffUL;

 /* Physical Pin 4 (pio_2) is configured as output */
 LPC_GPIO_PORT->DIR0 |= (1 << 2);

 /* pio_2 is set to open drain mode and it's pull up resistor disabled */
 LPC_IOCON->PIO0_2 = (1 << 10)  ;

 /* Set the UART clock divisor to 1  */
 LPC_SYSCON->UARTCLKDIV = 1; // note on reset the value is 0. i.e clock is disabled
 /* Configure UART0 baud rate */
 LPC_USART0->BRG = ((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4)
   / BAUDRATE - 1;
 LPC_SYSCON->UARTFRGMULT =
   ((((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4) * (0x100))
     / (BAUDRATE * (LPC_USART0->BRG + 1))) - (0x100);
 LPC_SYSCON->UARTFRGDIV = 0xFF; //note on reset the value is 0

 /* Set UART0 to 8N1 and finally enable */
 LPC_USART0->CFG = UART_CFG_DATALEN_8 | UART_CFG_PARITY_NONE
   | UART_CFG_STOPLEN_1 | UART_CFG_ENABLE;

 /* Set pio_2 according to which keypress '0' and '1' */
 while (1) {
  switch (uart0PollChar()) {
  case '0':
   LPC_GPIO_PORT->B0[2] = 0;
   uart0putc('0');
   break;
  case '1':
   LPC_GPIO_PORT->B0[2] = 1;
   uart0putc('1');
   break;
  }
 }
 return 0;
}


Interfacing a light sensor module to the LPC810

In the previous posts we looked at what could be done with NXP's LPC810 having only the UART connected. In this post let us connect a simple light sensor module like this one:



Any similar sensor module could be used they are available as magnetic reed switch, IR proximity detector ect. They all work the same way and use the trusty LM393 comparator to provide a on/off value on the data line D0 in this case when the light is above or below a certain threshold that can be adjusted by the potentiometer seen in blue.

It is wired up as so with Pin 3 (pio_3) connected to the DO line of the light sensor module.


We replace the main.c built up in the previous posts with a simplified one which simply outputs are 0 or 1 when the light level goes above or below the required threshold:-



#include "LPC8xx.h"

#define BAUDRATE 57600
#define UART_CFG_DATALEN_8      (0x01 << 2)  /* UART 8 bit length mode */
#define UART_CFG_PARITY_NONE    (0x00 << 4)  /* No parity */
#define UART_CFG_STOPLEN_1      (0x00 << 6)  /* UART One Stop Bit Select */
#define UART_STAT_RXRDY         (0x01 << 0)  /* Receiver ready */
#define UART_STAT_TXRDY         (0x01 << 2)  /* Transmitter ready for data */
#define UART_CFG_ENABLE         (0x01 << 0)

uint32_t SystemCoreClock = 12000000; /* Value @ Reset */
uint32_t SystemMainClock = 12000000; /* Value @ Reset */

void uart0putc(unsigned char c) {
 /* Wait until we're ready to send */
 while (!(LPC_USART0->STAT & UART_STAT_TXRDY));
 LPC_USART0->TXDATA = c;
}

int main(void) {
 /* Enable AHB clock to the Switch Matrix , UART0 , GPIO */
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7) | (1 << 14) | (1 << 6);

 /* Configure Switch Matrix so that Pin2 = U0_TXD and Pin8 = U0_RXD */
 LPC_SWM->PINASSIGN0 = 0xffff0004UL;

 /* Set the UART clock divisor to 1  */
 LPC_SYSCON->UARTCLKDIV = 1; // note on reset the value is 0. i.e clock is disabled
 /* Configure UART0 baud rate */
 LPC_USART0->BRG = ((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4)
   / BAUDRATE - 1;
 LPC_SYSCON->UARTFRGMULT =
   ((((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4) * (0x100))
     / (BAUDRATE * (LPC_USART0->BRG + 1))) - (0x100);
 LPC_SYSCON->UARTFRGDIV = 0xFF; //note on reset the value is 0

 /* Set UART0 to 8N1 and finally enable */
 LPC_USART0->CFG = UART_CFG_DATALEN_8 | UART_CFG_PARITY_NONE
   | UART_CFG_STOPLEN_1 | UART_CFG_ENABLE;

 /* Output changes to pio_03 over the uart as zeros and ones */
 char old_v = -1;
 while (1) {
  char v = LPC_GPIO_PORT->B0[3];
  if (v!=old_v){
   uart0putc(v+'0');
   uart0putc('\n');
   uart0putc('\r');
   old_v = v;
  }
 }
 return 0;
}


We enable the Clock to the GPIO peripheral in SYSAHBCLKCTRL , the GPIO's clock is actually enabled just after reset so this is not strictly necessary but makes the code a clearer at no extra cost.

Also after reset all Pins are set to GPIO and the pin direction is as input so we need to do nothing with the switch matrix or the GPIO direction register to attach a simple sensor.

The GPIO's input pin value is read by the line

char v = LPC_GPIO_PORT->B0[3];

which reads the pin value as a byte value which can be either 0 or 1

Monday, 4 August 2014

Some other uses for the LPC810 Multi Rate Timer (MRT)

In the last post a clock cycle accurate delay which stalled the CPU bus rather than eat up CPU cycles was created using the Multi Rate Timer while in this post we  look at some other simple uses for the remaining 3 channels of the MRT.

A Millisecond delay routine on channel 2, this delay routine will poll the Status register to see if the timer is still running and consume CPU cycles whist running, it will not however block interrupts which is necessary for long delays although a callback timer shown below may be more appropriate in some cases.

/* Delay by a number of milliseconds
 * Note the divide of SystemCoreClock will affect the accuracy
 * The overhead is approximately 286 +/- 10 (varies with the actual divide) clock cycles which is about 24us @ 12MHZ
 * Uses channel 2 of the MRT
 */

void delay_ms(int delay) {
 LPC_MRT->Channel[2].INTVAL = (((SystemCoreClock / 250L) * delay) >> 2)
   - 286 ;
 while (LPC_MRT->Channel[2].STAT & 0x02)
  ; //wait while running
}

It is initilized like so

 LPC_MRT->Channel[2].CTRL = (0x01 << 1); //MRT2 (delay_ms) single shot mode , no interrupts

A Profile timer on channel 1

/* Profiler on MRT Channel 1 */
volatile static uint32_t __profile_clocks;
#define PROFILE_START()  LPC_MRT->Channel[1].INTVAL = 0xffffffff //Force count down from max value
#define PROFILE_STOP()  __profile_clocks = LPC_MRT->Channel[1].TIMER //snatch timer value
#define PROFILE_COUNT()  (0x7fffffffUL - 8 - __profile_clocks )   //Return the number of clock cycles counted
#define PROFILE_PREPARE() (__profile_clocks)// fudge to even init clock cycles



The Profile timer is initilized like so

 LPC_MRT->Channel[1].CTRL = (0x01 << 1); //MRT1 (Profiler) single shot mode , no interrupts

and used like below

PROFILE_PREPARE();
PROFILE_START();
halt_clk(30);
PROFILE_STOP();
xprintf("30 profile clocks are %d\n\r",PROFILE_COUNT());

Finally on channel 0 we have a timer function that will execute a callback function after a specified amount of clock cycles, it can be made to repeat or used as a single shot timer.

/* timer()
 * the timer() function executes callback after clk clock cycles
 * repeat signals if the callback is to be repeated.
 * Uses MRT Channel 0
 */
void (*__callback)(void);

void timer(int clk,void (*callback)(void),bool repeat){
 if (repeat)
  LPC_MRT->Channel[0].CTRL = 0x1 ; /* MRT0 repeat mode , interrupts enabled */
 else
  LPC_MRT->Channel[0].CTRL = (0x01 << 1) | 0x1 ; /* MRT0 single shot mode , interrupts enabled */
 __callback = callback;
 LPC_MRT->Channel[0].INTVAL = clk | (1 << 31);
ISER[0] = (1 << 10); /* enable interrupts */
}
/* MRT_IRQHandler used for timer() function */
void MRT_IRQHandler(void){
 LPC_MRT->Channel[0].STAT = 0x1 ; /* clr interupt request */
 if (__callback)
  __callback();

}



Sunday, 3 August 2014

Microsecond delays using the LPC810's Multi Rate Timer (MRT).

A Situation that occurs frequently is the need to delay the CPU for a specific number of microseconds or clock cycles. An ideal way to do this with the with the Multi Rate Timer of the LPC810 is with a special mode called One-shot bus stall mode.

The Multi Rate Timer comprises of Four individual 31 bit timers capable of generating a repetitive interrupt similar to the SysTick Timer or counting down to zero and generating a single shot interrupt. All the four timers will trigger the same interrupt routine which will need to determine which of the interrupt enabled timers triggered it.

There is however another mode of operation which does not use interrupts and is known as the One-shot bus stall mode. This mode  will instead stall the bus interface of the System Clock for a specified number of clock cycles. This mode effectively stops all CPU activity until the MRT has finished counting down to zero and is ideal for creating a microsecond or fixed cycle delay functions as in the time the MRT is counting down to zero the CPU consumes very little power as opposed to a tradition delay loop or a polled timer delay loop.

We need to write the number of clock cycles to stall the bus to the INTVAL register of the timer, The bus is actually stalled for INTVAL+3 cycles as some time is needed by the MRT to actually stall the bus.

First lets use channel 3 of the MRT and initialize it to bus stall mode somewhere in our main routine.

LPC_MRT->Channel[3].CTRL = (0x02 << 1) ; //MRT3 (halt_clk) bus stall mode , no interrupts

Next lets define a macro that we can use to halt the CPU for a number of clock cycles, This macro works providing that the number of clock cycles is greater that 3.

#define halt_clk(clk) LPC_MRT->Channel[3].INTVAL = (clk-3)

For Instance

halt_clk(120); /* Gives a 10us delay with 12MHZ clock */



Saturday, 2 August 2014

Using the SysTick timer of the LPC810

Every Cortex M0 Mcu such as the LPC810 has a system timer know as the SysTick timer which is a simple 24 bit timer. The SysTick timer is intended to provide a regular interrupt that can be used to update a system tick count, the code below provides a SysTick_Handler which overrides the WEAK reference to SysTick_Handler in cr_startup.c

/* SysTick Handler to be interupted every 1ms */
uint32_t __tick;
void SysTick_Handler(void) {
 __tick++;
}

The following lines of code enable a SysTick interrupt to occur every 1 Millisecond

SysTick->LOAD = (SystemCoreClock / 1000 * 1/*# ms*/) - 1; /* Every 1 ms */
SysTick->VAL = 0;
__tick = 0;
SysTick->CTRL = 0x7; /* d2:ClkSrc=SystemCoreClock, d1:Interrupt=enabled, d0:SysTick=enabled */

We Load the System Timer with the repeat count in the LOAD field then set the initial value to zero in the VAL field rather  than leave it at some random value and also reset the __tick count to zero.
The CTRL field is set to enable Interrupts in bit d1 (Our SysTick_Handler above) and to use the SystemCoreClock rather than SystemCoreClock / 2 by setting bit d2, Then finally setting bit d0 enables the System Timer.

The Internal RC Clock of the LPC810 is specified to be accurate to within 1% which is about 14 Minutes a day or 6 seconds very 10 Minutes. The device I tried appears to be doing slightly better and losing 3 seconds every 10 Minutes.

The updated code for the example is below:


#include "LPC8xx.h"
#include "xprintf.h"

#define BAUDRATE 57600
#define UART_CFG_DATALEN_8      (0x01 << 2)  /* UART 8 bit length mode */
#define UART_CFG_PARITY_NONE    (0x00 << 4)  /* No parity */
#define UART_CFG_STOPLEN_1      (0x00 << 6)  /* UART One Stop Bit Select */
#define UART_STAT_RXRDY         (0x01 << 0)  /* Receiver ready */
#define UART_STAT_TXRDY         (0x01 << 2)  /* Transmitter ready for data */
#define UART_CFG_ENABLE         (0x01 << 0)

/*Which Clock source ?, if both are 0 then Internal RC Oscillator is used */
#define USE_PLL    0
#define USE_WATCHDOG   0

#define USE_SYSTICK  1

#define WATCHDOG_300KHZ ((1 << 5) | (0))
#define WATCHDOG_9375HZ ((1 << 5) | (0x1f))
#define WATCHDOG_2300KHZ ((0xf << 5) | (0))
#define PLL_60MHZ (0x24)
#define PLL_24MHZ (0x41)
#define PLL_96MHZ (0x07)

uint32_t SystemCoreClock = 12000000; /* Value @ Reset */
uint32_t SystemMainClock = 12000000; /* Value @ Reset */

#if (USE_SYSTICK)
uint32_t __tick;
void SysTick_Handler(void) {
 __tick++;
}
#endif

void uart0putc(unsigned char c) {
 /* Wait until we're ready to send */
 while (!(LPC_USART0->STAT & UART_STAT_TXRDY));
 LPC_USART0->TXDATA = c;
}

unsigned char uart0getc() {
 /* Wait until we're ready to receive */
 while (!(LPC_USART0->STAT & UART_STAT_RXRDY));
 return LPC_USART0->RXDATA;
}

short uart0PollChar() {
 if (!(LPC_USART0->STAT & UART_STAT_RXRDY))
  return -1;
 return LPC_USART0->RXDATA;
}

int main(void) {
 /* Enable AHB clock to the Switch Matrix , UART0 , IOCON */
 LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7) | (1 << 14) | (1 << 18);

#if (USE_PLL)
 /* Enable the PLL Clock for a maximum 30MHZ SystemCoreClock */
 LPC_SYSCON->SYSPLLCTRL = PLL_60MHZ; /* 60 MHZ pll output clock*/
 LPC_SYSCON->PDRUNCFG &= ~(0x1 << 7); /* Power-up SYSPLL          */
 while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked    */

 LPC_SYSCON->MAINCLKSEL = 3; /* Select PLL Clock Output  */
 LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
 while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated       */

 LPC_SYSCON->SYSAHBCLKDIV = 2; /* Divide by 2 to get the maximum 30MHZ SystemCoreClock */

 SystemMainClock = 12000000 * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1); /* Calculate SystemMainClock for IRC directed to the PLL*/
 SystemCoreClock = SystemMainClock / LPC_SYSCON->SYSAHBCLKDIV; /*Calculate SystemCoreClock */

#elif (USE_WATCHDOG)
 /* Enable the Watchdog Oscillator for minimum power consumption*/
 LPC_SYSCON->WDTOSCCTRL = WATCHDOG_2300KHZ;
 LPC_SYSCON->PDRUNCFG &= ~(0x1 << 6); /* Power-up Watchdog          */
 LPC_SYSCON->MAINCLKSEL = 2; /* Select Watchdog Clock Output  */
 LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
 while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated       */

 if ((LPC_SYSCON->WDTOSCCTRL & (0x0f << 5)) == (0x01 << 5))
 SystemMainClock = 600000 / (2 * (1 + (LPC_SYSCON->WDTOSCCTRL & 0x1f)));
 else
 SystemMainClock = 4600000 / (2 * (1 + (LPC_SYSCON->WDTOSCCTRL & 0x1f)));

 SystemCoreClock = SystemMainClock / LPC_SYSCON->SYSAHBCLKDIV; /* Calculate SystemCoreClock */
 LPC_SYSCON->PDRUNCFG |= (1 << 7) | (1 << 1) | (1 << 0); /* Power down IRC & PLL as not needed now */
#endif

#if (USE_SYSTICK)
 SysTick->LOAD = (SystemCoreClock / 1000 * 1/*# ms*/) - 1; /* Every 1 ms */
 SysTick->VAL = 0;
 __tick = 0;
 SysTick->CTRL = 0x7; /* d2:ClkSrc=SystemCoreClock, d1:Interrupt=enabled, d0:SysTick=enabled */
#endif

 /* Set the UART clock divisor to 1  */
 LPC_SYSCON->UARTCLKDIV = 1; // note on reset the value is 0. i.e clock is disabled
 /* Configure UART0 baud rate */
 LPC_USART0->BRG = ((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4)
   / BAUDRATE - 1;
 LPC_SYSCON->UARTFRGMULT =
   ((((SystemMainClock / LPC_SYSCON->UARTCLKDIV) >> 4) * (0x100))
     / (BAUDRATE * (LPC_USART0->BRG + 1))) - (0x100);
 LPC_SYSCON->UARTFRGDIV = 0xFF; //note on reset the value is 0

 /* Set UART0 to 8N1 and finally enable */
 LPC_USART0->CFG = UART_CFG_DATALEN_8 | UART_CFG_PARITY_NONE
   | UART_CFG_STOPLEN_1 | UART_CFG_ENABLE;

 /* Initialise Chan's Embedded String Functions (xprintf ect) */
 xdev_out(uart0putc);
 xdev_in(uart0getc);

 /* Some variables for Clock logic */
 char buf[9];
 char err = 0;
 long refh, refm, refs; /* ref time */
 int reftick;
 int reftime; // ref time in seconds
 // Enter an infinite loop testing for a keypress
 while (1) {
  switch (uart0PollChar()) {
  case '0':
   xprintf("System Core Clock is %d hz\n\rSystem Main Clock is %d\n\r",
     SystemCoreClock, SystemMainClock);
   break;
  case '1':
   xprintf("current _tick is %d\n\r", __tick);
   break;
  case 's':
   //set clock time hh:mm:ss
   xprintf("Please enter current time hh:mm:ss > ");
   xgets(buf, 9);
   reftick = __tick;
   if (buf[2] == ':' && buf[5] == ':') {
    buf[2] = ' ';
    buf[5] = ' ';
    char *p = &buf[0];
    if (!(xatoi(&p, &refh) && xatoi(&p, &refm) && xatoi(&p, &refs)))
     err = 1;
    else
     reftime = ((refh * 60) + refm) * 60 + refs;
   } else {
    err = 1;
   }
   if (err == 1)
    xprintf("\n\rError the time format is incorrect,  You entered %s\n\r",buf);
   break;
  case 'c':
   //get clock time
  {
   int secs = (__tick - reftick) / 1000; //number of seconds since time set
   int current = (reftime + secs) % (60 * 60 * 60);
   int h = (current / (60 * 60)) % 24;
   int m = (current / 60) % 60;
   int s = current % 60;
   xprintf("Current time is %d:%d:%d  The number of seconds passed is %d\n\r", h, m, s, secs);
  }
   break;
 }
 }
 return 0;
}