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.

Timer.cpp

Committer:
elevatorguy
Date:
2013-01-03
Revision:
2:276fb0fe230c
Parent:
0:d2d9baa1a6d8

File content as of revision 2:276fb0fe230c:

#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();
}