aboutsummaryrefslogtreecommitdiffstats
path: root/examples/vga-leaf.cpp
diff options
context:
space:
mode:
authorPerry Hung <iperry@gmail.com>2011-03-09 23:25:03 -0500
committerPerry Hung <iperry@gmail.com>2011-03-09 23:25:03 -0500
commit4651227fa9f7dece1dd24d2170db16c2e35dc04e (patch)
tree7e05d637bdca69811f04d6d55b8cc24b8c9e8cc5 /examples/vga-leaf.cpp
parent07536e9a1a92af2b1bad8f32b1b0f6b868957d26 (diff)
downloadlibrambutan-4651227fa9f7dece1dd24d2170db16c2e35dc04e.tar.gz
librambutan-4651227fa9f7dece1dd24d2170db16c2e35dc04e.zip
Merge refactor into i2c-wip:
Squashed commit of the following: commit 4d6662dadfda7f2fd55107535165dc98a0638a3c Merge: 174d9ab 7ddc844 Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Fri Mar 4 23:18:29 2011 -0500 Merge remote branch 'origin/refactor' into refactor commit 174d9ab73cc3387a3812e6f3d3e97519bf5b2150 Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Fri Mar 4 23:16:53 2011 -0500 USBSerial docs fix. commit f217acb73d94f0a88bf33a42684e6e988dcb3685 Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Fri Mar 4 20:25:26 2011 -0500 Brought examples/ up to date; PIN_MAP bugfix for D24. commit c4ba3ba05fc39ef260cd80d91759966952df74ae Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Fri Mar 4 19:16:42 2011 -0500 Cosmetic/documentation changes to adc.c commit e7747b4eb831621951deef6d31629f55cb5c3500 Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Fri Mar 4 19:16:07 2011 -0500 Cosmetic changes to wirish/main.cxx commit e2f9d4116e59d8487c936989384228ea084a3501 Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Fri Mar 4 19:15:24 2011 -0500 Untabifying docs/source/conf.py commit 7ddc84481b4eebe337065a0219e3d8dc000791e5 Author: Perry Hung <iperry@gmail.com> Date: Wed Mar 2 00:30:19 2011 -0500 cscope: Find .S instead of .s files commit 62cb09ed6357eae58b0234fbc074c44e9c0aa5e5 Author: Marti Bolivar <mbolivar@leaflabs.com> Date: Wed Mar 2 00:07:10 2011 -0500 Fixing typo in main.cpp.example.
Diffstat (limited to 'examples/vga-leaf.cpp')
-rw-r--r--examples/vga-leaf.cpp162
1 files changed, 103 insertions, 59 deletions
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) {