aboutsummaryrefslogtreecommitdiffstats
path: root/examples/vga-leaf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/vga-leaf.cpp')
-rw-r--r--examples/vga-leaf.cpp162
1 files changed, 59 insertions, 103 deletions
diff --git a/examples/vga-leaf.cpp b/examples/vga-leaf.cpp
index 9d9fce2..d1c6d7d 100644
--- a/examples/vga-leaf.cpp
+++ b/examples/vga-leaf.cpp
@@ -1,21 +1,21 @@
/*
- VGA Output
+ Crude VGA Output
- 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).
+ 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).
- 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.
+ 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.
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)
+ D5 via ~200ohms to VGA Red (1)
+ D6 via ~200ohms to VGA Green (2)
+ D7 via ~200ohms to VGA Blue (3)
D11 to VGA VSync (14) (swapped?)
D12 to VGA HSync (13) (swapped?)
GND to VGA Ground (5)
@@ -24,71 +24,48 @@
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 BOARD_LED_PIN
+#define LED_PIN 13
-// 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
+// Pinouts
+#define VGA_R 5 // STM32: B6
+#define VGA_G 6 // STM32: A8
+#define VGA_B 7 // STM32: A9
#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 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)
+// 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)
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
-uint16 logo_y = 0; // Y coordinate, mapped into valid logo index (for speed)
-bool v_active = true; // Are we in the image?
+uint8 v_active = 1; // Are we in the image?
-const uint8 x_max = 16;
-const uint8 y_max = 18;
-uint32 logo[y_max][x_max] = {
+// 1-bit!
+uint8 logo[18][16] = {
{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,},
@@ -122,20 +99,9 @@ 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();
- systick_disable();
+ SystemTick.end();
// Configure
Timer4.pause(); // while we configure
@@ -154,13 +120,14 @@ 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() {
- toggleLED();
+ toggle ^= 1;
+ digitalWrite(LED_PIN, toggle);
delay(100);
// Everything happens in the interrupts!
@@ -172,59 +139,51 @@ 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;
- logo_y = 0;
- v_active = true;
+ if(y>=523) {
+ y=1;
+ v_active = 1;
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 = false;
+ if(y>=479) {
+ v_active = 0;
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", 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]);
+ // 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;
+ }
}
}
// 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;
@@ -235,11 +194,8 @@ void isr_update(void) {
VGA_H_LOW;
}
-__attribute__((constructor)) void premain() {
- init();
-}
-
int main(void) {
+ init();
setup();
while (1) {