954f9e5065
Move libmaple/*.h to (new) libmaple/include/libmaple/. The new accepted way to include a libmaple header foo.h is with: #include <libmaple/foo.h> This is more polite in terms of the include namespace. It also allows us to e.g. implement the Arduino SPI library at all (which has header SPI.h; providing it was previously impossible on case-insensitive filesystems due to libmaple's spi.h). Similarly for Wirish. The old include style (#include "header.h") is now deprecated. libmaple/*.h: - Change include guard #defines from _FOO_H_ to _LIBMAPLE_FOO_H_. - Add license headers where they're missing - Add conditional extern "C" { ... } blocks where they're missing (they aren't always necessary, but we might was well do it against the future, while we're at it.). - Change includes from #include "foo.h" to #include <libmaple/foo.h>. - Move includes after extern "C". - Remove extra trailing newlines Note that this doesn't include the headers under libmaple/usb/ or libmaple/usb/usb_lib. These will get fixed later. libmaple/*.c: - Change includes from #include "foo.h" to #include <libmaple/foo.h>. Makefile: - Add I$(LIBMAPLE_PATH)/include/libmaple to GLOBAL_FLAGS. This allows for users (including Wirish) to migrate their code, but should go away ASAP, since it slows down compilation. Wirish: - Move wirish/**/*.h to (new) wirish/include/wirish/. This ignores the USB headers, which, as usual, are getting handled after everything else. - Similarly generify wirish/boards/ structure. For each supported board "foo", move wirish/boards/foo.h and wirish/boards/foo.cpp to wirish/boards/foo/include/board/board.h and wirish/boards/foo/board.cpp, respectively. Also remove the #ifdef hacks around the .cpp files. - wirish/rules.mk: put wirish/boards/foo/include in the include path (and add wirish/boards/foo/board.cpp to the list of sources to be compiled). This allows saying: #include <board/board.h> instead of the hack currently in place. We can allow the user to override this setting later to make adding custom board definitions easier. - Disable -Werror in libmaple/rules.mk, as the current USB warnings don't let the olimex_stm32_h103 board compile. We can re-enable -Werror once we've moved the board-specific bits out of libmaple proper. libraries, examples: - Update includes accordingly. - Miscellaneous cosmetic fixups. Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
206 lines
5.1 KiB
C++
206 lines
5.1 KiB
C++
/*
|
|
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.
|
|
|
|
Authors:
|
|
|
|
Bryan Newbold <bnewbold@leaflabs.com>
|
|
Marti Bolivar <mbolivar@leaflabs.com>
|
|
*/
|
|
|
|
#include <wirish/wirish.h>
|
|
#include <libmaple/systick.h>
|
|
|
|
// FIXME: generalize for Native and Mini
|
|
|
|
#define ANALOG_PIN 18
|
|
|
|
// 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() {
|
|
pinMode(BOARD_LED_PIN, OUTPUT);
|
|
pinMode(ANALOG_PIN, INPUT_ANALOG);
|
|
digitalWrite(BOARD_LED_PIN, 1);
|
|
pinMode(VGA_R, OUTPUT);
|
|
pinMode(VGA_G, OUTPUT);
|
|
pinMode(VGA_B, OUTPUT);
|
|
pinMode(VGA_V, OUTPUT);
|
|
pinMode(VGA_H, OUTPUT);
|
|
|
|
// Send a message out USART2
|
|
Serial2.begin(9600);
|
|
Serial2.println("Time to kill the radio star...");
|
|
|
|
// 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();
|
|
|
|
digitalWrite(VGA_R, 0);
|
|
digitalWrite(VGA_G, 0);
|
|
digitalWrite(VGA_B, 0);
|
|
digitalWrite(VGA_H, 1);
|
|
digitalWrite(VGA_V, 1);
|
|
|
|
timer_pause(TIMER4);
|
|
timer_set_prescaler(TIMER4, 0);
|
|
timer_set_mode(TIMER4, 1, TIMER_OUTPUT_COMPARE);
|
|
timer_set_mode(TIMER4, 2, TIMER_OUTPUT_COMPARE);
|
|
timer_set_mode(TIMER4, 3, TIMER_OUTPUT_COMPARE);
|
|
timer_set_mode(TIMER4, 4, TIMER_OUTPUT_COMPARE);
|
|
timer_set_reload(TIMER4, 2287);
|
|
timer_set_compare(TIMER4, 1, 200);
|
|
timer_set_compare(TIMER4, 2, 250);
|
|
timer_set_compare(TIMER4, 3, 2170); // 2219 max...
|
|
timer_set_compare(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);
|
|
}
|
|
|
|
uint16 y = 0;
|
|
uint16 val = 0;
|
|
bool v_active = true;
|
|
const uint16 x_max = 60; // empirically (and sloppily) determined
|
|
|
|
void isr_porch(void) {
|
|
VGA_H_HIGH;
|
|
y++;
|
|
val = map(analogRead(ANALOG_PIN), 0, 4095, 0, x_max);
|
|
if (y >= 523) {
|
|
y = 1;
|
|
v_active = true;
|
|
return;
|
|
}
|
|
if (y >= 492) {
|
|
VGA_V_HIGH;
|
|
return;
|
|
}
|
|
if (y >= 490) {
|
|
VGA_V_LOW;
|
|
return;
|
|
}
|
|
if (y >= 479) {
|
|
v_active = false;
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
void isr_start(void) {
|
|
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_COLOR(COLOR_BLACK);
|
|
}
|
|
|
|
void isr_update(void) {
|
|
VGA_H_LOW;
|
|
}
|
|
|
|
void loop() {
|
|
toggleLED();
|
|
delay(100);
|
|
}
|
|
|
|
__attribute__((constructor)) void premain() {
|
|
init();
|
|
}
|
|
|
|
int main(void) {
|
|
setup();
|
|
|
|
while (true) {
|
|
loop();
|
|
}
|
|
return 0;
|
|
}
|