aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/blinky.cpp6
-rw-r--r--examples/debug-dtrrts.cpp23
-rw-r--r--examples/qa-slave-shield.cpp66
-rw-r--r--examples/spi_master.cpp7
-rw-r--r--examples/test-dac.cpp4
-rw-r--r--examples/test-serial-flush.cpp18
-rw-r--r--examples/test-serialusb.cpp74
-rw-r--r--examples/test-session.cpp137
-rw-r--r--examples/test-systick.cpp50
-rw-r--r--examples/test-timers.cpp68
-rw-r--r--examples/vga-leaf.cpp162
-rw-r--r--examples/vga-scope.cpp212
-rw-r--r--wirish/boards.h2
13 files changed, 474 insertions, 355 deletions
diff --git a/examples/blinky.cpp b/examples/blinky.cpp
index 5611987..209a6e6 100644
--- a/examples/blinky.cpp
+++ b/examples/blinky.cpp
@@ -1,4 +1,4 @@
-// Blinks the LED, pin 13
+// Blinks the built-in LED
#include "wirish.h"
@@ -20,8 +20,8 @@ void loop() {
}
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
diff --git a/examples/debug-dtrrts.cpp b/examples/debug-dtrrts.cpp
index f9f8b96..61c061a 100644
--- a/examples/debug-dtrrts.cpp
+++ b/examples/debug-dtrrts.cpp
@@ -1,14 +1,12 @@
-// Sample main.cpp file. Blinks an LED, sends a message out USART2
-// and turns on PWM on pin 2
+// Test sketch for figuring out DTR/RTS behavior on different platforms.
#include "wirish.h"
#include "usb.h"
-#define LED_PIN 13
-#define PWM_PIN 2
+#define LED_PIN BOARD_LED_PIN
+#define PWM_PIN 2
-void setup()
-{
+void setup() {
/* Set up the LED to blink */
pinMode(LED_PIN, OUTPUT);
@@ -18,12 +16,10 @@ void setup()
}
-int toggle = 0;
-
void loop() {
- toggle ^= 1;
- digitalWrite(LED_PIN, toggle);
+ toggleLED();
delay(100);
+
Serial2.print("DTR: ");
Serial2.print(usbGetDTR(), DEC);
Serial2.print("\tRTS: ");
@@ -31,13 +27,12 @@ void loop() {
}
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/qa-slave-shield.cpp b/examples/qa-slave-shield.cpp
index b395cca..5ca451d 100644
--- a/examples/qa-slave-shield.cpp
+++ b/examples/qa-slave-shield.cpp
@@ -1,50 +1,72 @@
-// slave mode for QA shield
+// Slave mode for QA shield
#include "wirish.h"
-#define LED_PIN 13
-#define NUM_GPIO 38 // not the number of the max...
+#define LED_PIN BOARD_LED_PIN
-int i;
+#if defined(BOARD_maple) || defined(BOARD_maple_RET6)
+const uint8 pins_to_skip[] = {LED_PIN};
-void setup()
-{
+#elif defined(BOARD_maple_mini)
+#define USB_DP 23
+#define USB_DM 24
+const uint8 pins_to_skip[] = {LED_PIN, USB_DP, USB_DM};
+
+#elif defined(BOARD_maple_native)
+const uint8 pins_to_skip[] = {LED_PIN};
+
+#else
+#error "Board type has not been selected correctly."
+#endif
+
+bool skip_pin_p(uint8 pin);
+
+void setup() {
/* Set up the LED to blink */
pinMode(LED_PIN, OUTPUT);
- digitalWrite(LED_PIN, 1);
+ digitalWrite(LED_PIN, HIGH);
- for(i=0; i<NUM_GPIO; i++) {
- if(i==13) { continue; }
+ for(int i = 0; i < NR_GPIO_PINS; i++) {
+ if (skip_pin_p(i)) {
+ continue;
+ }
pinMode(i, OUTPUT);
- digitalWrite(i,0);
+ digitalWrite(i, LOW);
}
- //delay(5000);
SerialUSB.println("OK, starting...");
-
}
void loop() {
- digitalWrite(LED_PIN,1);
+ toggleLED();
delay(100);
- digitalWrite(LED_PIN,0);
+ toggleLED();
- for(i=0; i<NUM_GPIO; i++) {
- if(i==13) { continue; }
- digitalWrite(i,1);
+ for(int i = 0; i < NR_GPIO_PINS; i++) {
+ if (skip_pin_p(i)) {
+ continue;
+ }
+ togglePin(i);
delay(5);
- digitalWrite(i,0);
+ togglePin(i);
delay(5);
}
}
+bool skip_pin_p(uint8 pin) {
+ for (uint8 i = 0; i < sizeof(pins_to_skip); i++) {
+ if (pin == pins_to_skip[i])
+ return true;
+ }
+ return false;
+}
+
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/spi_master.cpp b/examples/spi_master.cpp
index 9f6d81b..06cad02 100644
--- a/examples/spi_master.cpp
+++ b/examples/spi_master.cpp
@@ -60,13 +60,12 @@ void loop() {
}
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/test-dac.cpp b/examples/test-dac.cpp
index 3a699e2..6f08b05 100644
--- a/examples/test-dac.cpp
+++ b/examples/test-dac.cpp
@@ -1,8 +1,4 @@
-
#include "wirish.h"
-#include "fsmc.h"
-#include "rcc.h"
-#include "gpio.h"
#include "dac.h"
uint16 count = 0;
diff --git a/examples/test-serial-flush.cpp b/examples/test-serial-flush.cpp
index d7fbf7a..1cd82b6 100644
--- a/examples/test-serial-flush.cpp
+++ b/examples/test-serial-flush.cpp
@@ -2,22 +2,13 @@
#include "wirish.h"
-void setup()
-{
+void setup() {
/* Send a message out USART2 */
Serial2.begin(9600);
Serial2.println("Hello world!");
}
-int toggle = 0;
-
void loop() {
-
- Serial2.println("This is the first line.");
- Serial2.end();
- Serial2.println("This is the second line.");
-
- Serial2.begin(9600);
Serial2.println("Waiting for multiple input...");
while(Serial2.available() < 5) { }
Serial2.println(Serial2.read());
@@ -29,13 +20,12 @@ void loop() {
}
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/test-serialusb.cpp b/examples/test-serialusb.cpp
index 9d0a862..678c2b9 100644
--- a/examples/test-serialusb.cpp
+++ b/examples/test-serialusb.cpp
@@ -1,11 +1,10 @@
-// Sample main.cpp file. Blinks an LED, sends a message out USART2
-// and turns on PWM on pin 2
+// Tests SerialUSB functionality.
#include "wirish.h"
#include "usb.h"
-#define LED_PIN 13
-#define BUT_PIN 38
+#define LED_PIN BOARD_LED_PIN
+#define BUT_PIN BOARD_BUTTON_PIN
uint32 state = 0;
#define QUICKPRINT 0
@@ -14,33 +13,29 @@ uint32 state = 0;
#define SIMPLE 3
#define ONOFF 4
-
-void setup()
-{
+void setup() {
/* Set up the LED to blink */
pinMode(LED_PIN, OUTPUT);
/* Set up the Button */
- pinMode(BUT_PIN, INPUT_PULLUP);
+ pinMode(BUT_PIN, INPUT);
Serial2.begin(9600);
- Serial2.println("Hello world! This is the debug channel.");
-}
+ Serial2.println("This is the debug channel. Press BUT.");
-int toggle = 0;
+ waitForButtonPress(0);
+}
uint8 c1 = '-';
void loop() {
- toggle ^= 1;
- digitalWrite(LED_PIN, toggle);
+ toggleLED();
delay(1000);
- if(digitalRead(BUT_PIN)) {
- while(digitalRead(BUT_PIN)) {};
+ if(isButtonPressed()) {
state++;
}
-
+
switch(state) {
case QUICKPRINT:
for(int i = 0; i<30; i++) {
@@ -48,34 +43,34 @@ void loop() {
SerialUSB.print('.');
SerialUSB.print('|');
}
- Serial2.println(SerialUSB.pending(),DEC);
+ Serial2.println(SerialUSB.pending(), DEC);
SerialUSB.println();
break;
case BIGSTUFF:
- SerialUSB.println("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
- SerialUSB.println((uint32)123456789,DEC);
+ SerialUSB.println("0123456789012345678901234567890123456789"
+ "0123456789012345678901234567890123456789"
+ "012345678901234567890");
+ SerialUSB.println((int64)123456789, DEC);
SerialUSB.println(3.1415926535);
- Serial2.println(SerialUSB.pending(),DEC);
+ Serial2.println(SerialUSB.pending(), DEC);
break;
case NUMBERS:
SerialUSB.println("Numbers! -----------------------------");
Serial2.println("Numbers! -----------------------------");
SerialUSB.println('1');
Serial2.println('1');
- SerialUSB.println(1,DEC);
- Serial2.println(1,DEC);
- SerialUSB.println(-1,DEC);
- Serial2.println(-1,DEC);
+ SerialUSB.println(1, DEC);
+ Serial2.println(1, DEC);
+ SerialUSB.println(-1, DEC);
+ Serial2.println(-1, DEC);
SerialUSB.println(3.14159265);
Serial2.println(3.14159265);
- SerialUSB.println(3.14159265,9);
- Serial2.println(3.14159265,9);
- SerialUSB.println(123456789,DEC);
- Serial2.println(123456789,DEC);
- SerialUSB.println(-123456789,DEC);
- Serial2.println(-123456789,DEC);
- SerialUSB.println(65535,HEX);
- Serial2.println(65535,HEX);
+ SerialUSB.println(123456789, DEC);
+ Serial2.println(123456789, DEC);
+ SerialUSB.println(-123456789, DEC);
+ Serial2.println(-123456789, DEC);
+ SerialUSB.println(65535, HEX);
+ Serial2.println(65535, HEX);
break;
case SIMPLE:
Serial2.println("Trying write('a')");
@@ -92,8 +87,8 @@ void loop() {
SerialUSB.print("hij\n\r");
SerialUSB.write(' ');
SerialUSB.println();
- Serial2.println("Trying println(123456789,DEC)");
- SerialUSB.println(123456789);
+ Serial2.println("Trying println(123456789, DEC)");
+ SerialUSB.println(123456789, DEC);
Serial2.println("Trying println(3.141592)");
SerialUSB.println(3.141592);
Serial2.println("Trying println(\"DONE\")");
@@ -103,12 +98,12 @@ void loop() {
Serial2.println("Shutting down...");
SerialUSB.println("Shutting down...");
SerialUSB.end();
- Serial2.println("Waiting 4seconds...");
+ Serial2.println("Waiting 4 seconds...");
delay(4000);
Serial2.println("Starting up...");
SerialUSB.begin();
SerialUSB.println("Hello World!");
- Serial2.println("Waiting 4seconds...");
+ Serial2.println("Waiting 4 seconds...");
delay(4000);
state++;
break;
@@ -118,13 +113,12 @@ void loop() {
}
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/test-session.cpp b/examples/test-session.cpp
index 7601fab..cf1f4ec 100644
--- a/examples/test-session.cpp
+++ b/examples/test-session.cpp
@@ -20,27 +20,43 @@
int rate = 0;
+#if defined(BOARD_maple) || defined(BOARD_maple_RET6)
+
+#elif defined(BOARD_maple_mini)
+
+#elif defined(BOARD_maple_native)
+const uint8[] pins_to_skip = {LED_PIN};
+
+#else
+#error "Board not selected correctly."
+#endif
+
#if defined(BOARD_maple)
const uint8 pwm_pins[] =
{0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 24, 25, 27, 28};
const uint8 adc_pins[] =
{0, 1, 2, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 27, 28};
+const uint8 pins_to_skip[] = {LED_PIN};
#elif defined(BOARD_maple_mini)
+#define USB_DP 23
+#define USB_DM 24
const uint8 pwm_pins[] = {3, 4, 5, 8, 9, 10, 11, 15, 16, 25, 26, 27};
const uint8 adc_pins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 33}; // NB: 33 is LED
+const uint8 pins_to_skip[] = {LED_PIN, USB_DP, USB_DM};
#elif defined(BOARD_maple_native)
-const uint8 pwm_pins[] = {12, 13, 14, 15, 22, 23, 24, 25, 37, 38, 45,
- 46, 47, 48, 49, 50, 53, 54};
-const uint8 adc_pins[] = {6, 7, 8, 9, 10, 11,
- /* the following are on ADC3, which lacks support:
- 39, 40, 41, 42, 43, 45, */
- 46, 47, 48, 49, 50, 51, 52, 53, 54};
+const uint8 pwm_pins[] = {
+ 12, 13, 14, 15, 22, 23, 24, 25, 37, 38, 45, 46, 47, 48, 49, 50, 53, 54};
+const uint8 adc_pins[] = {
+ 6, 7, 8, 9, 10, 11,
+ /* FIXME These are on ADC3, which lacks support:
+ 39, 40, 41, 42, 43, 45, */
+ 46, 47, 48, 49, 50, 51, 52, 53, 54};
+const uint8 pins_to_skip[] = {LED_PIN};
#else
-#error "Board type has not been selected correctly"
-
+#error "Board type has not been selected correctly."
#endif
uint8 gpio_state[NR_GPIO_PINS];
@@ -62,6 +78,7 @@ void cmd_sequential_pwm_test(void);
void cmd_pwm_sweep(void);
void cmd_servo_sweep(void);
+bool skip_pin_p(uint8 pin);
void measure_adc_noise(uint8 pin);
void fast_gpio(int pin);
void do_serials(HardwareSerial **serials, int n, unsigned baud);
@@ -79,10 +96,10 @@ void setup() {
// Send a message out over COMM interface
COMM.println(" ");
COMM.println(" __ __ _ _ ");
- COMM.println(" | \/ | __ _ _ __ | | ___| |");
- COMM.println(" | |\/| |/ _` | '_ \| |/ _ \ |");
+ COMM.println(" | \\/ | __ _ _ __ | | ___| |");
+ COMM.println(" | |\\/| |/ _` | '_ \\| |/ _ \\ |");
COMM.println(" | | | | (_| | |_) | | __/_|");
- COMM.println(" |_| |_|\__,_| .__/|_|\___(_)");
+ COMM.println(" |_| |_|\\__,_| .__/|_|\\___(_)");
COMM.println(" |_|");
COMM.println(" by leaflabs");
COMM.println("");
@@ -274,7 +291,7 @@ void cmd_print_help(void) {
COMM.println("\tr: Monitor and print GPIO status changes");
COMM.println("\ts: output a sweeping servo PWM on all PWM channels");
COMM.println("\tm: output data on USART1 and USART3 with various rates");
- COMM.println("\t+: test shield mode (for QA, will disrupt Serial2!)");
+ COMM.println("\t+: test shield mode (for QA; will disrupt USARTS)");
COMM.println("Unimplemented:");
COMM.println("\te: do everything all at once until new input");
@@ -294,11 +311,11 @@ void measure_adc_noise(uint8 pin) { // TODO
// variance algorithm from knuth; see wikipedia
// checked against python
- for(int i = 0; i<100; i++) {
+ for(int i = 0; i < 100; i++) {
data[i] = analogRead(pin);
delta = data[i] - mean;
- mean = mean + delta/(i+1);
- M2 = M2 + delta*(data[i] - mean);
+ mean = mean + delta/(i + 1);
+ M2 = M2 + delta * (data[i] - mean);
}
//sqrt is broken?
@@ -313,7 +330,7 @@ void measure_adc_noise(uint8 pin) { // TODO
void cmd_adc_stats(void) {
COMM.println("Taking ADC noise stats...");
digitalWrite(BOARD_LED_PIN, 0);
- for(uint32 i = 0; i<sizeof(adc_pins); i++) {
+ for(uint32 i = 0; i < sizeof(adc_pins); i++) {
delay(5);
measure_adc_noise(adc_pins[i]);
}
@@ -322,21 +339,21 @@ void cmd_adc_stats(void) {
void cmd_stressful_adc_stats(void) {
COMM.println("Taking ADC noise stats under duress...");
digitalWrite(BOARD_LED_PIN, 0);
- for(uint32 i = 0; i<sizeof(adc_pins); i++) {
+ for(uint32 i = 0; i < sizeof(adc_pins); i++) {
// spool up PWM
- for(uint32 j = 2; j<(uint32)sizeof(pwm_pins); j++) {
+ for(uint32 j = 2; j < (uint32)sizeof(pwm_pins); j++) {
if(adc_pins[i] != pwm_pins[j]) {
- pinMode(pwm_pins[j],PWM);
+ pinMode(pwm_pins[j], PWM);
pwmWrite(pwm_pins[j], 1000 + i);
}
}
SerialUSB.print(dummy_dat);
SerialUSB.print(dummy_dat);
measure_adc_noise(adc_pins[i]);
- for(uint32 j = 2; j<(uint32)sizeof(pwm_pins); j++) {
+ for(uint32 j = 2; j < (uint32)sizeof(pwm_pins); j++) {
if(adc_pins[i] != pwm_pins[j]) {
- pinMode(pwm_pins[j],OUTPUT);
- digitalWrite(pwm_pins[j],0);
+ pinMode(pwm_pins[j], OUTPUT);
+ digitalWrite(pwm_pins[j], 0);
}
}
}
@@ -408,12 +425,12 @@ void cmd_gpio_monitoring(void) {
COMM.println("Monitoring GPIO read state changes. Press any key.");
digitalWrite(BOARD_LED_PIN, 0);
// make sure to skip the TX/RX headers
- for(int i = 2; i<NR_GPIO_PINS; i++) {
+ for(int i = 2; i < NR_GPIO_PINS; i++) {
pinMode(i, INPUT_PULLDOWN);
gpio_state[i] = (uint8)digitalRead(i);
}
while(!COMM.available()) {
- for(int i = 2; i<NR_GPIO_PINS; i++) {
+ for(int i = 2; i < NR_GPIO_PINS; i++) {
uint8 current_state = (uint8)digitalRead(i);
if(current_state != gpio_state[i]) {
COMM.print("State change on header D");
@@ -424,7 +441,7 @@ void cmd_gpio_monitoring(void) {
}
}
}
- for(int i = 2; i<NR_GPIO_PINS; i++) {
+ for(int i = 2; i < NR_GPIO_PINS; i++) {
pinMode(i, OUTPUT);
}
}
@@ -434,7 +451,7 @@ void cmd_sequential_adc_reads(void) {
COMM.println("Press any key for next port, or ESC to stop.");
digitalWrite(LED_PIN, 0);
// make sure to skip the TX/RX headers
- for(uint32 i = 2; i<sizeof(adc_pins); i++) {
+ for(uint32 i = 2; i < sizeof(adc_pins); i++) {
COMM.print("Reading on header D");
COMM.print(adc_pins[i], DEC);
COMM.println("...");
@@ -446,13 +463,13 @@ void cmd_sequential_adc_reads(void) {
COMM.print(sample,DEC);
COMM.print("\t");
COMM.print("|");
- for(int j = 0; j<4096; j+= 100) {
+ for(int j = 0; j < 4096; j += 100) {
if(sample >= j) COMM.print("#");
else COMM.print(" ");
}
COMM.print("| ");
- for(int j = 0; j<12; j++) {
- if(sample & (1 << (11-j))) COMM.print("1");
+ for(int j = 0; j < 12; j++) {
+ if(sample & (1 << (11 - j))) COMM.print("1");
else COMM.print("0");
}
COMM.println("");
@@ -466,32 +483,33 @@ void cmd_sequential_adc_reads(void) {
void cmd_gpio_qa(void) {
COMM.println("Doing QA testing for most GPIO pins...");
digitalWrite(BOARD_LED_PIN, 0);
- for(int i = 0; i<NR_GPIO_PINS; i++) {
+ for(int i = 0; i < NR_GPIO_PINS; i++) {
pinMode(i, INPUT);
gpio_state[i] = 0;
}
- COMM.println("Waiting to start...");
+ COMM.println("Waiting to start; press a key.");
while(digitalRead(0) != 1 && !COMM.available()) {
continue;
}
- for(int i=0; i<38; i++) {
- if(i == BOARD_LED_PIN) {
- COMM.println("Not checking LED");
+ for(int i = 0; i < NR_GPIO_PINS; i++) {
+ if(skip_pin_p(i)) {
+ COMM.print("Not checking pin ");
+ COMM.println(i);
continue;
}
- COMM.print("Checking D");
- COMM.print(i,DEC);
+ COMM.print("Checking pin ")
+ COMM.print(i, DEC);
while(digitalRead(i) == 0) continue;
- for(int j=0; j<NR_GPIO_PINS; j++) {
- if(digitalRead(j) && j!=i) {
+ for(int j = 0; j < NR_GPIO_PINS; j++) {
+ if(digitalRead(j) && j != i) {
COMM.print(": FAIL ########################### D");
COMM.println(j, DEC);
break;
}
}
while(digitalRead(i) == 1) continue;
- for(int j=0; j<NR_GPIO_PINS; j++) {
- if(digitalRead(j) && j!=i) {
+ for(int j = 0; j < NR_GPIO_PINS; j++) {
+ if(digitalRead(j) && j != i) {
COMM.print(": FAIL ########################### D");
COMM.println(j, DEC);
break;
@@ -499,18 +517,26 @@ void cmd_gpio_qa(void) {
}
COMM.println(": Ok!");
}
- for(int i = 0; i<NR_GPIO_PINS; i++) {
+ for(int i = 0; i < NR_GPIO_PINS; i++) {
pinMode(i, OUTPUT);
digitalWrite(i, 0);
}
}
+bool skip_pin_p(uint8 pin) {
+ for (uint8 i = 0; i < sizeof(pins_to_skip); i++) {
+ if (pin == pins_to_skip[i])
+ return true;
+ }
+ return false;
+}
+
void cmd_sequential_gpio_writes(void) {
COMM.print("Sequentially toggling all pins except D0, D1. ");
COMM.println("Anything for next, ESC to stop.");
digitalWrite(BOARD_LED_PIN, 0);
// make sure to skip the TX/RX headers
- for(uint32 i = 2; i<NR_GPIO_PINS; i++) {
+ for(uint32 i = 2; i < NR_GPIO_PINS; i++) {
COMM.print("GPIO write out on header D");
COMM.print((int)i, DEC);
COMM.println("...");
@@ -527,15 +553,15 @@ void cmd_gpio_toggling(void) {
COMM.println("Toggling all GPIOs simultaneously. Press any key.");
digitalWrite(BOARD_LED_PIN, 0);
// make sure to skip the TX/RX headers
- for(uint32 i = 2; i<NR_GPIO_PINS; i++) {
+ for(uint32 i = 2; i < NR_GPIO_PINS; i++) {
pinMode(i, OUTPUT);
}
while(!COMM.available()) {
- for(uint32 i = 2; i<NR_GPIO_PINS; i++) {
+ for(uint32 i = 2; i < NR_GPIO_PINS; i++) {
togglePin(i);
}
}
- for(uint32 i = 2; i<NR_GPIO_PINS; i++) {
+ for(uint32 i = 2; i < NR_GPIO_PINS; i++) {
digitalWrite(i, 0);
}
}
@@ -546,7 +572,7 @@ void cmd_sequential_pwm_test(void) {
COMM.println("Press any key for next, ESC to stop.");
digitalWrite(BOARD_LED_PIN, 0);
// make sure to skip the TX/RX headers
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
COMM.print("PWM out on header D");
COMM.print(pwm_pins[i], DEC);
COMM.println("...");
@@ -563,19 +589,19 @@ void cmd_pwm_sweep(void) {
COMM.println("Testing all PWM ports with a sweep. Press any key.");
digitalWrite(BOARD_LED_PIN, 0);
// make sure to skip the TX/RX pins
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
pinMode(pwm_pins[i], PWM);
pwmWrite(pwm_pins[i], 4000);
}
while(!COMM.available()) {
rate += 20;
if(rate > 65500) rate = 0;
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
pwmWrite(pwm_pins[i], rate);
}
delay(1);
}
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
pinMode(pwm_pins[i], OUTPUT);
}
}
@@ -586,7 +612,7 @@ void cmd_servo_sweep(void) {
digitalWrite(BOARD_LED_PIN, 0);
init_all_timers(21);
// make sure to skip the TX/RX headers
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
pinMode(pwm_pins[i], PWM);
pwmWrite(pwm_pins[i], 4000);
}
@@ -597,12 +623,12 @@ void cmd_servo_sweep(void) {
while(!COMM.available()) {
rate += 20;
if(rate > 5734) rate = 4096;
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
pwmWrite(pwm_pins[i], rate);
}
delay(20);
}
- for(uint32 i = 2; i<sizeof(pwm_pins); i++) {
+ for(uint32 i = 2; i < sizeof(pwm_pins); i++) {
pinMode(pwm_pins[i], OUTPUT);
}
init_all_timers(1);
@@ -626,13 +652,12 @@ void init_all_timers(uint16 prescale) {
// Force init to be called *first*, i.e. before static object allocation.
-// Otherwise, statically allocated object that need libmaple may fail.
-__attribute__(( constructor )) void premain() {
+// Otherwise, statically allocated objects that need libmaple may fail.
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/test-systick.cpp b/examples/test-systick.cpp
index 247892d..c7b5529 100644
--- a/examples/test-systick.cpp
+++ b/examples/test-systick.cpp
@@ -3,54 +3,48 @@
#include "wirish.h"
#include "systick.h"
-#define LED_PIN 13
-#define PWM_PIN 2
-#define BUT 38
+#define LED_PIN BOARD_LED_PIN
+#define PWM_PIN 2
+#define BUT BOARD_BUTTON_PIN
-void setup()
-{
+void setup() {
/* Set up the LED to blink */
pinMode(LED_PIN, OUTPUT);
-
- /* Turn on PWM on pin PWM_PIN */
- pinMode(PWM_PIN, PWM);
- pwmWrite(PWM_PIN, 0x8000);
-
- pinMode(BUT, INPUT_PULLDOWN);
+ pinMode(BUT, INPUT);
}
-int toggle = 0;
+bool disable = true;
long time = 0;
void loop() {
- toggle ^= 1;
- digitalWrite(LED_PIN, toggle);
+ volatile int i = 0;
+ toggleLED();
// An artificial delay
- int16 i = 1;
- float j = 1;
- for(i=0; i<6553; i++) {
- j = sqrt(j) + 1;
- }
-
- if(digitalRead(BUT)) {
- systick_disable();
- } else {
- systick_resume();
+ for(i = 0; i < 150000; i++)
+ ;
+
+ if(isButtonPressed()) {
+ if (disable) {
+ systick_disable();
+ SerialUSB.println("Disabling SysTick");
+ } else {
+ SerialUSB.println("Re-enabling SysTick");
+ systick_resume();
+ }
+ disable = !disable;
}
- //SerialUSB.println(micros()); // there is a bug with this
SerialUSB.println(millis());
}
// Force init to be called *first*, i.e. before static object allocation.
// Otherwise, statically allocated object that need libmaple may fail.
- __attribute__(( constructor )) void premain() {
+__attribute__((constructor)) void premain() {
init();
}
-int main(void)
-{
+int main(void) {
setup();
while (1) {
diff --git a/examples/test-timers.cpp b/examples/test-timers.cpp
index ccba251..f3cfdcc 100644
--- a/examples/test-timers.cpp
+++ b/examples/test-timers.cpp
@@ -2,7 +2,7 @@
#include "wirish.h"
-#define LED_PIN 13
+#define LED_PIN BOARD_LED_PIN
void handler1(void);
void handler2(void);
@@ -12,7 +12,6 @@ void handler4(void);
void handler3b(void);
void handler4b(void);
-int toggle = 0;
int t;
int count1 = 0;
@@ -36,25 +35,24 @@ void setup()
pinMode(LED_PIN, OUTPUT);
// Setup the button as input
- pinMode(38, INPUT_PULLUP);
+ pinMode(BOARD_BUTTON_PIN, INPUT);
- /* Send a message out USART2 */
- //SerialUSB.begin(9600);
- SerialUSB.println("Begining timer test...");
+ // Wait for user to attach...
+ waitForButtonPress(0);
+
+ // Send a message out SerialUSB
+ SerialUSB.println("Beginning timer test...");
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);
}
-
- // Wait for user to attach...
- delay(2000);
}
void loop() {
SerialUSB.println("-----------------------------------------------------");
- SerialUSB.println("Testing setCount/getCount");
+ SerialUSB.println("Testing setCount/getCount");
SerialUSB.print("Timer1.getCount() = "); SerialUSB.println(Timer1.getCount());
SerialUSB.println("Timer1.setCount(1234)");
Timer1.setCount(1234);
@@ -63,7 +61,7 @@ void loop() {
// down Timer4 is in the "pause" state and the timer doesn't increment, so
// the final counts should reflect the ratio of time that BUT was held down
SerialUSB.println("-----------------------------------------------------");
- SerialUSB.println("Testing Pause/Resume; button roughly controls Timer4");
+ SerialUSB.println("Testing Pause/Resume; button roughly controls Timer4");
count3 = 0;
count4 = 0;
Timer3.setChannel1Mode(TIMER_OUTPUTCOMPARE);
@@ -80,9 +78,9 @@ void loop() {
Timer4.attachCompare1Interrupt(handler4b);
Timer3.resume();
Timer4.resume();
- SerialUSB.println("~4 seconds...");
+ SerialUSB.println("~4 seconds...");
for(int i = 0; i<4000; i++) {
- if(digitalRead(38)) {
+ if(isButtonPressed()) {
Timer4.pause();
} else {
Timer4.resume();
@@ -96,14 +94,14 @@ void loop() {
// These test the setPeriod auto-configure functionality
SerialUSB.println("-----------------------------------------------------");
- SerialUSB.println("Testing setPeriod");
+ SerialUSB.println("Testing setPeriod");
Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer4.setCompare1(1);
- Timer4.setPeriod(10);
+ Timer4.setPeriod(10);
Timer4.pause();
Timer4.setCount(0);
Timer4.attachCompare1Interrupt(handler4b);
- SerialUSB.println("Period 10ms, wait 2 seconds...");
+ SerialUSB.println("Period 10ms, wait 2 seconds...");
count4 = 0;
Timer4.resume();
delay(2000);
@@ -114,10 +112,10 @@ void loop() {
Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer4.setCompare1(1);
Timer4.pause();
- Timer4.setPeriod(30000);
+ Timer4.setPeriod(30000);
Timer4.setCount(0);
Timer4.attachCompare1Interrupt(handler4b);
- SerialUSB.println("Period 30000ms, wait 2 seconds...");
+ SerialUSB.println("Period 30000ms, wait 2 seconds...");
count4 = 0;
Timer4.resume();
delay(2000);
@@ -127,12 +125,12 @@ void loop() {
SerialUSB.println("(should be around 2sec/30000ms ~ 67)");
Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
- Timer4.setPeriod(300000);
+ Timer4.setPeriod(300000);
Timer4.setCompare1(1);
Timer4.pause();
Timer4.setCount(0);
Timer4.attachCompare1Interrupt(handler4b);
- SerialUSB.println("Period 300000ms, wait 2 seconds...");
+ SerialUSB.println("Period 300000ms, wait 2 seconds...");
count4 = 0;
Timer4.resume();
delay(2000);
@@ -146,9 +144,9 @@ void loop() {
Timer4.setOverflow(65454);
Timer4.pause();
Timer4.setCount(0);
- Timer4.setCompare1(1);
+ Timer4.setCompare1(1);
Timer4.attachCompare1Interrupt(handler4b);
- SerialUSB.println("Period 30000ms, wait 2 seconds...");
+ SerialUSB.println("Period 30000ms, wait 2 seconds...");
count4 = 0;
Timer4.resume();
delay(2000);
@@ -159,11 +157,11 @@ void loop() {
Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer4.setCompare1(1);
- Timer4.setPeriod(30000);
+ Timer4.setPeriod(30000);
Timer4.pause();
Timer4.setCount(0);
Timer4.attachCompare1Interrupt(handler4b);
- SerialUSB.println("Period 30000ms, wait 2 seconds...");
+ SerialUSB.println("Period 30000ms, wait 2 seconds...");
count4 = 0;
Timer4.resume();
delay(2000);
@@ -177,7 +175,7 @@ void loop() {
// that over time the actual timing rates get blown away by other system
// interrupts.
for(t=0; t<4; t++) {
- toggle ^= 1; digitalWrite(LED_PIN, toggle);
+ toggleLED();
delay(100);
SerialUSB.println("-----------------------------------------------------");
SerialUSB.print("Testing Timer "); SerialUSB.println(t+1);
@@ -214,33 +212,39 @@ void handler1(void) {
val1 += rate1;
Timers[t].setCompare1(val1);
count1++;
-}
+}
+
void handler2(void) {
val2 += rate2;
Timers[t].setCompare2(val2);
count2++;
-}
+}
+
void handler3(void) {
val3 += rate3;
Timers[t].setCompare3(val3);
count3++;
-}
+}
+
void handler4(void) {
val4 += rate4;
Timers[t].setCompare4(val4);
count4++;
-}
+}
void handler3b(void) {
count3++;
-}
+}
+
void handler4b(void) {
count4++;
-}
+}
+__attribute__((constructor)) void premain() {
+ init();
+}
int main(void) {
- init();
setup();
while (1) {
diff --git a/examples/vga-leaf.cpp b/examples/vga-leaf.cpp
index d1c6d7d..9d9fce2 100644
--- a/examples/vga-leaf.cpp
+++ b/examples/vga-leaf.cpp
@@ -1,21 +1,21 @@
/*
- Crude VGA Output
+ VGA Output
- Outputs a red and white leaf to VGA. This implementation is crude and noisy,
- but a fun demo. It should run most VGA monitors at 640x480, though it does
- not follow the timing spec very carefully. Real twisted or shielded wires,
- proper grounding, and not doing this on a breadboard are recommended (but
- it seems to work ok without).
+ Outputs a red and white leaf to VGA. It should run most VGA monitors
+ at 640x480, though it does not follow the timing spec very
+ carefully. Real twisted or shielded wires, proper grounding, and not
+ doing this on a breadboard are recommended (but it seems to work ok
+ without).
- SerialUSB is disabled to get rid of most interrupts (which mess with timing);
- the SysTick is probably the source of the remaining flickers. This means that
- you have to use perpetual bootloader or the reset button to flash new
- programs.
+ SerialUSB and SysTick are disabled to get rid of the most frequently
+ occurring interrupts (which mess with timing). This means that you
+ have to use perpetual bootloader mode or the reset button to flash
+ new programs.
How to wire this to a VGA port:
- D5 via ~200ohms to VGA Red (1)
- D6 via ~200ohms to VGA Green (2)
- D7 via ~200ohms to VGA Blue (3)
+ D6 via ~200ohms to VGA Red (1)
+ D7 via ~200ohms to VGA Green (2)
+ D8 via ~200ohms to VGA Blue (3)
D11 to VGA VSync (14) (swapped?)
D12 to VGA HSync (13) (swapped?)
GND to VGA Ground (5)
@@ -24,48 +24,71 @@
See also:
- http://pinouts.ru/Video/VGA15_pinout.shtml
- http://www.epanorama.net/documents/pc/vga_timing.html
-
+
Created 20 July 2010
By Bryan Newbold for LeafLabs
This code is released with no strings attached.
-
+
+ Modified 4 March 2011
+ By Marti Bolivar
+ Disabled SysTick, kept up-to-date with libmaple.
*/
+// FIXME: generalize for Native and Mini
+
#include "wirish.h"
-#define LED_PIN 13
+#define LED_PIN BOARD_LED_PIN
-// Pinouts
-#define VGA_R 5 // STM32: B6
-#define VGA_G 6 // STM32: A8
-#define VGA_B 7 // STM32: A9
+// Pinouts -- you also must change the GPIO macros below if you change
+// these
+#define VGA_R 6 // STM32: A8
+#define VGA_G 7 // STM32: A9
+#define VGA_B 8 // STM32: A10
#define VGA_V 11 // STM32: A6
#define VGA_H 12 // STM32: A7
-// These low level macros make GPIO writes much faster
-#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)
-#define VGA_G_LOW (GPIOA_BASE)->BRR = BIT(8)
-#define VGA_B_HIGH (GPIOA_BASE)->BSRR = BIT(9)
-#define VGA_B_LOW (GPIOA_BASE)->BRR = BIT(9)
-#define VGA_V_HIGH (GPIOA_BASE)->BSRR = BIT(6)
-#define VGA_V_LOW (GPIOA_BASE)->BRR = BIT(6)
-#define VGA_H_HIGH (GPIOA_BASE)->BSRR = BIT(7)
-#define VGA_H_LOW (GPIOA_BASE)->BRR = BIT(7)
+// These low level (and STM32 specific) macros make GPIO writes much
+// faster
+#define ABSRR ((volatile uint32*)0x40010810)
+#define ABRR ((volatile uint32*)0x40010814)
+
+#define RBIT 8 // (see pinouts)
+#define GBIT 9
+#define BBIT 10
+
+#define VGA_R_HIGH *ABSRR = BIT(RBIT)
+#define VGA_R_LOW *ABRR = BIT(RBIT)
+#define VGA_G_HIGH *ABSRR = BIT(GBIT)
+#define VGA_G_LOW *ABRR = BIT(GBIT)
+#define VGA_B_HIGH *ABSRR = BIT(BBIT)
+#define VGA_B_LOW *ABRR = BIT(BBIT)
+
+#define ON_COLOR BIT(RBIT)
+#define OFF_COLOR (BIT(RBIT) | BIT(GBIT) | BIT(BBIT))
+
+// set has priority, so clear every bit and set some given bits:
+#define VGA_COLOR(c) (*ABSRR = c | \
+ BIT(RBIT+16) | BIT(GBIT+16) | BIT(BBIT+16))
+
+#define VGA_V_HIGH *ABSRR = BIT(6)
+#define VGA_V_LOW *ABRR = BIT(6)
+#define VGA_H_HIGH *ABSRR = BIT(7)
+#define VGA_H_LOW *ABRR = BIT(7)
void isr_porch(void);
void isr_start(void);
void isr_stop(void);
void isr_update(void);
-uint8 toggle;
uint16 x = 0; // X coordinate
uint16 y = 0; // Y coordinate
-uint8 v_active = 1; // Are we in the image?
+uint16 logo_y = 0; // Y coordinate, mapped into valid logo index (for speed)
+bool v_active = true; // Are we in the image?
-// 1-bit!
-uint8 logo[18][16] = {
+const uint8 x_max = 16;
+const uint8 y_max = 18;
+uint32 logo[y_max][x_max] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,},
{0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,},
@@ -99,9 +122,20 @@ void setup() {
digitalWrite(VGA_H, HIGH);
digitalWrite(VGA_V, HIGH);
+ // Fill the logo array with color patterns corresponding to its
+ // truth value. Note that we could get more tricky here, since
+ // there are 3 bits of color.
+ for (int y = 0; y < y_max; y++) {
+ for (int x = 0; x < x_max; x++) {
+ logo[y][x] = logo[y][x] ? ON_COLOR : OFF_COLOR;
+ }
+ }
+
// This gets rid of the majority of the interrupt artifacts;
+ // there's still a glitch for low values of y, but let's not worry
+ // about that. (Probably due to the hackish way vsync is done).
SerialUSB.end();
- SystemTick.end();
+ systick_disable();
// Configure
Timer4.pause(); // while we configure
@@ -120,14 +154,13 @@ void setup() {
Timer4.attachCompare3Interrupt(isr_stop);
Timer4.setCompare4(1); // Could be zero I guess
Timer4.attachCompare4Interrupt(isr_update);
-
+
Timer4.setCount(0); // Ready...
Timer4.resume(); // Go!
}
void loop() {
- toggle ^= 1;
- digitalWrite(LED_PIN, toggle);
+ toggleLED();
delay(100);
// Everything happens in the interrupts!
@@ -139,51 +172,59 @@ void loop() {
void isr_porch(void) {
VGA_H_HIGH;
y++;
+ logo_y = map(y, 0, 478, 0, y_max);
// Back to the top
- if(y>=523) {
- y=1;
- v_active = 1;
+ if(y >= 523) {
+ y = 1;
+ logo_y = 0;
+ v_active = true;
return;
}
// Other vsync stuff below the image
- if(y>=492) {
+ if(y >= 492) {
VGA_V_HIGH;
return;
}
- if(y>=490) {
+ if(y >= 490) {
VGA_V_LOW;
return;
}
- if(y>=479) {
- v_active = 0;
+ if(y >= 479) {
+ v_active = false;
return;
}
}
// This is the main horizontal sweep
-void isr_start(void) {
+void isr_start(void) {
// Skip if we're not in the image at all
- if(!v_active) { return; }
+ if (!v_active) {
+ return;
+ }
// Start Red
VGA_R_LOW;
VGA_R_HIGH;
- // For each "pixel" (really 20 or so screen pixels?) go red or white
- for(x=0; x<32; x++) {
- if(logo[y/28][x/2]) {
- VGA_G_HIGH;
- VGA_B_HIGH;
- } else {
- VGA_G_LOW;
- VGA_B_LOW;
- }
+ // For each "pixel", go ON_COLOR or OFF_COLOR
+ for(x = 0; x < 16; x++) {
+ // setting the color several times is just an easy way to
+ // delay, so the image is wider. if you only do the following
+ // once, you'll be able to make the logo array a lot wider:
+ VGA_COLOR(logo[logo_y][x]);
+ VGA_COLOR(logo[logo_y][x]);
+ VGA_COLOR(logo[logo_y][x]);
+ VGA_COLOR(logo[logo_y][x]);
+ VGA_COLOR(logo[logo_y][x]);
+ VGA_COLOR(logo[logo_y][x]);
}
}
// End of the horizontal line
void isr_stop(void) {
- if(!v_active) { return; }
+ if (!v_active) {
+ return;
+ }
VGA_R_LOW;
VGA_G_LOW;
VGA_B_LOW;
@@ -194,8 +235,11 @@ void isr_update(void) {
VGA_H_LOW;
}
-int main(void) {
+__attribute__((constructor)) void premain() {
init();
+}
+
+int main(void) {
setup();
while (1) {
diff --git a/examples/vga-scope.cpp b/examples/vga-scope.cpp
index 0265f9c..9c6dca5 100644
--- a/examples/vga-scope.cpp
+++ b/examples/vga-scope.cpp
@@ -1,34 +1,90 @@
-// Low-level, non-wirish demonstration of VGA
-//
-// Connect a microphone or something less to ANALOG_PIN
+/*
+ VGA Oscilloscope demo.
+
+ Connect a microphone or something like it to ANALOG_PIN (0V -- 3.3V
+ only; 0.2V -- 3.1V will probably look nicer); an attached VGA
+ monitor will display the signal roughly in real-time.
+
+ The thick blue line corresponds roughly to 0V.
+
+ This is a fairy crude hack, but it's fun to watch/toy around with.
+
+ SerialUSB and SysTick are disabled to get rid of the most frequently
+ occurring interrupts (which mess with timing). This means that you
+ have to use perpetual bootloader mode or the reset button to flash
+ new programs.
+
+ How to wire this to a VGA port:
+ D6 via ~200ohms to VGA Red (1)
+ D7 via ~200ohms to VGA Green (2)
+ D8 via ~200ohms to VGA Blue (3)
+ D11 to VGA VSync (14) (swapped?)
+ D12 to VGA HSync (13) (swapped?)
+ GND to VGA Ground (5)
+ GND to VGA Sync Ground (10)
+
+ See also:
+ - http://pinouts.ru/Video/VGA15_pinout.shtml
+ - http://www.epanorama.net/documents/pc/vga_timing.html
+
+ This code is released into the public domain.
+ */
#include "wirish.h"
+#include "systick.h"
+
+// FIXME generalize for Native and Mini
-#define LED_PIN 13
+#define LED_PIN BOARD_LED_PIN
#define ANALOG_PIN 18
-#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)
-#define VGA_G_LOW (GPIOA_BASE)->BRR = BIT(8)
-#define VGA_B_HIGH (GPIOA_BASE)->BSRR = BIT(9)
-#define VGA_B_LOW (GPIOA_BASE)->BRR = BIT(9)
-#define VGA_V_HIGH (GPIOA_BASE)->BSRR = BIT(6)
-#define VGA_V_LOW (GPIOA_BASE)->BRR = BIT(6)
-#define VGA_H_HIGH (GPIOA_BASE)->BSRR = BIT(7)
-#define VGA_H_LOW (GPIOA_BASE)->BRR = BIT(7)
+
+// Pinouts -- you also must change the GPIO macros below if you change
+// these
+#define VGA_R 6 // STM32: A8
+#define VGA_G 7 // STM32: A9
+#define VGA_B 8 // STM32: A10
+#define VGA_V 11 // STM32: A6
+#define VGA_H 12 // STM32: A7
+
+// These low level (and STM32 specific) macros make GPIO writes much
+// faster
+#define ABSRR ((volatile uint32*)0x40010810)
+#define ABRR ((volatile uint32*)0x40010814)
+
+#define RBIT 8 // (see pinouts)
+#define GBIT 9
+#define BBIT 10
+
+#define VGA_R_HIGH *ABSRR = BIT(RBIT)
+#define VGA_R_LOW *ABRR = BIT(RBIT)
+#define VGA_G_HIGH *ABSRR = BIT(GBIT)
+#define VGA_G_LOW *ABRR = BIT(GBIT)
+#define VGA_B_HIGH *ABSRR = BIT(BBIT)
+#define VGA_B_LOW *ABRR = BIT(BBIT)
+
+#define COLOR_WHITE (BIT(RBIT) | BIT(GBIT) | BIT(BBIT))
+#define COLOR_BLACK 0
+#define COLOR_RED BIT(RBIT)
+#define COLOR_GREEN BIT(GBIT)
+#define COLOR_BLUE BIT(BBIT)
+
+#define BORDER_COLOR COLOR_BLUE
+
+// set has priority, so clear every bit and set some given bits:
+#define VGA_COLOR(c) (*ABSRR = c | \
+ BIT(RBIT+16) | BIT(GBIT+16) | BIT(BBIT+16))
+
+#define VGA_V_HIGH *ABSRR = BIT(6)
+#define VGA_V_LOW *ABRR = BIT(6)
+#define VGA_H_HIGH *ABSRR = BIT(7)
+#define VGA_H_LOW *ABRR = BIT(7)
void isr_porch(void);
void isr_start(void);
void isr_stop(void);
void isr_update(void);
-void setup()
-{
+void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(ANALOG_PIN, INPUT_ANALOG);
digitalWrite(LED_PIN, 1);
@@ -38,104 +94,104 @@ void setup()
pinMode(VGA_V, OUTPUT);
pinMode(VGA_H, OUTPUT);
- /* Send a message out USART2 */
+ // Send a message out USART2
Serial2.begin(9600);
- Serial2.println("Video time...");
+ Serial2.println("Time to kill the radio star...");
// This gets rid of the majority of the interrupt artifacts;
- // a SysTick.end() is required as well
+ // there's still a glitch for low values of y, but let's not worry
+ // about that. (Probably due to the hackish way vsync is done).
SerialUSB.end();
-
+ systick_disable();
+
digitalWrite(VGA_R, 0);
digitalWrite(VGA_G, 0);
digitalWrite(VGA_B, 0);
- digitalWrite(VGA_H,1);
- digitalWrite(VGA_V,1);
-
- timer_set_prescaler(4,0);
- timer_set_mode(4, 1, TIMER_OUTPUTCOMPARE);
- timer_set_mode(4, 2, TIMER_OUTPUTCOMPARE);
- timer_set_mode(4, 3, TIMER_OUTPUTCOMPARE);
- timer_set_mode(4, 4, TIMER_OUTPUTCOMPARE);
- timer_set_reload(4, 2287);
- timer_set_compare_value(4,1,200);
- timer_set_compare_value(4,2,300);
- timer_set_compare_value(4,3,2170); // 2219 max...
- timer_set_compare_value(4,4,1);
- timer_attach_interrupt(4,1,isr_porch);
- timer_attach_interrupt(4,2,isr_start);
- timer_attach_interrupt(4,3,isr_stop);
- timer_attach_interrupt(4,4,isr_update);
-
- timer_set_count(4,0);
+ digitalWrite(VGA_H, 1);
+ digitalWrite(VGA_V, 1);
+
+ timer_pause(TIMER4);
+ timer_set_prescaler(TIMER4, 0);
+ timer_set_mode(TIMER4, 1, TIMER_OUTPUTCOMPARE);
+ timer_set_mode(TIMER4, 2, TIMER_OUTPUTCOMPARE);
+ timer_set_mode(TIMER4, 3, TIMER_OUTPUTCOMPARE);
+ timer_set_mode(TIMER4, 4, TIMER_OUTPUTCOMPARE);
+ timer_set_reload(TIMER4, 2287);
+ timer_set_compare_value(TIMER4, 1, 200);
+ timer_set_compare_value(TIMER4, 2, 250);
+ timer_set_compare_value(TIMER4, 3, 2170); // 2219 max...
+ timer_set_compare_value(TIMER4, 4, 1);
+ timer_attach_interrupt(TIMER4, 1, isr_porch);
+ timer_attach_interrupt(TIMER4, 2, isr_start);
+ timer_attach_interrupt(TIMER4, 3, isr_stop);
+ timer_attach_interrupt(TIMER4, 4, isr_update);
+
+ timer_set_count(TIMER4, 0);
+ timer_resume(TIMER4);
}
-int toggle = 0;
-uint16 x = 0;
uint16 y = 0;
uint16 val = 0;
-uint8 v_active = 1;
-GPIO_Port *portb = GPIOB_BASE;
+bool v_active = true;
+const uint16 x_max = 60; // empirically (and lazily) determined
void isr_porch(void) {
VGA_H_HIGH;
y++;
- if(y>=523) {
- y=1;
- v_active = 1;
+ val = map(analogRead(ANALOG_PIN), 0, 4095, 0, x_max);
+ if(y >= 523) {
+ y = 1;
+ v_active = true;
return;
}
- if(y>=492) {
+ if(y >= 492) {
VGA_V_HIGH;
return;
}
- if(y>=490) {
+ if(y >= 490) {
VGA_V_LOW;
return;
}
- if(y>=479) { // 479
- v_active = 0;
+ if(y >= 479) {
+ v_active = false;
return;
}
}
void isr_start(void) {
- if(!v_active) { return; }
- VGA_R_HIGH;
- VGA_R_HIGH;
- VGA_R_HIGH;
- VGA_R_LOW;
- //delayMicroseconds(2);
- //gpio_write_bit(GPIOA_BASE, 8, 1); // VGA_G
- for(x=0; x<(val>>6); x++) {
- }
- VGA_B_HIGH;
- VGA_G_HIGH;
- VGA_G_LOW;
- VGA_B_LOW;
- //VGA_R_HIGH;
- //val = (val + analogRead(ANALOG_PIN))/2;
- val = analogRead(ANALOG_PIN);
-
+ if (!v_active) {
+ return;
+ }
+ VGA_COLOR(BORDER_COLOR);
+ for (int x = 0; x < val; x++) {
+ VGA_COLOR(COLOR_BLACK);
+ }
+ VGA_COLOR(COLOR_WHITE);
+ VGA_COLOR(COLOR_BLACK);
}
+
void isr_stop(void) {
- if(!v_active) { return; }
- VGA_R_LOW;
- VGA_G_LOW;
- VGA_B_LOW;
+ if (!v_active) {
+ return;
+ }
+ VGA_COLOR(COLOR_BLACK);
}
+
void isr_update(void) {
VGA_H_LOW;
}
void loop() {
- //val = analogRead(ANALOG_PIN);
+ toggleLED();
+ delay(100);
}
+__attribute__((constructor)) void premain() {
+ init();
+}
int main(void) {
- init();
setup();
while (1) {
diff --git a/wirish/boards.h b/wirish/boards.h
index f8505ab..ecb5f69 100644
--- a/wirish/boards.h
+++ b/wirish/boards.h
@@ -134,7 +134,7 @@ typedef struct PinMapping {
/* D23/PC15 */
{GPIOC_BASE, 15, ADC_INVALID, 0, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D24/PB9 */
- {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
+ {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB, TIMER4, 4},
/* D25/PD2 */
{GPIOD_BASE, 2, ADC_INVALID, 0, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
/* D26/PC10 */