/* * main.c * * Created: 06.01.2015 11:41:12 * Author: freelancer */ #define F_CPU 16000000UL // 16 MHz #include #include #include #include #define DATA_COL PB0 #define DATA_ROW PD2 #define STROBE PD3 #define OE_WHITE PD4 #define OE_BLACK PD5 #define CLK_COL PD6 #define CLK_ROW PD7 #define LED PB1 // red LED on expansion board // TODO: switch PD6 and PD4 to allow timer pulse generating for both OE enum { ROWS = 16, // number of rows of a panel COLS = 40, // number of columns of a panel START_BIT = 7, // 1: indicates start of UART command VAL_BIT = 0, // 0: black, 1: white FILL_BIT = 1, // 0: set one pixel to $color, 1: sets whole screen to $color SYNC_BIT = 2 // 0: only set pixel in framebuffer, 1: update screen too }; bool SetPixel(uint8_t row, uint8_t col, uint8_t val); // sets one pixel in the framebuffer to a color void SetFrame(uint8_t val); // sets the whole framebuffer to a color void RefreshRow(uint8_t row); // outputs a row of the framebuffer to the screen void RefreshRowTimer(uint8_t row); // call 3 times to output a row of the framebuffer fast with timer pulses uint8_t buffer_whiteA[16][6] = {{0}}; // diff. framebuffer white A, 16 column and 40 rows (as 2x24bit in 3 bytes) uint8_t buffer_whiteB[16][6] = {{0}}; // diff. framebuffer white B, 16 column and 40 rows (as 2x24bit in 3 bytes) uint8_t buffer_blackA[16][6] = {{0}}; // diff. framebuffer black A, 16 column and 40 rows (as 2x24bit in 3 bytes) uint8_t buffer_blackB[16][6] = {{0}}; // diff. framebuffer black B, 16 column and 40 rows (as 2x24bit in 3 bytes) uint8_t selector = 0; // dual-buffer state; 0 = A is receiving and B is outputting int main(void) { uint8_t row_byte; uint8_t col_byte; uint8_t val_byte; uint8_t tmp_byte; // buffer for incoming UART bytes uint8_t packets = 0; // count incoming packets uint8_t syncline = 0; // sync flag; 0: no sync ongoing, 1-16: current line being synced /* init I/O-ports */ DDRB |= (1<= ROWS) || (col >= COLS)) // out of screen { return false; } display = col / 20; col -= display * 20; colgroup = display * 3; while(col >= CHAR_BIT) // select byte { colgroup += 1; col -= CHAR_BIT; } if(selector) // write to buffer B { if(val) // determine color { buffer_whiteB[row][colgroup] |= (1<<(CHAR_BIT-(col+1))); buffer_blackB[row][colgroup] &=~ (1<<(CHAR_BIT-(col+1))); /* FIXME: bit order is changed this way because of the way the data is arranged in memory */ } else { buffer_whiteB[row][colgroup] &= ~(1<<(CHAR_BIT-(col+1))); buffer_blackB[row][colgroup] |= (1<<(CHAR_BIT-(col+1))); } } else // write to buffer A { if(val) // determine color { buffer_whiteA[row][colgroup] |= (1<<(CHAR_BIT-(col+1))); buffer_blackA[row][colgroup] &=~ (1<<(CHAR_BIT-(col+1))); } else { buffer_whiteA[row][colgroup] &= ~(1<<(CHAR_BIT-(col+1))); buffer_blackA[row][colgroup] |= (1<<(CHAR_BIT-(col+1))); } } return true; // pixel successfully modified } void SetFrame(uint8_t val) { uint8_t filler; uint8_t i; uint8_t j; if(val) // determine the filling color { filler = 255; } else { filler = 0; } if(selector) // fill buffer B { for(i = 0; i < 16; i++) { for(j = 0; j < 6; j++) { buffer_whiteB[i][j] = filler; buffer_blackB[i][j] = ~filler; } } } else // fill buffer A { for(i = 0; i < 16; i++) { for(j = 0; j < 6; j++) { buffer_whiteA[i][j] = filler; buffer_blackA[i][j] = ~filler; } } } } void RefreshRow(uint8_t row) { uint8_t i; uint8_t frame_0; uint8_t frame_1; uint8_t frame_2; uint8_t frame_3; uint8_t frame_4; uint8_t frame_5; if(selector) // copy values from output-framebuffer { frame_0 = buffer_whiteA[row][0]; frame_1 = buffer_whiteA[row][1]; frame_2 = buffer_whiteA[row][2]; frame_3 = buffer_whiteA[row][3]; frame_4 = buffer_whiteA[row][4]; frame_5 = buffer_whiteA[row][5]; for(i = 0; i < 6; i++) { buffer_whiteA[row][i] = 0; } } else { frame_0 = buffer_whiteB[row][0]; frame_1 = buffer_whiteB[row][1]; frame_2 = buffer_whiteB[row][2]; frame_3 = buffer_whiteB[row][3]; frame_4 = buffer_whiteB[row][4]; frame_5 = buffer_whiteB[row][5]; for(i = 0; i < 6; i++) { buffer_whiteB[row][i] = 0; } } for(i=0; i<16; i++) // send 16 COL pulse { if(i == (15-row)) { PORTB |= (1<