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.
Ticker.cpp
- Committer:
- elevatorguy
- Date:
- 2013-01-03
- Revision:
- 0:d2d9baa1a6d8
- Child:
- 1:0b44a0a56f92
File content as of revision 0:d2d9baa1a6d8:
#include "Ticker.h" //This class uses Timer 2 extern "C" void TIMER2_IRQHandler(void) { if ( LPC_TIM2->IR & 0x1 ) { LPC_TIM2->IR = 0x1; /* clear interrupt flag */ for(char count = 0; count < Ticker::active_tickers; count++) { if((*(Ticker::tickers[count])).active) { if((*(Ticker::tickers[count])).remaining == 0) { //void (*func)(void) = (void (*)(void))((uint32_t)&isr); //func(); (*(void (*)(void))((*(Ticker::tickers[count])).func))(); if((*(Ticker::tickers[count])).timeout) (*(Ticker::tickers[count])).active = false; else (*(Ticker::tickers[count])).remaining = (*(Ticker::tickers[count])).interval - 1; //set up for next interval } else { (*(Ticker::tickers[count])).remaining = (*(Ticker::tickers[count])).remaining - 1; } } } } } // static data initialization (only called once) bool Ticker::timer2initialized = false; int Ticker::active_tickers = 0; int Ticker::MAX = 5; Ticker** Ticker::tickers = 0; //NULL POINTER void Ticker::initTimer2() { LPC_SC->PCLKSEL1 &= (3 << 12); //mask LPC_SC->PCLKSEL1 |= (1 << 12); //sets it to 1*SystemCoreClock - table 42 (page 57 in user manual) LPC_SC->PCONP |= (0x1<<22); // turn on power for timer 2 LPC_TIM2->TCR = 0x02; // reset timer LPC_TIM2->PR = (SystemCoreClock / 1000000); //microsecond steps LPC_TIM2->MR0 = 100; // 100 microsecond interval interrupts LPC_TIM2->IR = 0x3f; // reset all interrrupts LPC_TIM2->MCR = 0x03; // reset timer on match and generate interrupt (MR0) LPC_TIM2->TCR = 0x01; // start timer NVIC_EnableIRQ(TIMER2_IRQn); // Enable the interrupt timer2initialized = true; } Ticker::Ticker() { if(!timer2initialized) { initTimer2(); tickers = new Ticker*[MAX]; } active = false; timeout = false; } Ticker::Ticker(int maxsize) { if(!timer2initialized) { initTimer2(); tickers = new Ticker*[maxsize]; MAX = maxsize; } active = false; timeout = false; } void Ticker::attach(void (*funcaddr)(void), float secinterval) { func = (uint32_t)funcaddr; //pointer to function address interval = secinterval*10000; remaining = secinterval*10000 - 1; // 100 microsecond resolution tickers[active_tickers] = this; active_tickers = active_tickers + 1; active = true; } void Ticker::detach() { active_tickers = active_tickers - 1; tickers[active_tickers] = 0; //NULL pointer active = false; } Ticker::~Ticker() { if(active || timeout) detach(); }