This shows you the differences between two versions of the page.
|
projects:dlt [2011/07/19 14:40] bhagman |
projects:dlt [2011/07/19 14:48] (current) bhagman |
||
|---|---|---|---|
| Line 99: | Line 99: | ||
| <file cpp dotScan5x5.pde> | <file cpp dotScan5x5.pde> | ||
| - | #define MAX_BUFFER 256 | + | /** |
| + | * LED Matrix Support Methods | ||
| + | * | ||
| + | */ | ||
| - | #define SOM 0xaa | + | #include <SoftPWM.h> |
| - | #define EOM 0x55 | + | #include <avr/pgmspace.h> |
| - | #define ST_START 0 | + | #define MAX_INTENSITY 48 |
| - | #define ST_GET_LENGTH 1 | + | #define DS_NORTH 0 |
| - | #define ST_GET_DATA 2 | + | #define DS_EAST 1 |
| - | #define ST_GET_EOM 3 | + | #define DS_SOUTH 2 |
| - | #define ST_COMPLETE 4 | + | #define DS_WEST 3 |
| - | #define ST_MSG_ERROR 5 | + | |
| - | uint16_t errorCountMissedSOM = 0; | + | // ** Our Font |
| - | uint8_t msgBuffer[MAX_BUFFER]; | + | extern PROGMEM prog_uint8_t font5x5[]; |
| - | uint8_t getByte(void) | + | // ** Variables |
| + | //uint8_t dotBuf[5]; | ||
| + | uint8_t mBuf[5][5]; | ||
| + | uint8_t dS_orientation = 0; | ||
| + | |||
| + | // ** Constants | ||
| + | // LEDHead Proto | ||
| + | //const uint8_t rows[] = { 14, 15, 16, 17, 18 }; | ||
| + | //const uint8_t cols[] = { 8, 9, 10, 11, 12 }; | ||
| + | |||
| + | const uint8_t rows[] = { 16, 17, 18, 19, 20 }; | ||
| + | const uint8_t cols[] = { 24, 25, 26, 27, 28 }; | ||
| + | |||
| + | |||
| + | void (*tasksFunction)(void); | ||
| + | |||
| + | void dS_setTasksFunction(void (*tFunc)(void)) | ||
| { | { | ||
| - | while (!Serial1.available()); | + | tasksFunction = tFunc; |
| - | return Serial1.read(); | + | |
| } | } | ||
| - | inline void putByte(uint8_t c) | + | |
| + | void dS_tasksDelay(unsigned long ms) | ||
| { | { | ||
| - | Serial1.write(c); | + | unsigned long start = millis(); |
| + | |||
| + | while ((millis() - start) < ms) | ||
| + | { | ||
| + | if (tasksFunction != NULL) | ||
| + | tasksFunction(); | ||
| + | } | ||
| } | } | ||
| - | int16_t getMessage(void) | + | |
| + | void dS_setOrientation(uint8_t o) | ||
| { | { | ||
| - | uint8_t msgParseState; | + | uint8_t col, row; |
| - | uint8_t msgLength = 0; | + | uint8_t source[5][5]; |
| - | uint8_t i = 0; | + | |
| - | uint8_t c; | + | |
| - | msgParseState = ST_START; | + | // I'm sure there is an easier way to do this. |
| - | errorCountMissedSOM = 0; | + | // Just keeping it simple for now. Let me know if you |
| + | // have an easier way to do this. | ||
| - | while ((msgParseState != ST_COMPLETE) && (msgParseState != ST_MSG_ERROR)) | + | // first, get our base bitmap back |
| + | for (col = 0; col < 5; col++) | ||
| { | { | ||
| - | c = getByte(); | + | for (row = 0; row < 5; row++) |
| + | { | ||
| + | switch (dS_orientation) | ||
| + | { | ||
| + | case DS_NORTH: | ||
| + | source[col][row] = mBuf[col][row]; | ||
| + | break; | ||
| + | case DS_EAST: | ||
| + | source[col][row] = mBuf[4-row][col]; | ||
| + | break; | ||
| + | case DS_SOUTH: | ||
| + | source[col][row] = mBuf[4-col][4-row]; | ||
| + | break; | ||
| + | case DS_WEST: | ||
| + | source[col][row] = mBuf[row][4-col]; | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | dS_orientation = o; | ||
| - | switch (msgParseState) | + | // now remap |
| + | |||
| + | for (col = 0; col < 5; col++) | ||
| + | { | ||
| + | for (row = 0; row < 5; row++) | ||
| { | { | ||
| - | case ST_START: | + | switch (dS_orientation) |
| - | if (c == SOM) | + | { |
| - | msgParseState = ST_GET_LENGTH; | + | case DS_NORTH: |
| - | else | + | mBuf[col][row] = source[col][row]; |
| - | errorCountMissedSOM++; | + | break; |
| - | break; | + | case DS_EAST: |
| + | mBuf[4-row][col] = source[col][row]; | ||
| + | break; | ||
| + | case DS_SOUTH: | ||
| + | mBuf[4-col][4-row] = source[col][row]; | ||
| + | break; | ||
| + | case DS_WEST: | ||
| + | mBuf[row][4-col] = source[col][row]; | ||
| + | break; | ||
| - | case ST_GET_LENGTH: | + | /* |
| - | msgLength = c; | + | case DS_NORTH: |
| - | if (c == 0) | + | mBuf[col][row] = source[col][row]; |
| - | msgParseState = ST_GET_EOM; | + | break; |
| - | else | + | case DS_EAST: |
| - | msgParseState = ST_GET_DATA; | + | mBuf[col][row] = source[4-row][col]; |
| - | break; | + | break; |
| + | case DS_SOUTH: | ||
| + | mBuf[col][row] = source[4-col][4-row]; | ||
| + | break; | ||
| + | case DS_WEST: | ||
| + | mBuf[col][row] = source[row][4-col]; | ||
| + | break; | ||
| + | */ | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| - | case ST_GET_DATA: | ||
| - | msgBuffer[i++] = c; | ||
| - | if (i == msgLength) | ||
| - | msgParseState = ST_GET_EOM; | ||
| - | break; | ||
| - | case ST_GET_EOM: | + | void setPeriod(uint32_t microseconds) |
| - | if (c == EOM) | + | { |
| - | msgParseState = ST_COMPLETE; | + | uint8_t clockSelect; |
| - | else | + | #define RESOLUTION 65536 |
| - | msgParseState = ST_MSG_ERROR; | + | |
| - | break; | + | uint32_t cycles = (F_CPU/1000 * microseconds) / 1000; |
| + | |||
| + | if (cycles < RESOLUTION) clockSelect = CLOCK_NO_PRESCALE; // no prescale, full xtal | ||
| + | else if ((cycles >>= 3) < RESOLUTION) clockSelect = CLOCK_PRESCALE_8; // prescale by /8 | ||
| + | else if ((cycles >>= 3) < RESOLUTION) clockSelect = CLOCK_PRESCALE_64; // prescale by /64 | ||
| + | else if ((cycles >>= 2) < RESOLUTION) clockSelect = CLOCK_PRESCALE_256; // prescale by /256 | ||
| + | else if ((cycles >>= 2) < RESOLUTION) clockSelect = CLOCK_PRESCALE_1024; // prescale by /1024 | ||
| + | else cycles = RESOLUTION - 1, clockSelect = CLOCK_PRESCALE_1024; // request was out of bounds, set as maximum | ||
| + | |||
| + | Timer1.setMode(0b0100); // CTC mode (OCR1A = TOP) | ||
| + | Timer1.setOCR(CHANNEL_A, cycles); // must set the OCR AFTER mode | ||
| + | Timer1.setClockSource(clockSelect); | ||
| + | } | ||
| + | |||
| + | |||
| + | // ** Our interrupt routine | ||
| + | void dotScan(void) | ||
| + | { | ||
| + | static uint8_t currBuf[5][5]; | ||
| + | static uint8_t currCol = 0; | ||
| + | uint8_t i, j; | ||
| + | |||
| + | // DEBUG | ||
| + | // digitalWrite(13, 1); | ||
| + | |||
| + | // Turn off the last column | ||
| + | if (currCol == 0) | ||
| + | digitalWrite(cols[4], 0); | ||
| + | else | ||
| + | digitalWrite(cols[currCol-1], 0); | ||
| - | } // switch | + | // now turn on rows (before turning on column) |
| - | } // while (msgParseState) | + | |
| - | if (msgParseState == ST_COMPLETE) | + | // Binary version |
| - | return msgLength; | + | // //for (i=0; i<5; i++) |
| + | // // digitalWrite(rows[i], !((currBuf[currCol] >> i) & 1)); | ||
| + | //PORTA &= 0b11100000; // clear the port first | ||
| + | //PORTA |= currBuf[currCol] & 0b00011111; | ||
| + | |||
| + | // PWM version | ||
| + | // for (i=0; i<5; i++) | ||
| + | // if ((currBuf[currCol] >> i) & 1) | ||
| + | // SoftPWMSet(rows[i], intensity, 1); | ||
| + | // else | ||
| + | // { | ||
| + | // SoftPWMSet(rows[i], 0, 1); | ||
| + | // digitalWrite(rows[i], 0); //set immediately | ||
| + | // } | ||
| + | |||
| + | // Grayscale PWM version | ||
| + | for (i = 0; i < 5; i++) | ||
| + | { | ||
| + | SoftPWMSet(rows[i], currBuf[currCol][i], 1); | ||
| + | } | ||
| + | |||
| + | // turn on next column | ||
| + | digitalWrite(cols[currCol], 1); | ||
| + | |||
| + | currCol++; | ||
| + | |||
| + | if (currCol >= 5) | ||
| + | { | ||
| + | // blit in the new screen | ||
| + | for (i = 0; i < 5; i++) | ||
| + | for (j = 0; j < 5; j++) | ||
| + | currBuf[i][j] = mBuf[i][j]; | ||
| + | |||
| + | // reset to the first column | ||
| + | currCol = 0; | ||
| + | } | ||
| + | |||
| + | // DEBUG | ||
| + | // digitalWrite(13, 0); | ||
| + | } | ||
| + | |||
| + | |||
| + | void dS_rightToLeftChar(uint8_t ch, uint8_t intensity, int dtime) | ||
| + | { | ||
| + | uint8_t i, j, k; | ||
| + | uint8_t newcol; | ||
| + | |||
| + | // feed in one column first | ||
| + | |||
| + | for (i = 0; i < 4; i++) | ||
| + | for (j = 0; j < 5; j++) | ||
| + | mBuf[i][j] = mBuf[i+1][j]; | ||
| + | |||
| + | for (j = 0; j < 5; j++) | ||
| + | mBuf[4][j] = 0; | ||
| + | |||
| + | dS_tasksDelay(dtime); | ||
| + | |||
| + | // now shift in each column of the char | ||
| + | for (k = 0; k < 5; k++) | ||
| + | { | ||
| + | // shift existing | ||
| + | for (i = 0; i < 4; i++) | ||
| + | for (j = 0; j < 5; j++) | ||
| + | mBuf[i][j] = mBuf[i+1][j]; | ||
| + | |||
| + | // now load a new column | ||
| + | // dotBuf[4] = pgm_read_byte(font5x5 + ((uint8_t)(c - 32))*5 + i); | ||
| + | newcol = pgm_read_byte(font5x5 + ((uint8_t)(ch - 32))*5 + k); | ||
| + | |||
| + | for (j = 0; j < 5; j++) | ||
| + | { | ||
| + | if (newcol & 1) | ||
| + | mBuf[4][j] = intensity; | ||
| + | else | ||
| + | mBuf[4][j] = 0; | ||
| + | newcol >>= 1; | ||
| + | } | ||
| + | |||
| + | dS_tasksDelay(dtime); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | void dS_loadChar(uint8_t ch, uint8_t intensity) | ||
| + | { | ||
| + | // c = char | ||
| + | uint8_t i, j; | ||
| + | uint8_t newcol; | ||
| + | |||
| + | if (ch >= 32 && ch <= 90) | ||
| + | { | ||
| + | for (i = 0; i < 5; i++) | ||
| + | { | ||
| + | newcol = pgm_read_byte(font5x5 + ((uint8_t)(ch - 32))*5 + i); | ||
| + | |||
| + | for (j = 0; j < 5; j++) | ||
| + | { | ||
| + | if (newcol & 1) | ||
| + | mBuf[i][j] = intensity; | ||
| + | else | ||
| + | mBuf[i][j] = 0; | ||
| + | newcol >>= 1; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| else | else | ||
| - | return -1; | + | { |
| + | for (i = 0; i < 5; i++) | ||
| + | for (j = 0; j < 5; j++) | ||
| + | mBuf[i][j] = 0; | ||
| + | } | ||
| } | } | ||
| - | void putMessage(uint8_t data[], uint16_t length) | + | void dS_loadmBuf(uint8_t data, uint8_t col, uint8_t row) |
| + | { | ||
| + | if (col > 4) | ||
| + | col = 4; | ||
| + | if (row > 4) | ||
| + | row = 4; | ||
| + | |||
| + | switch (dS_orientation) | ||
| + | { | ||
| + | case DS_NORTH: | ||
| + | mBuf[col][row] = data; | ||
| + | break; | ||
| + | case DS_EAST: | ||
| + | mBuf[4-row][col] = data; | ||
| + | break; | ||
| + | case DS_SOUTH: | ||
| + | mBuf[4-col][4-row] = data; | ||
| + | break; | ||
| + | case DS_WEST: | ||
| + | mBuf[row][4-col] = data; | ||
| + | break; | ||
| + | |||
| + | /* | ||
| + | case DS_NORTH: | ||
| + | mBuf[col][row] = load[col][row]; | ||
| + | break; | ||
| + | case DS_EAST: | ||
| + | mBuf[col][row] = load[4-row][col]; | ||
| + | break; | ||
| + | case DS_SOUTH: | ||
| + | mBuf[col][row] = load[4-col][4-row]; | ||
| + | break; | ||
| + | case DS_WEST: | ||
| + | mBuf[col][row] = load[row][4-col]; | ||
| + | break; | ||
| + | */ | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | void dS_loadmBuf(uint8_t *columnData, uint8_t col) | ||
| + | { | ||
| + | uint8_t row; | ||
| + | |||
| + | for (row = 0; row < 5; row++) | ||
| + | { | ||
| + | dS_loadmBuf(columnData[row], col, row); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void dS_loadmBuf(uint8_t *load) | ||
| + | { | ||
| + | // loads the mBuf, according to current orientation (NORTH = TOP) | ||
| + | uint8_t col, row; | ||
| + | |||
| + | for (col = 0; col < 5; col++) | ||
| + | { | ||
| + | dS_loadmBuf(&load[col * 5], col); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | void dS_changeIntensity(int8_t changeAmount) | ||
| + | { | ||
| + | uint8_t col, row; | ||
| + | int8_t newval; | ||
| + | |||
| + | for (col = 0; col < 5; col++) | ||
| + | { | ||
| + | for (row = 0; row < 5; row++) | ||
| + | { | ||
| + | newval = mBuf[col][row]; | ||
| + | if (newval > 0) | ||
| + | { | ||
| + | newval += changeAmount; | ||
| + | if (newval < 0) | ||
| + | newval = 0; | ||
| + | else if (newval > MAX_INTENSITY) | ||
| + | newval = MAX_INTENSITY; | ||
| + | |||
| + | mBuf[col][row] = newval; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | void dotScanSetup(void) | ||
| { | { | ||
| uint8_t i; | uint8_t i; | ||
| - | if (length > 256) | + | dS_orientation = DS_NORTH; |
| - | length = 256; | + | tasksFunction = NULL; |
| - | putByte(SOM); | + | |
| - | putByte(length); | + | // For binary version |
| - | i = 0; | + | //DDRA = 0b00011111; |
| - | while (i < length) | + | //PORTA = 0b00011111; |
| - | putByte(data[i++]); | + | |
| - | putByte(EOM); | + | SoftPWMBegin(SOFTPWM_INVERTED); |
| + | for (i=0; i<5; i++) | ||
| + | SoftPWMSet(rows[i], 0); | ||
| + | |||
| + | for (i=0; i<5; i++) | ||
| + | { | ||
| + | // Needed for binary version: | ||
| + | // pinMode(rows[i], OUTPUT); | ||
| + | // digitalWrite(rows[i], 1); | ||
| + | pinMode(cols[i], OUTPUT); | ||
| + | digitalWrite(cols[i], 0); | ||
| + | } | ||
| + | |||
| + | // Timer1.initialize(3333); | ||
| + | Timer1.attachInterrupt(INTERRUPT_COMPARE_MATCH_A, dotScan); | ||
| + | setPeriod(3333); | ||
| } | } | ||
| </file> | </file> | ||