diff options
Diffstat (limited to 'examples/vga-leaf.cpp')
-rw-r--r-- | examples/vga-leaf.cpp | 162 |
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) { |