my implementation of mbed-like classes using the LPC1768 register access.

Dependents:   registers-example RedWireBridge

This is just to satisfy my curiosity on how the mbed libraries work. I put it here just in case others are too. Every time I learn how another internal register works, I'll keep it here to save myself from future coding headaches.

working

  • DigitalIn
  • DigitalOut
  • wait()

mostly working

  • Serial
  • Timer
  • Ticker
  • Timeout

Serial doesn't have all the methods that mbed had, but it works for me. (only UART0, so only over USB to the pc for now) Timer has the same limitations of mbed for default resolution (30 min limit), and if you start at the end of resolution and stop after it rolls back to 0, it doesn't take that into account. But I added the option to change resolution, so I can have longer timers.

For Ticker, I used a 100 microsecond timer instead of a 1 microsecond Timer, so the smallest interval in between function calls is 100 microseconds. (10KHz) However, this means that the maximum interval in between function calls is 59 hours. (untested)

The Timeout class, simply uses a Ticker, but then marks it as nonactive after the first function call. Automatically calls the detach() function when attaching it again, so no don't need to worry about it.

Revision:
0:d2d9baa1a6d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Timer.cpp	Thu Jan 03 04:25:08 2013 +0000
@@ -0,0 +1,111 @@
+#include "Timer.h"
+//This class uses Timer 1
+
+// static data initialization  (only called once)
+bool Timer::timer1initialized = false; 
+int Timer::resolution = 1000000; //default: microseconds accuracy
+
+void Timer::initTimer1(int res) 
+{
+    uint8_t pclk;
+    uint32_t pclkdiv = (LPC_SC->PCLKSEL0 >> 4) & 0x03; //PCLK for Timer 1 (page 56)
+
+    switch ( pclkdiv ) // table 42 (page 57 in user manual)
+    {
+      case 0x00:
+      default:
+            pclk = 4;
+            break;
+      case 0x01:
+            pclk = 1;
+            break;
+      case 0x02:
+            pclk = 2;
+            break;
+      case 0x03:
+            pclk = 8;
+            break;
+    }
+
+    LPC_TIM1->TCR = 0x02;           // reset timer
+    LPC_TIM1->PR  = (SystemCoreClock / (pclk * res)); //default: microsecond steps
+    LPC_TIM1->MR0 = 2147483647;             // highest number a 32bit signed int can store (for us ~ 35.79 minutes, or, for ms ~ 596.52 hours )
+    LPC_TIM1->IR  = 0xff;           // reset all interrrupts
+    LPC_TIM1->MCR = 0x02;           // reset timer on match
+    LPC_TIM1->TCR = 0x01;           // start timer
+
+    // The timer simply goes on forever! It just resets itself when it hits the max number for TC
+    timer1initialized = true;
+    resolution = res;
+}
+
+Timer::Timer()
+{        
+    if(!timer1initialized)
+    {
+        initTimer1(resolution); //default resolution
+    }
+    
+    starttime = 0;
+    stoptime = 0;
+    running = false;
+}
+
+//for when we want to allow lower counting resolution, eg. milliseconds
+//so we can count longer than the 35 minutes with microsecond resolution
+Timer::Timer(int res) // millisecond, res = 1000
+{   
+    if(!timer1initialized)
+    {
+        initTimer1(res); //custom resolution
+    }
+    
+    starttime = 0;
+    stoptime = 0;
+    running = false;
+}
+
+void Timer::start()
+{
+    starttime = LPC_TIM1->TC;
+    stoptime = 0; //clear previous stoptime
+    running = true;
+}
+
+void Timer::stop()
+{
+   stoptime = LPC_TIM1->TC;
+   running = false;
+}
+
+void Timer::reset()
+{
+    if(running)
+    {
+        starttime = LPC_TIM1->TC;
+    }
+    else
+    {
+        starttime = 0;
+    }
+    
+    stoptime = 0;
+}
+
+float Timer::read()
+{
+    if(running)
+    {    
+        int currenttime = LPC_TIM1->TC;
+        return (currenttime - starttime) / (resolution*1.0);
+    }
+    else // compare startime and stoptime
+    {
+        return (stoptime - starttime) / (resolution*1.0);
+    }
+}
+
+Timer::operator float()
+{
+    return read();
+}