aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/test-timers.cpp143
-rw-r--r--examples/vga-leaf.cpp138
-rw-r--r--examples/vga-scope.cpp28
-rw-r--r--libmaple/timers.c57
-rw-r--r--notes/timers.txt73
-rw-r--r--notes/vga.txt26
-rw-r--r--wirish/rules.mk1
-rw-r--r--wirish/wirish.c6
-rw-r--r--wirish/wirish.h3
9 files changed, 163 insertions, 312 deletions
diff --git a/examples/test-timers.cpp b/examples/test-timers.cpp
index c3e3cb9..374b903 100644
--- a/examples/test-timers.cpp
+++ b/examples/test-timers.cpp
@@ -2,7 +2,6 @@
// and turns on PWM on pin 2
#include "wirish.h"
-#include "timers.h"
#define LED_PIN 13
#define PWM_PIN 2
@@ -12,12 +11,8 @@ void handler2(void);
void handler3(void);
void handler4(void);
-void setup_test_timer(void);
-
int toggle = 0;
-int timer = 1;
-int state = 3;
-int last_but = 0;
+int t;
int count1 = 0;
int count2 = 0;
@@ -25,13 +20,15 @@ int count3 = 0;
int count4 = 0;
uint16 rate1 = 1000;
uint16 rate2 = 2000;
-uint16 rate3 = 3000;
-uint16 rate4 = 4000;
+uint16 rate3 = 4000;
+uint16 rate4 = 8000;
uint16 val1 = 10000;
uint16 val2 = 10000;
uint16 val3 = 10000;
uint16 val4 = 10000;
+HardwareTimer Timers[] = {Timer1, Timer2, Timer3, Timer4};
+
void setup()
{
/* Set up the LED to blink */
@@ -42,123 +39,59 @@ void setup()
/* Send a message out USART2 */
//SerialUSB.begin(9600);
SerialUSB.println("Begining timer test...");
-
- /* Send a message out the usb virtual serial port */
- //SerialUSB.println("Hello!");
-
- timer = 1;
- setup_test_timer();
-
+ for(int t=0; t<4; t++) {
+ Timers[t].setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].setChannel2Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].setChannel3Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].setChannel4Mode(TIMER_OUTPUTCOMPARE);
+ }
}
-
void loop() {
- toggle ^= 1;
- digitalWrite(LED_PIN, toggle);
- delay(800);
-
-
- if(digitalRead(38) && !last_but) {
- state++;
- switch(state){
- case 1:
- SerialUSB.println("Testing Timer1 ---------------------------");
- timer = 1;
- setup_test_timer();
- break;
- case 2:
- SerialUSB.println("Testing Timer2 ---------------------------");
- timer_set_mode(timer,1,TIMER_DISABLED);
- timer_set_mode(timer,2,TIMER_DISABLED);
- timer_set_mode(timer,3,TIMER_DISABLED);
- timer_set_mode(timer,4,TIMER_DISABLED);
- timer_set_count(1,0);
- timer_set_count(2,0);
- timer_set_count(3,0);
- timer_set_count(4,0);
- timer = 2;
- setup_test_timer();
- break;
- case 3:
- SerialUSB.println("Testing Timer3 ---------------------------");
- timer_set_mode(timer,1,TIMER_DISABLED);
- timer_set_mode(timer,2,TIMER_DISABLED);
- timer_set_mode(timer,3,TIMER_DISABLED);
- timer_set_mode(timer,4,TIMER_DISABLED);
- timer = 3;
- setup_test_timer();
- break;
- case 4:
- SerialUSB.println("Testing Timer4 ---------------------------");
- timer_set_mode(timer,1,TIMER_DISABLED);
- timer_set_mode(timer,2,TIMER_DISABLED);
- timer_set_mode(timer,3,TIMER_DISABLED);
- timer_set_mode(timer,4,TIMER_DISABLED);
- timer = 4;
- setup_test_timer();
- break;
- default:
- state = 0;
- timer_set_mode(timer,1,TIMER_DISABLED);
- timer_set_mode(timer,2,TIMER_DISABLED);
- timer_set_mode(timer,3,TIMER_DISABLED);
- timer_set_mode(timer,4,TIMER_DISABLED);
- timer = 0;
- SerialUSB.println("Restarting -------------------------------");
- }
+ for(t=0; t<4; t++) {
+ toggle ^= 1; digitalWrite(LED_PIN, toggle);
+ delay(1000);
+ SerialUSB.println("-----------------------------------------------------");
+ SerialUSB.print("Testing Timer "); SerialUSB.println(t+1);
+ count1 = count2 = count3 = count4 = 0;
+ Timers[t].setChannel1Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].setChannel2Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].setChannel3Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].setChannel4Mode(TIMER_OUTPUTCOMPARE);
+ Timers[t].attachCompare1Interrupt(handler1);
+ Timers[t].attachCompare2Interrupt(handler2);
+ Timers[t].attachCompare3Interrupt(handler3);
+ Timers[t].attachCompare4Interrupt(handler4);
+ delay(5000);
+ Timers[t].setChannel1Mode(TIMER_DISABLED);
+ Timers[t].setChannel2Mode(TIMER_DISABLED);
+ Timers[t].setChannel3Mode(TIMER_DISABLED);
+ Timers[t].setChannel4Mode(TIMER_DISABLED);
+ SerialUSB.print("Count1: "); SerialUSB.println(count1);
+ SerialUSB.print("Count2: "); SerialUSB.println(count2);
+ SerialUSB.print("Count3: "); SerialUSB.println(count3);
+ SerialUSB.print("Count4: "); SerialUSB.println(count4);
}
-
- SerialUSB.print("Doing ------------------ "); SerialUSB.println(timer,DEC);
- if(timer!=0) { SerialUSB.print("CNT: "); SerialUSB.println(timer_get_count(timer),DEC); }
- SerialUSB.print("Count1 : "); SerialUSB.println(count1,DEC);
- SerialUSB.print("Count2 : "); SerialUSB.println(count2,DEC);
- SerialUSB.print("Count3 : "); SerialUSB.println(count3,DEC);
- SerialUSB.print("Count4 : "); SerialUSB.println(count4,DEC);
- SerialUSB.println();
- /*
- SerialUSB.print("Status : "); SerialUSB.println(get_sr(),HEX);
- */
- last_but = digitalRead(38);
-}
-
-void setup_test_timer(void) {
- timer_set_prescaler(timer,10000);
- timer_set_mode(timer,1,TIMER_OUTPUTCOMPARE);
- timer_set_mode(timer,2,TIMER_OUTPUTCOMPARE);
- timer_set_mode(timer,3,TIMER_OUTPUTCOMPARE);
- timer_set_mode(timer,4,TIMER_OUTPUTCOMPARE);
- val1 = val2 = val3 = val4 = 10000;
- timer_set_compare_value(timer,1,val1);
- timer_set_compare_value(timer,2,val2);
- timer_set_compare_value(timer,3,val3);
- timer_set_compare_value(timer,4,val4);
- timer_attach_interrupt(timer,1,handler1);
- timer_attach_interrupt(timer,2,handler2);
- timer_attach_interrupt(timer,3,handler3);
- timer_attach_interrupt(timer,4,handler4);
- count1 = count2 = count3 = count4 = 0;
}
void handler1(void) {
val1 += rate1;
- timer_set_compare_value(timer,1,val1);
+ Timers[t].setCompare1(val1);
count1++;
- //SerialUSB.print("CC3 Inter: "); SerialUSB.print(get_sr(),HEX);
- // SerialUSB.print(", "); SerialUSB.println(get_sr_buff(),HEX);
}
void handler2(void) {
val2 += rate2;
- timer_set_compare_value(timer,2,val2);
+ Timers[t].setCompare2(val2);
count2++;
}
void handler3(void) {
val3 += rate3;
- timer_set_compare_value(timer,3,val3);
+ Timers[t].setCompare3(val3);
count3++;
}
void handler4(void) {
val4 += rate4;
- timer_set_compare_value(timer,4,val4);
+ Timers[t].setCompare4(val4);
count4++;
}
diff --git a/examples/vga-leaf.cpp b/examples/vga-leaf.cpp
index c2e61ae..3374608 100644
--- a/examples/vga-leaf.cpp
+++ b/examples/vga-leaf.cpp
@@ -1,39 +1,11 @@
-
#include "wirish.h"
-/*
-D5 PB6 - TIM4_CH1 I2C1_SCL - - Y
-D6 PA8 - TIM1_CH1 - USART1_CK - Y
-D7 PA9 - TIM1_CH2 - USART1_TX - Y
-D8 PA10 - TIM1_CH3 - USART1_RX - Y
-D9 PB7 - TIM4_CH2 I2C1_SDA - - Y
-*/
-
-//gpio_write_bit(GPIOB_BASE, 6, 1); // VGA_R
-//gpio_write_bit(GPIOB_BASE, 6, 0);
-
-//(GPIOA_BASE)->BSRR = BIT(8);
-//asm volatile("nop");
-//(GPIOA_BASE)->BRR = BIT(8);
-/*
- gpio_write_bit(GPIOB_BASE, 6, 1); // VGA_R
- gpio_write_bit(GPIOB_BASE, 6, 0);
- gpio_write_bit(GPIOA_BASE, 8, 1); // VGA_G
- gpio_write_bit(GPIOA_BASE, 8, 0);
- gpio_write_bit(GPIOA_BASE, 9, 1); // VGA_B
- gpio_write_bit(GPIOA_BASE, 9, 0);
- gpio_write_bit(GPIOA_BASE, 10, 1); // VGA_V
- gpio_write_bit(GPIOA_BASE, 10, 0);
- gpio_write_bit(GPIOB_BASE, 7, 1); // VGA_H
- gpio_write_bit(GPIOB_BASE, 7, 0);
-*/
-
#define LED_PIN 13
-#define VGA_R 5 // B6
-#define VGA_G 6 // A8
-#define VGA_B 7 // A9
-#define VGA_V 11 // A6
-#define VGA_H 12 // A7
+#define VGA_R 5 // B6
+#define VGA_G 6 // A8
+#define VGA_B 7 // A9
+#define VGA_V 11 // A6
+#define VGA_H 12 // A7
#define VGA_R_HIGH (GPIOB_BASE)->BSRR = BIT(6)
#define VGA_R_LOW (GPIOB_BASE)->BRR = BIT(6)
#define VGA_G_HIGH (GPIOA_BASE)->BSRR = BIT(8)
@@ -89,11 +61,14 @@ void setup()
timer_set_count(4,0);
}
+void loop() {
+ // everything happens in the interrupts!
+}
+
int toggle = 0;
-uint16 x = 0;
+uint16 x = 0;
uint16 y = 0;
uint8 v_active = 1;
-GPIO_Port *portb = GPIOB_BASE;
void isr_porch(void) {
VGA_H_HIGH;
@@ -139,9 +114,9 @@ uint8 logo[18][16] = {
void isr_start(void) {
if(!v_active) { return; }
+ VGA_R_LOW;
VGA_R_HIGH;
- //delayMicroseconds(2);
- //gpio_write_bit(GPIOA_BASE, 8, 1); // VGA_G
+
for(x=0; x<32; x++) {
if(logo[y/28][x/2]) {
VGA_G_HIGH;
@@ -151,7 +126,6 @@ void isr_start(void) {
VGA_B_LOW;
}
}
-
}
void isr_stop(void) {
if(!v_active) { return; }
@@ -163,94 +137,6 @@ void isr_update(void) {
VGA_H_LOW;
}
-void loop() {
- /*
- toggle ^= 1;
- digitalWrite(LED_PIN, toggle);
- delay(100);
- Serial2.println("HIHIHI!");
- */
- //for(y=0; y<480; y++) {
- /*
- for(y=0; y<160; y++) {
- VGA_R_LOW;
- VGA_H_LOW;
- delayMicroseconds(3);
- VGA_H_HIGH;
- VGA_R_HIGH;
- delayMicroseconds(8);
- VGA_G_HIGH;
- delayMicroseconds(10);
- VGA_B_HIGH;
- delayMicroseconds(10);
- VGA_R_LOW;
- VGA_B_LOW;
- VGA_G_LOW;
- //VGA_G_HIGH;
- }
- for(y=0; y<160; y++) {
- VGA_R_LOW;
- VGA_H_LOW;
- delayMicroseconds(3);
- VGA_H_HIGH;
- VGA_G_HIGH;
- delayMicroseconds(8);
- VGA_R_HIGH;
- delayMicroseconds(10);
- VGA_B_HIGH;
- delayMicroseconds(10);
- VGA_R_LOW;
- VGA_B_LOW;
- VGA_G_LOW;
- //VGA_G_HIGH;
- }
- for(y=0; y<160; y++) {
- VGA_R_LOW;
- VGA_H_LOW;
- delayMicroseconds(3);
- VGA_H_HIGH;
- VGA_B_HIGH;
- delayMicroseconds(8);
- VGA_G_HIGH;
- delayMicroseconds(10);
- VGA_R_HIGH;
- delayMicroseconds(10);
- VGA_R_LOW;
- VGA_B_LOW;
- VGA_G_LOW;
- //VGA_G_HIGH;
- }
- for(y=0; y<11; y++) {
- VGA_R_LOW;
- VGA_H_LOW;
- delayMicroseconds(3);
- VGA_R_LOW;
- VGA_H_HIGH;
- delayMicroseconds(28);
- }
- VGA_V_LOW;
- for(y=0; y<2; y++) {
- VGA_R_LOW;
- VGA_H_LOW;
- delayMicroseconds(3);
- VGA_R_LOW;
- VGA_H_HIGH;
- delayMicroseconds(28);
- }
- VGA_V_HIGH;
- for(y=0; y<30; y++) {
- VGA_R_LOW;
- VGA_H_LOW;
- delayMicroseconds(3);
- VGA_R_LOW;
- VGA_H_HIGH;
- delayMicroseconds(28);
- }
- */
-
-}
-
-
int main(void) {
init();
setup();
diff --git a/examples/vga-scope.cpp b/examples/vga-scope.cpp
index 1f597a4..3e7e75e 100644
--- a/examples/vga-scope.cpp
+++ b/examples/vga-scope.cpp
@@ -1,33 +1,6 @@
#include "wirish.h"
-/*
-D5 PB6 - TIM4_CH1 I2C1_SCL - - Y
-D6 PA8 - TIM1_CH1 - USART1_CK - Y
-D7 PA9 - TIM1_CH2 - USART1_TX - Y
-D8 PA10 - TIM1_CH3 - USART1_RX - Y
-D9 PB7 - TIM4_CH2 I2C1_SDA - - Y
-*/
-
-//gpio_write_bit(GPIOB_BASE, 6, 1); // VGA_R
-//gpio_write_bit(GPIOB_BASE, 6, 0);
-
-//(GPIOA_BASE)->BSRR = BIT(8);
-//asm volatile("nop");
-//(GPIOA_BASE)->BRR = BIT(8);
-/*
- gpio_write_bit(GPIOB_BASE, 6, 1); // VGA_R
- gpio_write_bit(GPIOB_BASE, 6, 0);
- gpio_write_bit(GPIOA_BASE, 8, 1); // VGA_G
- gpio_write_bit(GPIOA_BASE, 8, 0);
- gpio_write_bit(GPIOA_BASE, 9, 1); // VGA_B
- gpio_write_bit(GPIOA_BASE, 9, 0);
- gpio_write_bit(GPIOA_BASE, 10, 1); // VGA_V
- gpio_write_bit(GPIOA_BASE, 10, 0);
- gpio_write_bit(GPIOB_BASE, 7, 1); // VGA_H
- gpio_write_bit(GPIOB_BASE, 7, 0);
-*/
-
#define LED_PIN 13
#define ANALOG_PIN 18
#define VGA_R 5 // B6
@@ -152,7 +125,6 @@ void isr_update(void) {
void loop() {
//val = analogRead(ANALOG_PIN);
-
}
diff --git a/libmaple/timers.c b/libmaple/timers.c
index a772cf9..daf8b51 100644
--- a/libmaple/timers.c
+++ b/libmaple/timers.c
@@ -75,15 +75,17 @@ typedef struct {
uint16 RESERVED19;
} Timer;
-
+// These are the output compare interrupt functions that get called by the
+// handlers below
volatile static voidFuncPtr timer1_handlers[4];
volatile static voidFuncPtr timer2_handlers[4];
volatile static voidFuncPtr timer3_handlers[4];
volatile static voidFuncPtr timer4_handlers[4];
+// This function should probably be rewriten to take (timer_num, mode) and have
+// prescaler set elsewhere. The mode can be passed through to set_mode at the
+// end
void timer_init(uint8 timer_num, uint16 prescale) {
- // This initialization is very PWM-specific. That's a good default but it
- // should probably call down to a set_mode function
Timer *timer; uint8 is_advanced = 0;
@@ -151,9 +153,11 @@ void timer_init(uint8 timer_num, uint16 prescale) {
timer->CR1 |= 1; // Enable timer
}
-void timer_set_count(uint8 timer_num, uint16 value) {
- Timer *timer;
- ASSERT(timer_num > 0 && timer_num <= 4);
+// This function sets the counter value via register for the specified timer.
+// Can't think of specific usecases except for resetting to zero but it's easy
+// to implement and allows for "creative" programming
+void timer_set_count(uint8 timer_num, uint16 value) { Timer *timer;
+ASSERT(timer_num > 0 && timer_num <= 4);
switch(timer_num) {
case 1:
@@ -172,6 +176,8 @@ void timer_set_count(uint8 timer_num, uint16 value) {
timer->CNT = value;
}
+// Returns the current timer counter value. Probably very inaccurate if the
+// counter is running with a low prescaler.
uint16 timer_get_count(uint8 timer_num) {
Timer *timer;
ASSERT(timer_num > 0 && timer_num <= 4);
@@ -193,6 +199,7 @@ uint16 timer_get_count(uint8 timer_num) {
return timer->CNT;
}
+// Does what it says
void timer_set_prescaler(uint8 timer_num, uint16 prescale) {
Timer *timer;
ASSERT(timer_num > 0 && timer_num <= 4);
@@ -214,6 +221,8 @@ void timer_set_prescaler(uint8 timer_num, uint16 prescale) {
timer->PSC = prescale;
}
+// This sets the "reload" or "overflow" value for the entire timer. We should
+// probably settle on either "reload" or "overflow" to prevent confusion?
void timer_set_reload(uint8 timer_num, uint16 max_reload) {
Timer *timer;
ASSERT(timer_num > 0 && timer_num <= 4);
@@ -235,15 +244,28 @@ void timer_set_reload(uint8 timer_num, uint16 max_reload) {
timer->ARR = max_reload;
}
-
+// This quickly disables all 4 timers, presumably as part of a system shutdown
+// or similar to prevent interrupts and PWM output without 16 seperate function
+// calls to timer_set_mode
void timer_disable_all(void) {
// Note: this must be very robust because it gets called from, eg, ASSERT
// TODO: rewrite?
- Timer *timer; Timer *timers[4] = { (Timer*)TIMER1_BASE,
- (Timer*)TIMER2_BASE, (Timer*)TIMER3_BASE, (Timer*)TIMER4_BASE, }; int i;
- for (i = 0; i < 4; i++) { timer = timers[i]; timer->CR1 = 0; timer->CCER =
- 0; } }
+ Timer *timer;
+ Timer *timers[4] = { (Timer*)TIMER1_BASE,
+ (Timer*)TIMER2_BASE,
+ (Timer*)TIMER3_BASE,
+ (Timer*)TIMER4_BASE,
+ };
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ timer = timers[i];
+ timer->CR1 = 0;
+ timer->CCER = 0;
+ }
+}
+// Sets the mode of individual timer channels, including a DISABLE mode
void timer_set_mode(uint8 timer_num, uint8 channel, uint8 mode) {
Timer *timer;
switch (timer_num) {
@@ -359,6 +381,7 @@ void timer_set_mode(uint8 timer_num, uint8 channel, uint8 mode) {
}
}
+// This sets the compare value (aka the trigger) for a given timer channel
void timer_set_compare_value(uint8 timer_num, uint8 compare_num, uint16 value) {
// The faster version of this function is the inline timer_pwm_write_ccr
@@ -395,6 +418,8 @@ void timer_set_compare_value(uint8 timer_num, uint8 compare_num, uint16 value) {
}
}
+// Stores a pointer to the passed usercode interrupt function and configures
+// the actual ISR so that it will actually be called
void timer_attach_interrupt(uint8 timer_num, uint8 compare_num, voidFuncPtr handler) {
Timer *timer;
ASSERT(timer_num > 0 && timer_num <= 4 && compare_num > 0 && compare_num <= 4);
@@ -455,12 +480,20 @@ void timer_detach_interrupt(uint8 timer_num, uint8 compare_num) {
}
}
+// The following are the actual interrupt handlers; 1 for each timer which must
+// determine which actual compare value (aka channel) was triggered.
+//
+// These ISRs get called when the timer interrupt is enabled, the timer is running, and
+// the timer count equals any of the CCR registers /or/ has overflowed.
+//
+// This is a rather long implementation...
void TIM1_CC_IRQHandler(void) {
- // This is a rather long implementation...
Timer *timer = (Timer*)TIMER1_BASE;
uint16 sr_buffer;
sr_buffer = timer->SR;
+ // Simply switch/case-ing here doesn't work because multiple
+ // CC flags may be high.
if(sr_buffer & 0x10){ // CC4 flag
timer->SR &= ~(0x10);
if(timer1_handlers[3]) {
diff --git a/notes/timers.txt b/notes/timers.txt
index 3e6bb9c..3f5b9f4 100644
--- a/notes/timers.txt
+++ b/notes/timers.txt
@@ -12,54 +12,69 @@ Timer2,Ch 3+4 are D0 and D1, which conflict with Serial2. USART should work
fine as long as pins aren't in output mode? and timers should work fine if
Serial2 isn't in use?
+Caveats
+------------------------------------------------------------------------------
+There are probably subtle bugs with the way register settings get read in; eg,
+it is often required to have the counter fully overflow before new settings
+come into effect?
+Getting really good timing is still an art, not a science here... usually you
+need to fiddle with an oscilloscope and the exact overflow/compare numbers to
+get just the right time values.
+Any other interrupts (SysTick, USB, Serial, etc) can blow away all the nice
+timing stuff.
+
Misc Notes
------------------------------------------------------------------------------
-implementation with case/switch in the interrupt handlers doesn't work; a lot
+Implementation with case/switch in the interrupt handlers doesn't work; a lot
of the time multiple interrupt flags are active at the same time (or become
active?)
TODO
------------------------------------------------------------------------------
+- document carefully (eg, determine clock-wise and overflow-wise behavior for
+ each function)
+- track down and handle all pin conflicts
+- implement the update interrupt as a "5th channel"
+- "pulse in" stuff, both c and c++
- function to read out CCR registers
- allow comparison output to the pin (a la PWM)
- additional modes and configuration (up, down, up/down, etc)
-- Wirish (C++) higher level implementation
-- implement the update interrupt as a "5th channel"
-- track down and handle all pin conflicts
-- document
Possible Wirish implementation
------------------------------------------------------------------------------
-This recent implementation seems pretty clean:
+Inspired by Timer1 Library for arduino
http://arduino.cc/pipermail/developers_arduino.cc/2010-June/002845.html
- class Timer1Class {
- public:
- static void (*isrCompareA)(void);
- static void (*isrCompareB)(void);
-
- static const uint8_t PRESCALE1 = 1;
- static const uint8_t PRESCALE8 = 2;
- static const uint8_t PRESCALE64 = 3;
- static const uint8_t PRESCALE256 = 4;
- static const uint8_t PRESCALE1024 = 5;
+ class HardwareTimer {
- const static uint8_t NORMAL = 0;
- const static uint8_t CTC = 4;
+ public:
- void setPrescaleFactor(uint8_t factor);
- void setMode(uint8_t mode);
- uint16_t read();
- void write(uint16_t val);
- void writeCompareA(uint16_t val);
- void writeCompareB(uint16_t val);
- void attachCompareAInterrupt(void (*f)(void));
- void attachCompareBInterrupt(void (*f)(void));
- void detachCompareAInterrupt();
- void detachCompareBInterrupt();
+ void pause();
+ void resume();
+ void setPrescaleFactor(uint8 factor);
+ void setOverflow(uint16 val); // truncates to overflow
+ void setCount(uint16 val); // truncates to overflow
+ uint16 getCount();
+ uint16 setPeriod(uint32 microseconds); // tries to set prescaler and overflow wisely; returns overflow
+ void setMode(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(void (*f)(void));
+ void attachCompare2Interrupt(void (*f)(void));
+ void attachCompare3Interrupt(void (*f)(void));
+ void attachCompare4Interrupt(void (*f)(void));
+ void detachCompare1Interrupt();
+ void detachCompare2Interrupt();
+ void detachCompare3Interrupt();
+ void detachCompare4Interrupt();
};
- extern Timer1Class Timer1;
+ HardwareTimer Timer1 = HardwareTimer(1);
+ HardwareTimer Timer2 = HardwareTimer(2);
+ HardwareTimer Timer3 = HardwareTimer(3);
+ HardwareTimer Timer4 = HardwareTimer(4);
Here's one of the more standard libaries out there:
http://www.arduino.cc/playground/Code/Timer1
diff --git a/notes/vga.txt b/notes/vga.txt
index 2230f57..d75281a 100644
--- a/notes/vga.txt
+++ b/notes/vga.txt
@@ -1,32 +1,42 @@
-classic digitalWrite() gives ~500ns pulse time (2MHz)
+Notes on GPIO Writing
+------------------------------------------------------------------------------
+Classic digitalWrite() gives ~500ns pulse time (2MHz)
gpio_write_bit() is about 360ns (2.78MHz)
-writing to GPIO?_BASE is about 60ns (16.6MHz -> 18MHz)
+Writing to GPIO?_BASE is about 60ns (16.6MHz -> 18MHz)
-pwm write 0x0001 is about 30ns (33MHz)
+pwm write 0x0001 is about 30ns (33MHz) with prescaler as 1 (default)
pwm write 0x0001 is about 14ns (72MHz) with prescaler as 0 (!)
-1/25.125MHz = 39.72ns
+VGA Timing
+------------------------------------------------------------------------------
+1/25.125MHz = 39.72ns (640x480 pixel clock)
-crude 640x480 directions:
- www.epanorama.net/documents/pc/vga_timing.html
+Crude 640x480 directions:
+ From www.epanorama.net/documents/pc/vga_timing.html
480 lines
31.77 us horizontal line length -> 2287.44 clock cycles -> 2287
3.77 us sync period -> 271 clocks -> 271
1.89 us front porch? -> 136 clocks -> 136
25.17 us video -> 1812.24 clocks -> 1812
- so...
+ So...
2287 reload
271 1: Hsync high
407 2: Video on
2219 3: Video off
2287 4: Hsync low
- vertically, it's
+ Vertically, it's
480 lines active video
11 lines front porch
2 lines Vsync (low)
31 lines back porch
+
+Currently, setting vs. clearing GPIO registers seems to take a different amount
+of time? Or perhaps i'm not analyzing branching correctly. Regardless, if you
+SET 100x times then UNSET on one line, then UNSET 100x then SET the next line,
+the two changes in color will generally not line up.
+
diff --git a/wirish/rules.mk b/wirish/rules.mk
index e74d15d..b2110bd 100644
--- a/wirish/rules.mk
+++ b/wirish/rules.mk
@@ -24,6 +24,7 @@ cppSRCS_$(d) := wirish_math.cpp \
comm/HardwareSerial.cpp \
comm/HardwareSPI.cpp \
usb_serial.cpp \
+ HardwareTimer.cpp \
cxxabi-compat.cpp
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
diff --git a/wirish/wirish.c b/wirish/wirish.c
index 520079c..e21f792 100644
--- a/wirish/wirish.c
+++ b/wirish/wirish.c
@@ -31,17 +31,17 @@
#include "systick.h"
#include "gpio.h"
#include "nvic.h"
-//#include "usb.h"
+#include "usb.h"
void init(void) {
rcc_init();
nvic_init();
-// systick_init();
+ systick_init();
gpio_init();
adc_init();
timer_init(1, 1);
timer_init(2, 1);
timer_init(3, 1);
timer_init(4, 1);
- //setupUSB();
+ setupUSB();
}
diff --git a/wirish/wirish.h b/wirish/wirish.h
index 34464a2..13ff313 100644
--- a/wirish/wirish.h
+++ b/wirish/wirish.h
@@ -43,7 +43,8 @@
#ifdef __cplusplus
#include "HardwareSPI.h"
#include "HardwareSerial.h"
-//#include "usb_serial.h"
+#include "usb_serial.h"
+#include "HardwareTimer.h"
#endif
#ifdef __cplusplus