diff options
Diffstat (limited to 'vga-more')
| -rw-r--r-- | vga-more/lib/.holder | 0 | ||||
| -rw-r--r-- | vga-more/src/TimerHelpers.h | 209 | ||||
| -rw-r--r-- | vga-more/src/screenFont.h | 160 | ||||
| -rw-r--r-- | vga-more/src/sketch.ino | 190 |
4 files changed, 559 insertions, 0 deletions
diff --git a/vga-more/lib/.holder b/vga-more/lib/.holder new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vga-more/lib/.holder diff --git a/vga-more/src/TimerHelpers.h b/vga-more/src/TimerHelpers.h new file mode 100644 index 0000000..d436987 --- /dev/null +++ b/vga-more/src/TimerHelpers.h @@ -0,0 +1,209 @@ +/* + Timer Helpers library. + +Devised and written by Nick Gammon. +Date: 21 March 2012 +Version: 1.0 + +Licence: Released for public use. + +See: http://www.gammon.com.au/forum/?id=11504 + + Example: + + // set up Timer 1 + TCNT1 = 0; // reset counter + OCR1A = 999; // compare A register value (1000 * clock speed) + + // Mode 4: CTC, top = OCR1A + Timer1::setMode (4, Timer1::PRESCALE_1, Timer1::CLEAR_A_ON_COMPARE); + + TIFR1 |= _BV (OCF1A); // clear interrupt flag + TIMSK1 = _BV (OCIE1A); // interrupt on Compare A Match + +*/ + +#ifndef _TimerHelpers_h +#define _TimerHelpers_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +/* --------------------------------------------------------------- + Timer 0 setup + --------------------------------------------------------------- */ + +namespace Timer0 +{ + // TCCR0A, TCCR0B + const byte Modes [8] [2] = + { + + { 0, 0 }, // 0: Normal, top = 0xFF + { _BV (WGM00), 0 }, // 1: PWM, Phase-correct, top = 0xFF + { _BV (WGM01), 0 }, // 2: CTC, top = OCR0A + { _BV (WGM00) | _BV (WGM01), 0 }, // 3: Fast PWM, top = 0xFF + { 0, _BV (WGM02) }, // 4: Reserved + { _BV (WGM00), _BV (WGM02) }, // 5: PWM, Phase-correct, top = OCR0A + { _BV (WGM01), _BV (WGM02) }, // 6: Reserved + { _BV (WGM00) | _BV (WGM01), _BV (WGM02) }, // 7: Fast PWM, top = OCR0A + + }; // end of Timer0::Modes + + // Activation + // Note: T0 is pin 6, Arduino port: D4 + enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256, PRESCALE_1024, T0_FALLING, T0_RISING }; + + // what ports to toggle on timer fire + enum { NO_PORT = 0, + + // pin 12, Arduino port: D6 + TOGGLE_A_ON_COMPARE = _BV (COM0A0), + CLEAR_A_ON_COMPARE = _BV (COM0A1), + SET_A_ON_COMPARE = _BV (COM0A0) | _BV (COM0A1), + + // pin 11, Arduino port: D5 + TOGGLE_B_ON_COMPARE = _BV (COM0B0), + CLEAR_B_ON_COMPARE = _BV (COM0B1), + SET_B_ON_COMPARE = _BV (COM0B0) | _BV (COM0B1), + }; + + + // choose a timer mode, set which clock speed, and which port to toggle + void setMode (const byte mode, const byte clock, const byte port) + { + if (mode < 0 || mode > 7) // sanity check + return; + + // reset existing flags + TCCR0A = 0; + TCCR0B = 0; + + TCCR0A |= (Modes [mode] [0]) | port; + TCCR0B |= (Modes [mode] [1]) | clock; + } // end of Timer0::setMode + +} // end of namespace Timer0 + +/* --------------------------------------------------------------- + Timer 1 setup + --------------------------------------------------------------- */ + +namespace Timer1 +{ + // TCCR1A, TCCR1B + const byte Modes [16] [2] = + { + + { 0, 0 }, // 0: Normal, top = 0xFFFF + { _BV (WGM10), 0 }, // 1: PWM, Phase-correct, 8 bit, top = 0xFF + { _BV (WGM11), 0 }, // 2: PWM, Phase-correct, 9 bit, top = 0x1FF + { _BV (WGM10) | _BV (WGM11), 0 }, // 3: PWM, Phase-correct, 10 bit, top = 0x3FF + { 0, _BV (WGM12) }, // 4: CTC, top = OCR1A + { _BV (WGM10), _BV (WGM12) }, // 5: Fast PWM, 8 bit, top = 0xFF + { _BV (WGM11), _BV (WGM12) }, // 6: Fast PWM, 9 bit, top = 0x1FF + { _BV (WGM10) | _BV (WGM11), _BV (WGM12) }, // 7: Fast PWM, 10 bit, top = 0x3FF + { 0, _BV (WGM13) }, // 8: PWM, phase and frequency correct, top = ICR1 + { _BV (WGM10), _BV (WGM13) }, // 9: PWM, phase and frequency correct, top = OCR1A + { _BV (WGM11), _BV (WGM13) }, // 10: PWM, phase correct, top = ICR1A + { _BV (WGM10) | _BV (WGM11), _BV (WGM13) }, // 11: PWM, phase correct, top = OCR1A + { 0, _BV (WGM12) | _BV (WGM13) }, // 12: CTC, top = ICR1 + { _BV (WGM10), _BV (WGM12) | _BV (WGM13) }, // 13: reserved + { _BV (WGM11), _BV (WGM12) | _BV (WGM13) }, // 14: Fast PWM, TOP = ICR1 + { _BV (WGM10) | _BV (WGM11), _BV (WGM12) | _BV (WGM13) }, // 15: Fast PWM, TOP = OCR1A + + }; // end of Timer1::Modes + + // Activation + // Note: T1 is pin 11, Arduino port: D5 + enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_64, PRESCALE_256, PRESCALE_1024, T1_FALLING, T1_RISING }; + + // what ports to toggle on timer fire + enum { NO_PORT = 0, + + // pin 15, Arduino port: D9 + TOGGLE_A_ON_COMPARE = _BV (COM1A0), + CLEAR_A_ON_COMPARE = _BV (COM1A1), + SET_A_ON_COMPARE = _BV (COM1A0) | _BV (COM1A1), + + // pin 16, Arduino port: D10 + TOGGLE_B_ON_COMPARE = _BV (COM1B0), + CLEAR_B_ON_COMPARE = _BV (COM1B1), + SET_B_ON_COMPARE = _BV (COM1B0) | _BV (COM1B1), + }; + + // choose a timer mode, set which clock speed, and which port to toggle + void setMode (const byte mode, const byte clock, const byte port) + { + if (mode < 0 || mode > 15) // sanity check + return; + + // reset existing flags + TCCR1A = 0; + TCCR1B = 0; + + TCCR1A |= (Modes [mode] [0]) | port; + TCCR1B |= (Modes [mode] [1]) | clock; + } // end of Timer1::setMode + +} // end of namespace Timer1 + +/* --------------------------------------------------------------- + Timer 2 setup + --------------------------------------------------------------- */ + +namespace Timer2 +{ + // TCCR2A, TCCR2B + const byte Modes [8] [2] = + { + + { 0, 0 }, // 0: Normal, top = 0xFF + { _BV (WGM20), 0 }, // 1: PWM, Phase-correct, top = 0xFF + { _BV (WGM21), 0 }, // 2: CTC, top = OCR2A + { _BV (WGM20) | _BV (WGM21), 0 }, // 3: Fast PWM, top = 0xFF + { 0, _BV (WGM22) }, // 4: Reserved + { _BV (WGM20), _BV (WGM22) }, // 5: PWM, Phase-correct, top = OCR2A + { _BV (WGM21), _BV (WGM22) }, // 6: Reserved + { _BV (WGM20) | _BV (WGM21), _BV (WGM22) }, // 7: Fast PWM, top = OCR2A + + }; // end of Timer2::Modes + + // Activation + enum { NO_CLOCK, PRESCALE_1, PRESCALE_8, PRESCALE_32, PRESCALE_64, PRESCALE_128, PRESCALE_256, PRESCALE_1024 }; + + // what ports to toggle on timer fire + enum { NO_PORT = 0, + + // pin 17, Arduino port: D11 + TOGGLE_A_ON_COMPARE = _BV (COM2A0), + CLEAR_A_ON_COMPARE = _BV (COM2A1), + SET_A_ON_COMPARE = _BV (COM2A0) | _BV (COM2A1), + + // pin 5, Arduino port: D3 + TOGGLE_B_ON_COMPARE = _BV (COM2B0), + CLEAR_B_ON_COMPARE = _BV (COM2B1), + SET_B_ON_COMPARE = _BV (COM2B0) | _BV (COM2B1), + }; + + + // choose a timer mode, set which clock speed, and which port to toggle + void setMode (const byte mode, const byte clock, const byte port) + { + if (mode < 0 || mode > 7) // sanity check + return; + + // reset existing flags + TCCR2A = 0; + TCCR2B = 0; + + TCCR2A |= (Modes [mode] [0]) | port; + TCCR2B |= (Modes [mode] [1]) | clock; + } // end of Timer2::setMode + +} // end of namespace Timer2 + +#endif diff --git a/vga-more/src/screenFont.h b/vga-more/src/screenFont.h new file mode 100644 index 0000000..5279f9e --- /dev/null +++ b/vga-more/src/screenFont.h @@ -0,0 +1,160 @@ +// bit patterns for the CP437 font, ROTATED, INVERTED + +// To save rendering time, they are ordered by line (ie. line 1, line 2) and then +// indexed by character. + +byte screen_font [8] [256] PROGMEM = { +// Row 1 + { + 0xFF, 0xC0, 0xC0, 0xC9, 0xF7, 0xE3, 0xF7, 0xFF, 0x80, 0xFF, 0x80, 0xF8, 0xE1, 0xE0, 0xC0, 0xB3, + 0xBF, 0xFE, 0xF3, 0xCC, 0xC0, 0xE0, 0xFF, 0xF3, 0xF3, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xE7, 0xC9, 0xC9, 0xE7, 0xFF, 0xE3, 0xCF, 0xF3, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xC1, 0xE7, 0xC3, 0xC3, 0xF1, 0x81, 0xE3, 0x81, 0xC3, 0xC3, 0xFF, 0xFF, 0xF3, 0xFF, 0xCF, 0xC3, + 0xC1, 0xE7, 0x81, 0xE1, 0x83, 0x80, 0x80, 0xE1, 0x99, 0xC3, 0xF0, 0x8C, 0x87, 0x9C, 0x9C, 0xE3, + 0x81, 0xC3, 0x81, 0xC3, 0x81, 0x99, 0x99, 0x9C, 0x9C, 0x99, 0x80, 0xC3, 0x9F, 0xC3, 0xF7, 0xFF, + 0xE7, 0xFF, 0x8F, 0xFF, 0xF1, 0xFF, 0xE3, 0xFF, 0x8F, 0xE7, 0xF9, 0x8F, 0xC7, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF3, 0x8F, 0xC4, 0xFF, + 0xC3, 0xFF, 0xF1, 0xC0, 0x99, 0x8F, 0xE7, 0xFF, 0xC0, 0x99, 0x8F, 0x99, 0xC1, 0x8F, 0x9C, 0xE7, + 0xF1, 0xFF, 0xE0, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0x9E, 0x99, 0xF3, 0xE3, 0x99, 0x83, 0xF8, + 0xF1, 0xE3, 0xFF, 0xFF, 0xFF, 0x81, 0xE1, 0xE3, 0xE7, 0xFF, 0xFF, 0x9E, 0x9E, 0xF3, 0xFF, 0xFF, + 0xEE, 0xD5, 0x92, 0xF3, 0xF3, 0xF3, 0xE4, 0xFF, 0xFF, 0xE4, 0xE4, 0xFF, 0xE4, 0xE4, 0xF3, 0xFF, + 0xF3, 0xF3, 0xFF, 0xF3, 0xFF, 0xF3, 0xF3, 0xE4, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xF3, + 0xE4, 0xFF, 0xFF, 0xE4, 0xF3, 0xFF, 0xFF, 0xE4, 0xF3, 0xF3, 0xFF, 0x80, 0xFF, 0x87, 0xF8, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x81, 0xE3, 0xE3, 0xF1, 0xFF, 0xFC, 0xE3, 0xC3, + 0xFF, 0xE7, 0xCF, 0xF3, 0xF8, 0xF3, 0xE7, 0xFF, 0xE3, 0xFF, 0xFF, 0xF8, 0xC3, 0xC7, 0xFF, 0xFF, + }, +// Row 2 + { + 0xFF, 0xBF, 0x80, 0x80, 0xE3, 0xC1, 0xF7, 0xFF, 0x80, 0xE1, 0x9E, 0xFC, 0xCC, 0xE6, 0xCE, 0xD2, + 0x8F, 0xF8, 0xE1, 0xCC, 0x92, 0xCE, 0xFF, 0xE1, 0xE1, 0xF3, 0xF3, 0xE7, 0xFF, 0xED, 0xF3, 0x80, + 0xFF, 0xC3, 0xC9, 0xC9, 0xC1, 0x9C, 0xC9, 0xCF, 0xE7, 0xE7, 0xCC, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, + 0x9C, 0xC7, 0x99, 0x99, 0xE1, 0x9F, 0xCF, 0x99, 0x99, 0x99, 0xE7, 0xE7, 0xE7, 0xFF, 0xE7, 0x99, + 0x9C, 0xC3, 0xCC, 0xCC, 0xC9, 0xCE, 0xCE, 0xCC, 0x99, 0xE7, 0xF9, 0xCC, 0xCF, 0x88, 0x8C, 0xC9, + 0xCC, 0x99, 0xCC, 0x99, 0xA5, 0x99, 0x99, 0x9C, 0x9C, 0x99, 0x9C, 0xCF, 0xCF, 0xF3, 0xE3, 0xFF, + 0xE7, 0xFF, 0xCF, 0xFF, 0xF9, 0xFF, 0xC9, 0xFF, 0xCF, 0xFF, 0xFF, 0xCF, 0xE7, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xF3, 0xE7, 0x91, 0xF7, + 0x99, 0x99, 0xFF, 0x9E, 0xFF, 0xFF, 0xE7, 0xFF, 0x9E, 0xFF, 0xFF, 0xFF, 0x9C, 0xFF, 0xE3, 0xE7, + 0xFF, 0xFF, 0xC9, 0x99, 0x99, 0x8F, 0x99, 0x8F, 0x99, 0xF3, 0xFF, 0xF3, 0xC9, 0x99, 0x99, 0xF2, + 0xFF, 0xFF, 0xF1, 0xF1, 0x83, 0xFF, 0xC9, 0xC9, 0xFF, 0xFF, 0xFF, 0x9C, 0x9C, 0xF3, 0xE6, 0x99, + 0xBB, 0xAA, 0xC4, 0xF3, 0xF3, 0xF3, 0xE4, 0xFF, 0xFF, 0xE4, 0xE4, 0xFF, 0xE4, 0xE4, 0xF3, 0xFF, + 0xF3, 0xF3, 0xFF, 0xF3, 0xFF, 0xF3, 0xF3, 0xE4, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xF3, + 0xE4, 0xFF, 0xFF, 0xE4, 0xF3, 0xFF, 0xFF, 0xE4, 0xF3, 0xF3, 0xFF, 0x80, 0xFF, 0x87, 0xF8, 0x80, + 0xFF, 0xC3, 0x81, 0x80, 0x99, 0xFF, 0xCC, 0xC4, 0xE7, 0xC9, 0xC9, 0xE7, 0xFF, 0xF9, 0xCF, 0x99, + 0x81, 0xE7, 0xE7, 0xE7, 0xF2, 0xF3, 0xE7, 0xC4, 0xC9, 0xFF, 0xFF, 0xF9, 0xC9, 0xF3, 0xFF, 0xFF, + }, +// Row 3 + { + 0xFF, 0xAD, 0x92, 0x80, 0xC1, 0xE3, 0xE3, 0xF3, 0x8C, 0xCC, 0xB3, 0xF8, 0xCC, 0xE0, 0xC0, 0xE1, + 0x83, 0xE0, 0xC0, 0xCC, 0x92, 0xE3, 0xFF, 0xC0, 0xC0, 0xF3, 0xF9, 0xCF, 0x9F, 0xCC, 0xE1, 0x80, + 0xFF, 0xC3, 0xC9, 0x80, 0x9F, 0x99, 0xE3, 0x9F, 0xCF, 0xF3, 0xE1, 0xE7, 0xFF, 0xFF, 0xFF, 0xF3, + 0x98, 0xE7, 0xF9, 0xF9, 0xC9, 0x83, 0x9F, 0xF9, 0x99, 0x99, 0xE7, 0xE7, 0xCF, 0x81, 0xF3, 0xF9, + 0x90, 0x99, 0xCC, 0x9F, 0xCC, 0xCB, 0xCB, 0x9F, 0x99, 0xE7, 0xF9, 0xC9, 0xCF, 0x80, 0x84, 0x9C, + 0xCC, 0x99, 0xCC, 0x8F, 0xE7, 0x99, 0x99, 0x9C, 0xC9, 0x99, 0xB9, 0xCF, 0xE7, 0xF3, 0xC9, 0xFF, + 0xF3, 0xC3, 0xCF, 0xC3, 0xF9, 0xC3, 0xCF, 0xC4, 0xC9, 0xC7, 0xF9, 0xCC, 0xE7, 0x99, 0x83, 0xC3, + 0x91, 0xC4, 0x91, 0xC1, 0xC1, 0x99, 0x99, 0x9C, 0x9C, 0x99, 0x81, 0xE7, 0xF3, 0xE7, 0xFF, 0xE3, + 0x9F, 0xFF, 0xC3, 0xE1, 0xC3, 0xC3, 0xC3, 0xC3, 0xE1, 0xC3, 0xC3, 0xC7, 0xE3, 0xC7, 0xC9, 0xFF, + 0x81, 0xC0, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0x99, 0xC0, 0xCD, 0xC3, 0x99, 0xF3, + 0xC3, 0xC7, 0xFF, 0xFF, 0xFF, 0x99, 0xC9, 0xC9, 0xE7, 0xFF, 0xFF, 0x99, 0x99, 0xFF, 0xCC, 0xCC, + 0xEE, 0xD5, 0x92, 0xF3, 0xF3, 0x83, 0xE4, 0xFF, 0x83, 0x84, 0xE4, 0x80, 0x84, 0xE4, 0x83, 0xFF, + 0xF3, 0xF3, 0xFF, 0xF3, 0xFF, 0xF3, 0xF0, 0xE4, 0xE4, 0xE0, 0x84, 0x80, 0xE4, 0x80, 0x84, 0x80, + 0xE4, 0x80, 0xFF, 0xE4, 0xF0, 0xF0, 0xFF, 0xE4, 0x80, 0xF3, 0xFF, 0x80, 0xFF, 0x87, 0xF8, 0x80, + 0xC4, 0x99, 0x99, 0xC9, 0xCF, 0xC0, 0xCC, 0x91, 0xC3, 0x9C, 0x9C, 0xF3, 0xC0, 0xC0, 0x9F, 0x99, + 0xFF, 0x81, 0xF3, 0xCF, 0xF2, 0xF3, 0xFF, 0x91, 0xC9, 0xFF, 0xFF, 0xF9, 0xC9, 0xE7, 0xE1, 0xFF, + }, +// Row 4 + { + 0xFF, 0xBF, 0x80, 0x80, 0x80, 0x80, 0xC1, 0xE1, 0x9E, 0xDE, 0xA1, 0xC1, 0xCC, 0xE7, 0xCE, 0x8C, + 0x80, 0x80, 0xF3, 0xCC, 0xC2, 0xC9, 0xFF, 0xF3, 0xF3, 0xF3, 0x80, 0x80, 0x9F, 0x80, 0xC0, 0xC0, + 0xFF, 0xE7, 0xFF, 0xC9, 0xC3, 0xF3, 0xC4, 0xFF, 0xCF, 0xF3, 0x80, 0x81, 0xFF, 0x81, 0xFF, 0xE7, + 0x90, 0xE7, 0xE3, 0xE3, 0x99, 0xF9, 0x83, 0xF3, 0xC3, 0xC1, 0xFF, 0xFF, 0x9F, 0xFF, 0xF9, 0xF3, + 0x90, 0x99, 0xC1, 0x9F, 0xCC, 0xC3, 0xC3, 0x9F, 0x81, 0xE7, 0xF9, 0xC3, 0xCF, 0x80, 0x90, 0x9C, + 0xC1, 0x99, 0xC1, 0xC7, 0xE7, 0x99, 0x99, 0x94, 0xE3, 0xC3, 0xF3, 0xCF, 0xF3, 0xF3, 0x9C, 0xFF, + 0xFF, 0xF9, 0xC1, 0x99, 0xC1, 0x99, 0x87, 0x99, 0xC4, 0xE7, 0xF9, 0xC9, 0xE7, 0x80, 0x99, 0x99, + 0xCC, 0x99, 0xC4, 0x9F, 0xE7, 0x99, 0x99, 0x94, 0xC9, 0x99, 0xB3, 0x8F, 0xFF, 0xF1, 0xFF, 0xC9, + 0x99, 0x99, 0x99, 0xFC, 0xF9, 0xF9, 0xF9, 0x9F, 0xCC, 0x99, 0x99, 0xE7, 0xF3, 0xE7, 0x9C, 0xC3, + 0xCF, 0xF9, 0x80, 0xC3, 0xC3, 0xC3, 0x99, 0x99, 0x99, 0xCC, 0x99, 0x9F, 0x87, 0x81, 0x82, 0xE1, + 0xF9, 0xE7, 0xC3, 0x99, 0x83, 0x89, 0xE0, 0xE3, 0xCF, 0x81, 0x81, 0x90, 0x92, 0xF3, 0x99, 0xE6, + 0xBB, 0xAA, 0x88, 0xF3, 0xF3, 0xF3, 0xE4, 0xFF, 0xF3, 0xFC, 0xE4, 0xFC, 0xFC, 0xE4, 0xF3, 0xFF, + 0xF3, 0xF3, 0xFF, 0xF3, 0xFF, 0xF3, 0xF3, 0xE4, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, + 0xE4, 0xFF, 0xFF, 0xE4, 0xF3, 0xF3, 0xFF, 0xE4, 0xF3, 0xF3, 0xFF, 0x80, 0xFF, 0x87, 0xF8, 0x80, + 0x91, 0x83, 0x9F, 0xC9, 0xE7, 0x93, 0xCC, 0xF3, 0x99, 0x80, 0x9C, 0xC1, 0x92, 0x92, 0x83, 0x99, + 0x81, 0xE7, 0xE7, 0xE7, 0xF3, 0xF3, 0x81, 0xFF, 0xE3, 0xF3, 0xFF, 0xF9, 0xC9, 0xCF, 0xE1, 0xFF, + }, +// Row 5 + { + 0xFF, 0xA1, 0x9E, 0xC1, 0xC1, 0x80, 0x80, 0xE1, 0x9E, 0xDE, 0xA1, 0x99, 0xE1, 0xE7, 0xCE, 0x8C, + 0x83, 0xE0, 0xF3, 0xCC, 0xF2, 0xC9, 0xC0, 0xC0, 0xF3, 0xC0, 0xF9, 0xCF, 0x9F, 0xCC, 0x80, 0xE1, + 0xFF, 0xE7, 0xFF, 0x80, 0xF9, 0xE7, 0x91, 0xFF, 0xCF, 0xF3, 0xE1, 0xE7, 0xFF, 0xFF, 0xFF, 0xCF, + 0x84, 0xE7, 0xCF, 0xF9, 0x80, 0xF9, 0x99, 0xE7, 0x99, 0xF9, 0xFF, 0xFF, 0xCF, 0xFF, 0xF3, 0xE7, + 0x90, 0x81, 0xCC, 0x9F, 0xCC, 0xCB, 0xCB, 0x98, 0x99, 0xE7, 0x99, 0xC9, 0xCE, 0x94, 0x98, 0x9C, + 0xCF, 0x91, 0xC9, 0xF1, 0xE7, 0x99, 0x99, 0x80, 0xE3, 0xE7, 0xE6, 0xCF, 0xF9, 0xF3, 0xFF, 0xFF, + 0xFF, 0xC1, 0xCC, 0x9F, 0x99, 0x81, 0xCF, 0x99, 0xCC, 0xE7, 0xF9, 0xC3, 0xE7, 0x80, 0x99, 0x99, + 0xCC, 0x99, 0xCC, 0xC3, 0xE7, 0x99, 0x99, 0x80, 0xE3, 0x99, 0xE7, 0xE7, 0xF3, 0xE7, 0xFF, 0x9C, + 0xC3, 0x99, 0x81, 0xE0, 0xC1, 0xC1, 0xC1, 0x9F, 0xC0, 0x81, 0x81, 0xE7, 0xF3, 0xE7, 0x80, 0x99, + 0xC3, 0xC0, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xCC, 0x99, 0x9F, 0xCF, 0xE7, 0x9C, 0xF3, + 0xC1, 0xE7, 0x99, 0x99, 0x99, 0x81, 0xFF, 0xFF, 0x9F, 0x9F, 0xF9, 0xE6, 0xE4, 0xF3, 0xCC, 0xCC, + 0xEE, 0xD5, 0x92, 0xF3, 0x83, 0x83, 0x84, 0x80, 0x83, 0x84, 0xE4, 0x84, 0x80, 0x80, 0x83, 0x83, + 0xF0, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF0, 0xE4, 0xE0, 0xE4, 0x80, 0x84, 0xE4, 0x80, 0x84, 0x80, + 0x80, 0x80, 0x80, 0xE0, 0xF0, 0xF0, 0xE0, 0x80, 0x80, 0x83, 0xF0, 0x80, 0x80, 0x87, 0xF8, 0xFF, + 0x9B, 0x99, 0x9F, 0xC9, 0xCF, 0x93, 0xCC, 0xF3, 0x99, 0x9C, 0xC9, 0x99, 0x92, 0x92, 0x9F, 0x99, + 0xFF, 0xE7, 0xCF, 0xF3, 0xF3, 0xF3, 0xFF, 0xC4, 0xFF, 0xF3, 0xF3, 0x89, 0xC9, 0xC3, 0xE1, 0xFF, + }, +// Row 6 + { + 0xFF, 0xB3, 0x8C, 0xE3, 0xE3, 0xC1, 0xC1, 0xF3, 0x8C, 0xCC, 0xB3, 0x99, 0xF3, 0xC7, 0xCC, 0xE1, + 0x8F, 0xF8, 0xC0, 0xFF, 0xF2, 0xE3, 0xC0, 0xE1, 0xF3, 0xE1, 0xF3, 0xE7, 0x80, 0xED, 0x80, 0xF3, + 0xFF, 0xFF, 0xFF, 0xC9, 0x83, 0xCC, 0x99, 0xFF, 0xE7, 0xE7, 0xCC, 0xE7, 0xE7, 0xFF, 0xE7, 0x9F, + 0x8C, 0xE7, 0x99, 0x99, 0xF9, 0x99, 0x99, 0xE7, 0x99, 0xF3, 0xE7, 0xE7, 0xE7, 0x81, 0xE7, 0xFF, + 0x9F, 0x99, 0xCC, 0xCC, 0xC9, 0xCE, 0xCF, 0xCC, 0x99, 0xE7, 0x99, 0xCC, 0xCC, 0x9C, 0x9C, 0xC9, + 0xCF, 0xC3, 0xCC, 0x99, 0xE7, 0x99, 0xC3, 0x88, 0xC9, 0xE7, 0xCC, 0xCF, 0xFC, 0xF3, 0xFF, 0xFF, + 0xFF, 0x99, 0xCC, 0x99, 0x99, 0x9F, 0xCF, 0xC1, 0xCC, 0xE7, 0x99, 0xC9, 0xE7, 0x94, 0x99, 0x99, + 0xC1, 0xC1, 0xCF, 0xF9, 0xE5, 0x99, 0xC3, 0x80, 0xC9, 0xC1, 0xCD, 0xE7, 0xF3, 0xE7, 0xFF, 0x9C, + 0xF3, 0x99, 0x9F, 0xCC, 0x99, 0x99, 0x99, 0xC3, 0xCF, 0x9F, 0x9F, 0xE7, 0xF3, 0xE7, 0x9C, 0x81, + 0xCF, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xC1, 0xE1, 0x99, 0xC0, 0x8C, 0x81, 0x98, 0xF3, + 0x99, 0xE7, 0x99, 0x99, 0x99, 0x91, 0xC0, 0xC1, 0x99, 0x9F, 0xF9, 0xCC, 0xC8, 0xF3, 0xE6, 0x99, + 0xBB, 0xAA, 0xC4, 0xF3, 0xF3, 0xF3, 0xE4, 0xE4, 0xF3, 0xE4, 0xE4, 0xE4, 0xFF, 0xFF, 0xFF, 0xF3, + 0xFF, 0xFF, 0xF3, 0xF3, 0xFF, 0xF3, 0xF3, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xE4, 0xFF, 0xE4, 0xFF, + 0xFF, 0xF3, 0xE4, 0xFF, 0xFF, 0xF3, 0xE4, 0xE4, 0xF3, 0xFF, 0xF3, 0x80, 0x80, 0x87, 0xF8, 0xFF, + 0x91, 0x83, 0x9F, 0xC9, 0x99, 0x93, 0xC1, 0xF3, 0xC3, 0xC9, 0xC9, 0x99, 0xC0, 0xC0, 0xCF, 0x99, + 0x81, 0xFF, 0xFF, 0xFF, 0xF3, 0x93, 0xE7, 0x91, 0xFF, 0xFF, 0xFF, 0xC9, 0xFF, 0xFF, 0xE1, 0xFF, + }, +// Row 7 + { + 0xFF, 0xBF, 0x80, 0xF7, 0xF7, 0xE3, 0xE3, 0xFF, 0x80, 0xE1, 0x9E, 0x99, 0xC0, 0x87, 0x8C, 0xD2, + 0xBF, 0xFE, 0xE1, 0xCC, 0xF2, 0x99, 0xC0, 0xF3, 0xF3, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xE7, 0xFF, 0xC9, 0xE7, 0x9C, 0xC4, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, 0xE7, 0xFF, 0xE7, 0xBF, + 0xC1, 0x81, 0x81, 0xC3, 0xF0, 0xC3, 0xC3, 0xE7, 0xC3, 0xC7, 0xE7, 0xE7, 0xF3, 0xFF, 0xCF, 0xE7, + 0xC3, 0x99, 0x81, 0xE1, 0x83, 0x80, 0x87, 0xE0, 0x99, 0xC3, 0xC3, 0x8C, 0x80, 0x9C, 0x9C, 0xE3, + 0x87, 0xF1, 0x8C, 0xC3, 0xC3, 0x81, 0xE7, 0x9C, 0x9C, 0xC3, 0x80, 0xC3, 0xFE, 0xC3, 0xFF, 0xFF, + 0xFF, 0xC4, 0x91, 0xC3, 0xC4, 0xC3, 0x87, 0xF9, 0x8C, 0xC3, 0x99, 0x8C, 0xC3, 0x9C, 0x99, 0xC3, + 0xCF, 0xF9, 0x87, 0x83, 0xF3, 0xC4, 0xE7, 0xC9, 0x9C, 0xF9, 0x81, 0xF1, 0xF3, 0x8F, 0xFF, 0x80, + 0xF9, 0xC0, 0xC3, 0xE0, 0xC0, 0xC0, 0xC0, 0xF9, 0xE1, 0xC3, 0xC3, 0xC3, 0xE1, 0xC3, 0x9C, 0x99, + 0x81, 0xC0, 0x98, 0xC3, 0xC3, 0xC3, 0xC0, 0xC0, 0xF9, 0xF3, 0xC3, 0xF3, 0x81, 0xE7, 0x9C, 0x93, + 0xC0, 0xC3, 0xC3, 0xC0, 0x99, 0x99, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0x99, 0x98, 0xF3, 0xFF, 0xFF, + 0xEE, 0xD5, 0x92, 0xF3, 0xF3, 0xF3, 0xE4, 0xE4, 0xF3, 0xE4, 0xE4, 0xE4, 0xFF, 0xFF, 0xFF, 0xF3, + 0xFF, 0xFF, 0xF3, 0xF3, 0xFF, 0xF3, 0xF3, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xE4, 0xFF, 0xE4, 0xFF, + 0xFF, 0xF3, 0xE4, 0xFF, 0xFF, 0xF3, 0xE4, 0xE4, 0xF3, 0xFF, 0xF3, 0x80, 0x80, 0x87, 0xF8, 0xFF, + 0xC4, 0x9F, 0x9F, 0xC9, 0x81, 0xC7, 0xCF, 0xF3, 0xE7, 0xE3, 0x88, 0xC3, 0xFF, 0xCF, 0xE3, 0x99, + 0xFF, 0x81, 0x81, 0x81, 0xF3, 0x93, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, + }, +// Row 8 + { + 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xC1, 0xC1, 0xFF, 0x80, 0xFF, 0x80, 0xC3, 0xF3, 0x8F, 0x9F, 0xB3, + 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xC3, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x87, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xF3, 0xFF, 0xE7, 0x9C, 0xC7, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, + 0xBB, 0xAA, 0x88, 0xF3, 0xF3, 0xF3, 0xE4, 0xE4, 0xF3, 0xE4, 0xE4, 0xE4, 0xFF, 0xFF, 0xFF, 0xF3, + 0xFF, 0xFF, 0xF3, 0xF3, 0xFF, 0xF3, 0xF3, 0xE4, 0xFF, 0xE4, 0xFF, 0xE4, 0xE4, 0xFF, 0xE4, 0xFF, + 0xFF, 0xF3, 0xE4, 0xFF, 0xFF, 0xF3, 0xE4, 0xE4, 0xF3, 0xFF, 0xF3, 0x80, 0x80, 0x87, 0xF8, 0xFF, + 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, + }, + +}; // end of screen_font
\ No newline at end of file diff --git a/vga-more/src/sketch.ino b/vga-more/src/sketch.ino new file mode 100644 index 0000000..a3a3c89 --- /dev/null +++ b/vga-more/src/sketch.ino @@ -0,0 +1,190 @@ +/* + VGA video generation + + Author: Nick Gammon + Date: 20th April 2012 + + Example code without I2C communications. + + Connections: + + D1 : Pixel output (180 ohms in series) (connect to R, G, B tied together) --> Pins 1, 2, 3 on DB15 socket + D3 : Horizontal Sync (68 ohms in series) --> Pin 13 on DB15 socket + D10 : Vertical Sync (68 ohms in series) --> Pin 14 on DB15 socket + + Gnd : --> Pins 5, 6, 7, 8, 10 on DB15 socket + +*/ + +#include "TimerHelpers.h" +#include <avr/pgmspace.h> +#include "screenFont.h" +#include <avr/sleep.h> + +#define BETA_ARDUINO ARDUINO < 100 + +const byte pixelPin = 1; // <------- Pixel data +const byte hSyncPin = 3; // <------- HSYNC +const byte MSPIM_SCK = 4; // <-- we aren't using it directly +const byte vSyncPin = 10; // <------- VSYNC + +const int horizontalBytes = 20; // 160 pixels wide +const int verticalPixels = 480; // 480 pixels high + +const byte i2cAddress = 42; + +// Timer 1 - Vertical sync + +// output OC1B pin 16 (D10) <------- VSYNC + +// Period: 16.64 mS (60 Hz) +// 1/60 * 1e6 = 16666.66 uS +// Pulse for 64 uS (2 x HSync width of 32 uS) +// Sync pulse: 2 lines +// Back porch: 33 lines +// Active video: 480 lines +// Front porch: 10 lines +// Total: 525 lines + +// Timer 2 - Horizontal sync + +// output OC2B pin 5 (D3) <------- HSYNC + +// Period: 32 uS (31.25 kHz) +// (1/60) / 525 * 1e6 = 31.74 uS +// Pulse for 4 uS (96 times 39.68 nS) +// Sync pulse: 96 pixels +// Back porch: 48 pixels +// Active video: 640 pixels +// Front porch: 16 pixels +// Total: 800 pixels + +// Pixel time = ((1/60) / 525 * 1e9) / 800 = 39.68 nS +// frequency = 1 / (((1/60) / 525 * 1e6) / 800) = 25.2 MHz + +// However in practice, it is the SPI speed, namely a period of 125 nS +// (that is 2 x system clock speed) +// giving an 8 MHz pixel frequency. Thus the characters are about 3 times too wide. +// Thus we fit 160 of "our" pixels on the screen in what usually takes 3 x 160 = 480 + +const byte screenFontHeight = 8; +const byte screenFontWidth = 8; + +const int verticalLines = verticalPixels / screenFontHeight / 2; // double-height characters +const int horizontalPixels = horizontalBytes * screenFontWidth; + +const byte verticalBackPorchLines = 35; // includes sync pulse? +const int verticalFrontPorchLines = 525 - verticalBackPorchLines; + +volatile int vLine; +volatile int messageLine; +volatile byte backPorchLinesToGo; + +char message [verticalLines] [horizontalBytes]; + +// ISR: Vsync pulse +ISR (TIMER1_OVF_vect) + { + vLine = 0; + messageLine = 0; + backPorchLinesToGo = verticalBackPorchLines; + } // end of TIMER1_OVF_vect + +// ISR: Hsync pulse ... this interrupt merely wakes us up +ISR (TIMER2_OVF_vect) + { + } // end of TIMER2_OVF_vect + +void setup() + { + + // initial message ... change to suit + for (int i = 0; i < verticalLines; i++) + sprintf (message [i], "Line %03i - hello!", i); + + // disable Timer 0 + TIMSK0 = 0; // no interrupts on Timer 0 + OCR0A = 0; // and turn it off + OCR0B = 0; + + // Timer 1 - vertical sync pulses + pinMode (vSyncPin, OUTPUT); + Timer1::setMode (15, Timer1::PRESCALE_1024, Timer1::CLEAR_B_ON_COMPARE); + OCR1A = 259; // 16666 / 64 uS = 260 (less one) + OCR1B = 0; // 64 / 64 uS = 1 (less one) + TIFR1 = _BV (TOV1); // clear overflow flag + TIMSK1 = _BV (TOIE1); // interrupt on overflow on timer 1 + + // Timer 2 - horizontal sync pulses + pinMode (hSyncPin, OUTPUT); + Timer2::setMode (7, Timer2::PRESCALE_8, Timer2::CLEAR_B_ON_COMPARE); + OCR2A = 63; // 32 / 0.5 uS = 64 (less one) + OCR2B = 7; // 4 / 0.5 uS = 8 (less one) + TIFR2 = _BV (TOV2); // clear overflow flag + TIMSK2 = _BV (TOIE2); // interrupt on overflow on timer 2 + + // Set up USART in SPI mode (MSPIM) + + // baud rate must be zero before enabling the transmitter + UBRR0 = 0; // USART Baud Rate Register + pinMode (MSPIM_SCK, OUTPUT); // set XCK pin as output to enable master mode + UCSR0B = 0; + UCSR0C = _BV (UMSEL00) | _BV (UMSEL01) | _BV (UCPHA0) | _BV (UCPOL0); // Master SPI mode + + // prepare to sleep between horizontal sync pulses + set_sleep_mode (SLEEP_MODE_IDLE); + +} // end of setup + +// draw a single scan line +void doOneScanLine () + { + + // after vsync we do the back porch + if (backPorchLinesToGo) + { + backPorchLinesToGo--; + return; + } // end still doing back porch + + // if all lines done, do the front porch + if (vLine >= verticalPixels) + return; + + // pre-load pointer for speed + const register byte * linePtr = &screen_font [ (vLine >> 1) & 0x07 ] [0]; + register char * messagePtr = & (message [messageLine] [0] ); + + // how many pixels to send + register byte i = horizontalBytes; + + // turn transmitter on + UCSR0B = _BV (TXEN0); // transmit enable (starts transmitting white) + + // blit pixel data to screen + while (i--) + UDR0 = pgm_read_byte (linePtr + (* messagePtr++)); + + // wait till done + while (!(UCSR0A & _BV(TXC0))) + {} + + // disable transmit + UCSR0B = 0; // drop back to black + + // this line done + vLine++; + + // every 16 pixels it is time to move to a new line in our text + // (because we double up the characters vertically) + if ((vLine & 0xF) == 0) + messageLine++; + + } // end of doOneScanLine + +void loop() + { + // sleep to ensure we start up in a predictable way + sleep_mode (); + doOneScanLine (); + } // end of loop |
