#include "ledconfig.h" #include "led.h" #include #include #include #define F_CPU 16000000UL // 16 MHz #include // Convenience macros for the shift register bits. // Strobe bit: #define SET_SR_LE { SR_LE_PORT |= _BV(SR_LE_BIT); } #define CLR_SR_LE { SR_LE_PORT &= ~_BV(SR_LE_BIT); } // Output enable bit: #define SET_SR_OE { SR_OE_PORT |= _BV(SR_OE_BIT); } #define CLR_SR_OE { SR_OE_PORT &= ~_BV(SR_OE_BIT); } // Clock bit: #define SET_SR_CLK { SR_CLK_PORT |= _BV(SR_CLK_BIT); } #define CLR_SR_CLK { SR_CLK_PORT &= ~_BV(SR_CLK_BIT); } // Data line bit: #define SET_SR_DAT { SR_DAT_PORT |= _BV(SR_DAT_BIT); } #define CLR_SR_DAT { SR_DAT_PORT &= ~_BV(SR_DAT_BIT); } void initClock() { // we use 8-bit timer 0 with a prescaler clock/256. TCCR0A = 0x00; // set prescaler and clock source TCCR0B = 0x05; // set prescaler and clock source TCNT0 = 0x80; // give us a little time to complete startup before we start barfing bits TIMSK0 |= 0x01; // enable the timer0 interrupt } unsigned char pBuf0[ BUF_SIZE ]; unsigned char pBuf1[ BUF_SIZE ]; unsigned char *pDisplay; unsigned char *pBacking; // Current bit depth being rendered (ranges from 1 to 2**BPP - 1) unsigned char curDepth; unsigned char curLine; unsigned char curFrame; uint32_t frameSeq; void initBuffers() { memset( pBuf0, 0, BUF_SIZE ); memset( pBuf1, 0, BUF_SIZE ); pDisplay = pBuf0; pBacking = pBuf1; getNextFrame( pDisplay, 0 ); } void initPins() { DDRD = 0xff; //PORTD = 0; DDRC = 0x3f; DDRB = 0x07; SET_COLS( 0xff ); } void init() { cli(); initPins(); curDepth = 1; curLine = 0; curFrame = 0; frameSeq = 0; initBuffers(); initClock(); set_sleep_mode( SLEEP_MODE_IDLE ); sei(); } int main( void ) { init(); while (1) { // if next frame ready if ( curFrame >= getFramesPerUpdate() ) { curFrame = 0; frameSeq++; // swap 'em unsigned char *pTmp = pBacking; pBacking = pDisplay; pDisplay = pTmp; // start new frame getNextFrame( pBacking, frameSeq ); } sleep_cpu(); } return 0; } // // HEY KIDS! Check out our bit pattern! // This represents the index of bits for a board. // ___________________________________________ // | | | | | // 47 ... 32 48 ... 63 15 ... 0 16 ... 31 // C' D A' B // // We want it to look like: // 0 ... 15 16 ... 31 32 ... 47 48 ... 63 // A B C D // // FURTHERMORE each pair of bits is swapped. // How did this happen? Well, some of us suck // at making PCBs. :P // // void writeByte(uint8_t b) { uint8_t i; for ( i = 0; i < 8; i++ ) { if ( (b & _BV(i ^ 0x01)) != 0 ) { SET_SR_DAT; } else { CLR_SR_DAT; } SET_SR_CLK; CLR_SR_CLK; } } void writeBytePrime(uint8_t b) { uint8_t i; for ( i = 8; i > 0; i-- ) { if ( (b & _BV((i-1) ^ 0x01)) != 0 ) { SET_SR_DAT; } else { CLR_SR_DAT; } SET_SR_CLK; CLR_SR_CLK; } } ISR(TIMER0_OVF_vect) { // set timer to 10 cycles (start at 246) TCNT0 = 252; CLR_SR_OE; // fill SR with current line unsigned char bitPlane = 0; // TODO: bit planes unsigned char* pBuf = pDisplay + (BIT_PLANE_SIZE * bitPlane) + (LINE_SIZE * curLine); unsigned char iByte; writeBytePrime(pBuf[5]); //-5 writeBytePrime(pBuf[4]); //-4 writeByte(pBuf[6]); //6 writeByte(pBuf[7]); //7 writeBytePrime(pBuf[1]); //-1 writeBytePrime(pBuf[0]); //-0 writeByte(pBuf[2]); //2 writeByte(pBuf[3]); //3 // columns off SET_COLS( 0xff ); // toggle strobe line SET_SR_LE; CLR_SR_LE; // columns on (7-x to invert) SET_COLS( (0xff ^ (_BV( ((HEIGHT-1)-curLine) ))) ); // increment line curLine++; if (curLine >= HEIGHT) { curFrame++; curLine = 0; } }