Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
/* NTSC, take 2 * --------------- * Created Sun Aug 26 14:59:29 EDT 2007 * * (cleft) 2007 by Matthieu Lalonde * * Note: Ideal values for the resistors are 900ohm and 330ohm! * */ #include "WProgram.h" #define _debugMode true // Définition des pins #define _pinSync 8 #define _pinVideo 9 #define _pinLED 12 // Definition of signal levels for the AD 2-bit converter #define _SYNC 0x00 /* 0.00v */ #define _BLACK 0x01 /* 0.33v */ #define _GRAY 0x02 /* 0.67v */ #define _WHITE 0x03 /* 1.00v */ // Defines TV Modes #define _NTSC 1 #define _PAL 2 // Select a TV mode (PAL isn't implemented) #define _tvMode _NTSC #ifdef _tvMode == _NTSC #define _tvNbrLines 262 /* Includes the last 20 lines for the vertical sync! */ #define _tvVSyncNbrLines 20 /* These 20 lines... */ #endif #define _tvPixelWidth 21 #define _tvPixelHeight 16 #define _serialBauteRate 19200 // Prototypes void startHSync(void); void endHSync(void); void generateVSync(void); void writeBufferLine(int position); void writeTVLines(void); void clearFrameBuffer(boolean mode); byte frameBuffer[_tvPixelWidth][_tvPixelHeight]; // Video frame buffer char c; // Serial buffer #ifdef _tvMode == _NTSC /** NTSC Signal definition: -- Horizontal sync (hsync) pulse: Start each scanline with 0.3V, then 0V for 4.7us (microseconds), and then back to 0.3V. This tells the TV to start drawing a new scanline -- The "Back Porch": A transition region of 0.3V for 5.9us between the hsync pulse and the visible region, off the left edge of the TV -- Visible scan region: This is the part you actually see. 0.3V shows up as black, 1V as white, everything in between is greyscale. The visible region lasts for 51.5us -- The "Front Porch": A transition region of 0.3V for 1.4us before the hsync pulse of the next line, off the right edge of the TV -- Vertical sync (vsync) pulse: Lines 243-262 of each frame (off the bottom of the TV) start with 0.3V for 4.7us, and the rest is 0V. This tells the TV to prepare for a new frame. Think of it as just 0V with an inverted sync pulse *** http://www.eyetap.org/ece385/lab5.htm *** **/ // Writes each pixel of a line void writeBufferLine(int position) { unsigned int ii; for (ii = 0; ii < _tvPixelWidth; ii++) { PORTB = frameBuffer[ii][position]; // Waste some time to make sure the line is sent with proper timing if (_tvPixelWidth < 51) delayMicroseconds((51.5 / _tvPixelWidth)); else delayMicroseconds((_tvPixelWidth / 51.5)); } } // Generate sync pulse for a new line void startHSync(void) { // Begin H Sync PORTB = _SYNC; delayMicroseconds(4.7); // Back Porch PORTB = _BLACK; delayMicroseconds(5.9); // Visible scan (51.5µs) follows } // Generate sync pulse for the end of a line void endHSync(void) { // Front Porch PORTB = _BLACK; delayMicroseconds(1.4); } // Generate sync pulse for the virtual sync (lasts 20 lines) void generateVSync(void) { unsigned int ii; for (ii = 0; ii < _tvVSyncNbrLines; ii++) { // Begin V Sync PORTB = _BLACK; delayMicroseconds(4.7); PORTB = _SYNC; delayMicroseconds(58.8); } } #endif // Writes every line from what's inside the frameBuffer void writeTVLines(void) { unsigned int i; for (i=0;i<(_tvNbrLines - _tvVSyncNbrLines);i++) // Includes correction for the vertical sync { startHSync(); // Write the line writeBufferLine(i>>4); endHSync(); } // Vertical Sync generateVSync(); } // Clears the frame buffer (if mode is true it will fill it with a chess board pattern) void clearFrameBuffer(boolean mode) { byte index, index2; for (index2 = 0; index2 < _tvPixelHeight; index2++) { for (index = 0; index < _tvPixelWidth; index++) { if (!mode) { frameBuffer[index][index2] = _BLACK; } else { frameBuffer[index][index2] = (index + index2) % 3 + 1; } } } } // Defines a static sprite const static byte graphic[_tvPixelWidth][_tvPixelHeight] = { {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE }, {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE }, {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE }, {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE }, {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE }, {_WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }, {_BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE, _BLACK, _WHITE }, {_GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY, _GRAY }}; void setup(void) { Serial.begin(_serialBauteRate); Serial.println("Arduino Initialized!"); Serial.println((long int) (sizeof frameBuffer)); Serial.print("Mode: "); pinMode(_pinVideo, OUTPUT); pinMode(_pinSync, OUTPUT); clearFrameBuffer(false); frameBuffer[(_tvPixelWidth / 2)][(_tvPixelHeight / 2)] = _WHITE; } void loop(void) { // Write the tv lines writeTVLines(); // Check for commands if (Serial.available()) { c = Serial.read(); switch (c) { case 'c' : Serial.println(); Serial.println("Clearing screen"); clearFrameBuffer(false); break; case 'f' : Serial.println(); Serial.println("Filling with pattern"); clearFrameBuffer(true); break; case 'g' : Serial.println(); Serial.println("Filling with graphic"); int ii,jj; for (ii=0;ii<_tvPixelWidth;ii++) { for(jj=0;jj<_tvPixelHeight;jj++) { frameBuffer[ii][jj] = graphic[ii][jj]; } } break; default : Serial.println(); Serial.println("c: clear screen | f: fille with pattern 1 | g: fill graphic pattern"); break; } Serial.print("Mode: "); } }
This paste will be private.
From the Design Piracy series on my blog: