aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/test-timers.cpp136
-rw-r--r--wirish/HardwareTimer.cpp149
-rw-r--r--wirish/HardwareTimer.h73
3 files changed, 355 insertions, 3 deletions
diff --git a/examples/test-timers.cpp b/examples/test-timers.cpp
index 374b903..9b1efc6 100644
--- a/examples/test-timers.cpp
+++ b/examples/test-timers.cpp
@@ -11,6 +11,9 @@ void handler2(void);
void handler3(void);
void handler4(void);
+void handler3b(void);
+void handler4b(void);
+
int toggle = 0;
int t;
@@ -34,7 +37,7 @@ void setup()
/* Set up the LED to blink */
pinMode(LED_PIN, OUTPUT);
- pinMode(38, INPUT);
+ pinMode(38, INPUT_PULLUP);
/* Send a message out USART2 */
//SerialUSB.begin(9600);
@@ -45,15 +48,133 @@ void setup()
Timers[t].setChannel3Mode(TIMER_OUTPUTCOMPARE);
Timers[t].setChannel4Mode(TIMER_OUTPUTCOMPARE);
}
+
+ // Wait for user to attach...
+ delay(2000);
}
void loop() {
+ SerialUSB.println("-----------------------------------------------------");
+ SerialUSB.println("Testing Pause/Resume; button roughly controls Timer4");
+ count3 = 0;
+ count4 = 0;
+ Timer3.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer3.pause();
+ Timer4.pause();
+ Timer3.setCount(0);
+ Timer4.setCount(0);
+ Timer3.setOverflow(30000);
+ Timer4.setOverflow(30000);
+ Timer3.setCompare1(1000);
+ Timer4.setCompare1(1000);
+ Timer3.attachCompare1Interrupt(handler3b);
+ Timer4.attachCompare1Interrupt(handler4b);
+ Timer3.resume();
+ Timer4.resume();
+ SerialUSB.println("~4 seconds...");
+ for(int i = 0; i<4000; i++) {
+ if(digitalRead(38)) {
+ Timer4.pause();
+ } else {
+ Timer4.resume();
+ }
+ delay(1);
+ }
+ Timer3.setChannel1Mode(TIMER_DISABLED);
+ Timer4.setChannel1Mode(TIMER_DISABLED);
+ SerialUSB.print("Count3: "); SerialUSB.println(count3);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
+
+ SerialUSB.println("-----------------------------------------------------");
+ SerialUSB.println("Testing setPeriod");
+ Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer4.setCompare1(1);
+ Timer4.setPeriod(10);
+ Timer4.pause();
+ Timer4.setCount(0);
+ Timer4.attachCompare1Interrupt(handler4b);
+ SerialUSB.println("Period 10ms, wait 2 seconds...");
+ count4 = 0;
+ Timer4.resume();
+ delay(2000);
+ Timer4.pause();
+ Timer4.setChannel1Mode(TIMER_DISABLED);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
+ SerialUSB.println("(should be around 2sec/10ms = 200000)");
+ Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer4.setCompare1(1);
+ Timer4.pause();
+ Timer4.setPeriod(30000);
+ Timer4.setCount(0);
+ Timer4.attachCompare1Interrupt(handler4b);
+ SerialUSB.println("Period 30000ms, wait 2 seconds...");
+ count4 = 0;
+ Timer4.resume();
+ delay(2000);
+ Timer4.pause();
+ Timer4.setChannel1Mode(TIMER_DISABLED);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
+ SerialUSB.println("(should be around 2sec/30000ms ~ 67)");
+
+ Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer4.setPeriod(300000);
+ Timer4.setCompare1(1);
+ Timer4.pause();
+ Timer4.setCount(0);
+ Timer4.attachCompare1Interrupt(handler4b);
+ SerialUSB.println("Period 300000ms, wait 2 seconds...");
+ count4 = 0;
+ Timer4.resume();
+ delay(2000);
+ Timer4.pause();
+ Timer4.setChannel1Mode(TIMER_DISABLED);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
+ SerialUSB.println("(should be around 2sec/300000ms ~ 6.7)");
+
+ Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer4.setPrescaleFactor(33);
+ Timer4.setOverflow(65454);
+ Timer4.pause();
+ Timer4.setCount(0);
+ Timer4.setCompare1(1);
+ Timer4.attachCompare1Interrupt(handler4b);
+ SerialUSB.println("Period 30000ms, wait 2 seconds...");
+ count4 = 0;
+ Timer4.resume();
+ delay(2000);
+ Timer4.pause();
+ Timer4.setChannel1Mode(TIMER_DISABLED);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
+ SerialUSB.println("(should be around 2sec/30000ms ~ 67)");
+
+ Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timer4.setCompare1(1);
+ Timer4.setPeriod(30000);
+ Timer4.pause();
+ Timer4.setCount(0);
+ Timer4.attachCompare1Interrupt(handler4b);
+ SerialUSB.println("Period 30000ms, wait 2 seconds...");
+ count4 = 0;
+ Timer4.resume();
+ delay(2000);
+ Timer4.pause();
+ Timer4.setChannel1Mode(TIMER_DISABLED);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
+ SerialUSB.println("(should be around 2sec/30000ms ~ 67)");
+
for(t=0; t<4; t++) {
toggle ^= 1; digitalWrite(LED_PIN, toggle);
- delay(1000);
+ delay(100);
SerialUSB.println("-----------------------------------------------------");
SerialUSB.print("Testing Timer "); SerialUSB.println(t+1);
count1 = count2 = count3 = count4 = 0;
+ Timers[t].setOverflow(0xFFFF);
+ Timers[t].setPrescaleFactor(1);
+ Timers[t].setCompare1(65535);
+ Timers[t].setCompare2(65535);
+ Timers[t].setCompare3(65535);
+ Timers[t].setCompare4(65535);
Timers[t].setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timers[t].setChannel2Mode(TIMER_OUTPUTCOMPARE);
Timers[t].setChannel3Mode(TIMER_OUTPUTCOMPARE);
@@ -62,7 +183,8 @@ void loop() {
Timers[t].attachCompare2Interrupt(handler2);
Timers[t].attachCompare3Interrupt(handler3);
Timers[t].attachCompare4Interrupt(handler4);
- delay(5000);
+ Timers[t].resume();
+ delay(3000);
Timers[t].setChannel1Mode(TIMER_DISABLED);
Timers[t].setChannel2Mode(TIMER_DISABLED);
Timers[t].setChannel3Mode(TIMER_DISABLED);
@@ -72,6 +194,7 @@ void loop() {
SerialUSB.print("Count3: "); SerialUSB.println(count3);
SerialUSB.print("Count4: "); SerialUSB.println(count4);
}
+
}
void handler1(void) {
@@ -95,6 +218,13 @@ void handler4(void) {
count4++;
}
+void handler3b(void) {
+ count3++;
+}
+void handler4b(void) {
+ count4++;
+}
+
int main(void) {
init();
diff --git a/wirish/HardwareTimer.cpp b/wirish/HardwareTimer.cpp
new file mode 100644
index 0000000..3c8e9f4
--- /dev/null
+++ b/wirish/HardwareTimer.cpp
@@ -0,0 +1,149 @@
+/* *****************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Bryan Newbold.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * ****************************************************************************/
+
+/**
+ * @brief wirish timer class to manage the four 16-bit timer peripherals
+ *
+ * This implementation is not very efficient (lots of duplicated functions)
+ */
+
+#include "wirish.h"
+#include "HardwareTimer.h"
+
+HardwareTimer::HardwareTimer(uint8 timerNum) {
+ ASSERT(timerNum == 1 ||
+ timerNum == 2 ||
+ timerNum == 3 ||
+ timerNum == 4);
+ this->timerNum = timerNum;
+ // Need to remember over flow for bounds checking
+ this->overflow = 0xFFFF;
+}
+
+void HardwareTimer::resume(void) {
+ timer_resume(this->timerNum);
+}
+void HardwareTimer::pause(void) {
+ timer_pause(this->timerNum);
+}
+void HardwareTimer::setPrescaleFactor(uint16 factor) {
+ // The prescaler register is zero-indexed
+ timer_set_prescaler(this->timerNum, factor-1);
+}
+void HardwareTimer::setOverflow(uint16 val) {
+ this->overflow = val;
+ timer_set_reload(this->timerNum, val);
+}
+void HardwareTimer::setCount(uint16 val) {
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_count(this->timerNum, val);
+}
+uint16 HardwareTimer::getCount(void) {
+ return timer_get_count(this->timerNum);
+}
+
+// This function will set the prescaler and overflow to get
+// a period of the given length with the most resolution;
+// the return value is the overflow value and thus the largest
+// value that can be set as a compare.
+uint16 HardwareTimer::setPeriod(uint32 microseconds) {
+ // XXX: 72MHz shouldn't be hard coded in here... global define?
+
+ // Not the best way to handle this edge case?
+ if(!microseconds) {
+ setPrescaleFactor(1);
+ setOverflow(1);
+ return this->overflow;
+ }
+ // With a prescale factor of 1, there are 72counts/ms
+ uint16 ps = ((microseconds*72)/65536) + 1;
+ setPrescaleFactor(ps);
+ // Find this overflow will always be less than 65536
+ setOverflow((microseconds*72)/ps);
+ return this->overflow;
+}
+void HardwareTimer::setChannel1Mode(uint8 mode) {
+ timer_set_mode(this->timerNum,1,mode);
+}
+void HardwareTimer::setChannel2Mode(uint8 mode) {
+ timer_set_mode(this->timerNum,2,mode);
+}
+void HardwareTimer::setChannel3Mode(uint8 mode) {
+ timer_set_mode(this->timerNum,3,mode);
+}
+void HardwareTimer::setChannel4Mode(uint8 mode) {
+ timer_set_mode(this->timerNum,4,mode);
+}
+void HardwareTimer::setCompare1(uint16 val) {
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_compare_value(this->timerNum,1,val);
+}
+void HardwareTimer::setCompare2(uint16 val) {
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_compare_value(this->timerNum,2,val);
+}
+void HardwareTimer::setCompare3(uint16 val) {
+ ASSERT(this->timerNum);
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_compare_value(this->timerNum,3,val);
+}
+void HardwareTimer::setCompare4(uint16 val) {
+ if(val > this->overflow)
+ val = this->overflow;
+ timer_set_compare_value(this->timerNum,4,val);
+}
+void HardwareTimer::attachCompare1Interrupt(voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum,1,handler);
+}
+void HardwareTimer::attachCompare2Interrupt(voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum,2,handler);
+}
+void HardwareTimer::attachCompare3Interrupt(voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum,3,handler);
+}
+void HardwareTimer::attachCompare4Interrupt(voidFuncPtr handler) {
+ timer_attach_interrupt(this->timerNum,4,handler);
+}
+void HardwareTimer::detachCompare1Interrupt(void) {
+ timer_detach_interrupt(this->timerNum,1);
+}
+void HardwareTimer::detachCompare2Interrupt(void) {
+ timer_detach_interrupt(this->timerNum,2);
+}
+void HardwareTimer::detachCompare3Interrupt(void) {
+ timer_detach_interrupt(this->timerNum,3);
+}
+void HardwareTimer::detachCompare4Interrupt(void) {
+ timer_detach_interrupt(this->timerNum,4);
+}
+
+HardwareTimer Timer1(1);
+HardwareTimer Timer2(2);
+HardwareTimer Timer3(3);
+HardwareTimer Timer4(4);
+
diff --git a/wirish/HardwareTimer.h b/wirish/HardwareTimer.h
new file mode 100644
index 0000000..c79f54f
--- /dev/null
+++ b/wirish/HardwareTimer.h
@@ -0,0 +1,73 @@
+/* *****************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 Bryan Newbold.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * ****************************************************************************/
+
+/**
+ * @brief wirish timer class to manage the four 16-bit timer peripherals
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+class HardwareTimer {
+ private:
+ uint16 overflow;
+ uint8 timerNum;
+
+ public:
+ HardwareTimer(uint8 timer_num);
+
+ void pause(void);
+ void resume(void);
+ void setPrescaleFactor(uint16 factor);
+ void setOverflow(uint16 val); // truncates to overflow
+ void setCount(uint16 val); // truncates to overflow
+ uint16 getCount(void);
+
+ // tries to set prescaler and overflow wisely; returns overflow
+ uint16 setPeriod(uint32 microseconds);
+ void setChannel1Mode(uint8 mode);
+ void setChannel2Mode(uint8 mode);
+ void setChannel3Mode(uint8 mode);
+ void setChannel4Mode(uint8 mode);
+ void setCompare1(uint16 val); // truncates to overflow
+ void setCompare2(uint16 val); // truncates to overflow
+ void setCompare3(uint16 val); // truncates to overflow
+ void setCompare4(uint16 val); // truncates to overflow
+ void attachCompare1Interrupt(voidFuncPtr handler);
+ void attachCompare2Interrupt(voidFuncPtr handler);
+ void attachCompare3Interrupt(voidFuncPtr handler);
+ void attachCompare4Interrupt(voidFuncPtr handler);
+ void detachCompare1Interrupt(void);
+ void detachCompare2Interrupt(void);
+ void detachCompare3Interrupt(void);
+ void detachCompare4Interrupt(void);
+};
+
+extern HardwareTimer Timer1;
+extern HardwareTimer Timer2;
+extern HardwareTimer Timer3;
+extern HardwareTimer Timer4;
+
+#endif
+