#include #include "TimerOne.h" #include #define BAUD 9600 //TLC5940NT pin definitions #define VPRG 2 #define SIN 11 #define SCLK 13 #define XLAT 4 #define BLANK 5 #define DCPRG 6 #define GSCLK 7 #define id 0 #define first_flash true // start reading from the first byte (address 0) of the EEPROM int address = 300; int vuelta = 0; #define intensidad 252 //0 - 255 const byte remap[7][5] = { //Mapeo de los leds {0,7,18,25,36}, {1,8,19,26,37}, {2,9,20,27,38}, {3,10,21,32,39}, {4,11,22,33,40}, {5,16,23,34,41}, {6,17,24,35,42}, }; int modo= 0; byte numero[10][7] = { { B01110, B10001, B10011, B10101, B11001, B10001, B01110}, //48 = '0' { B00100, B01100, B10100, B00100, B00100, B00100, B11111}, //49 = '1' { B01110, B10001, B00001, B00110, B01000, B10000, B11111}, //50 = '2' { B01110, B10001, B00001, B01110, B00001, B10001, B01110}, //51 = '3' { B00010, B00110, B01010, B10010, B11111, B00010, B00010}, //52 = '4' { B11111, B10000, B11110, B00001, B00001, B10001, B01110}, //53 = '5' { B01110, B10001, B10000, B11110, B10001, B10001, B01110}, //54 = '6' { B11111, B00001, B00010, B00100, B01000, B10000, B10000}, //55 = '7' { B01110, B10001, B10001, B01110, B10001, B10001, B01110}, //56 = '8' { B01110, B10001, B10001, B01111, B00001, B10001, B01110}, //57 = '9' }; byte caracterA[13][7] = {{ B01110, B10001, B10001, B11111, B10001, B10001, B10001}, //65 = 'A' { B11110, B10001, B10001, B11110, B10001, B10001, B11110}, //66 = 'B' { B01110, B10001, B10000, B10000, B10000, B10001, B01110}, //67 = 'C' { B11110, B10001, B10001, B10001, B10001, B10001, B11110}, //68 = 'D' { B11111, B10000, B10000, B11110, B10000, B10000, B11111}, //69 = 'E' { B11111, B10000, B10000, B11110, B10000, B10000, B10000}, //70 = 'F' { B01110, B10001, B10000, B10111, B10001, B10001, B01110}, //71 = 'G' { B10001, B10001, B10001, B11111, B10001, B10001, B10001}, //72 = 'H' { B11111, B00100, B00100, B00100, B00100, B00100, B11111}, //73 = 'I' { B00001, B00001, B00001, B00001, B10001, B10001, B01110}, //74 = 'J' { B10001, B10010, B10100, B11000, B10100, B10010, B10001}, //75 = 'K' { B10000, B10000, B10000, B10000, B10000, B10000, B11111}, //76 = 'L' { B10001, B11011, B10101, B10001, B10001, B10001, B10001}, //77 = 'M' }; byte caracterB[14][7] = {{ B10001, B11001, B10101, B10011, B10001, B10001, B10001}, //78 = 'N' { B01110, B10001, B10001, B10001, B10001, B10001, B01110}, //79 = 'O' { B11110, B10001, B10001, B11110, B10000, B10000, B10000}, //80 = 'P' { B01110, B10001, B10001, B10001, B10101, B10101, B01110}, //81 = 'Q' { B11110, B10001, B10001, B11110, B10100, B10010, B10001}, //82 = 'R' { B01110, B10001, B10000, B01110, B00001, B10001, B01110}, //83 = 'S' { B11111, B00100, B00100, B00100, B00100, B00100, B00100}, //84 = 'T' { B10001, B10001, B10001, B10001, B10001, B10001, B01110}, //85 = 'U' { B10001, B10001, B10001, B10001, B10001, B01010, B00100}, //86 = 'V' { B10001, B10001, B10001, B10001, B10101, B10101, B01010}, //87 = 'W' { B10001, B10001, B01010, B00100, B01010, B10001, B10001}, //88 = 'X' { B10001, B10001, B01010, B00100, B00100, B00100, B00100}, //89 = 'Y' { B11111, B00001, B00010, B00100, B01000, B10000, B11111}, //90 = 'Z' { B10000, B10000, B10000, B10010, B01010, B00110, B11110}, //flecha = 35 }; byte espacio[7] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000}; //32 = ' ' //byte sonrisa[7] = { B00000, B01010, B01010, B00000, B10001, B01110, B00000}; //Sonrisa byte test[7] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111};//0x01 byte test1[7] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111};//0x01 // Holds the current colour level for each of the buttons int levelW[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Variables for interpreting the serial commands byte command[64] = { ' ', ' ', 'B', 'E', 'N', 'V', 'I', 'N', 'G', 'U', 'D', 'E', 'S', ' ', ' ', ' ', ' ', 'B', 'E', 'N', 'V', 'I', 'N', 'G', 'U', 'T', 'S', ' ', 'A', 'L', ' ', ' ', ' ', ' ', 'C', 'I', 'B', 'E', 'R', 'N', 'A', 'R', 'I', 'U', 'M', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; byte finish = 1; byte count = 0x00; boolean save=false; boolean sincro=false; boolean bloqueo=false; boolean update = false; unsigned long time=0; // Transfer a character out over hardware SPI char spi_transfer(volatile byte data) { SPDR = data; // Start the transmission while (!(SPSR & (1<='0'))||((val<'N')&&(val>='A'))||((val<='Z')&&(val>='N'))||((val<'n')&&(val>='a'))||((val<='z')&&(val>='n'))) { command[count] = val; count++; bloqueo = false; save = true; update = true; } #else else if (val== (id + 0x0F)) sincro = true; else if (sincro) {command[0] = val; bloqueo = false; sincro = false;} else Serial.write(val); #endif } // If the serial buffer is getting too close to full, keep executing the parsing until it falls below a given level // This might cause flicker, or even dropped messages, but it should prevent a crash. } void setup() { // Start the serial port Serial.begin(BAUD); delay(10); //Setup data directions, and set everything to the correct initial levels, // For TLC5940 pinMode(VPRG, OUTPUT); pinMode(SIN, OUTPUT); pinMode(SCLK, OUTPUT); pinMode(XLAT, OUTPUT); pinMode(BLANK, OUTPUT); pinMode(DCPRG, OUTPUT); pinMode(GSCLK, OUTPUT); pinMode(MISO, INPUT); pinMode(SS,OUTPUT); digitalWrite(SS,HIGH); //disable device digitalWrite(SIN, LOW); digitalWrite(SCLK, LOW); digitalWrite(XLAT, LOW); digitalWrite(VPRG, LOW); digitalWrite(BLANK, HIGH); digitalWrite(GSCLK, HIGH); digitalWrite(DCPRG, LOW); // USE EEPROM DC register if LOW //////// LECTURA DE EEPROM //////// #if id == 0 delay(100); #if first_flash EEPROM.write(address, 48); for (int i = 0; i<48; i++) EEPROM.write(address + 1 + i, command[i]); // grabamos en eeprom el caracter #endif count = EEPROM.read(address); if (count>63) count = 63; for(int i = 0; i=5000)||(update)) { update = false; //for (int i = 1; i= count) Serial.write(' '); else Serial.write(command[(vuelta*limit) + i]); } // Serial.println(); } #endif //letra(test1,test1); if (!bloqueo) { time=millis(); if (command[limit*vuelta]==32) modo=1; //Espacio else if ((command[limit*vuelta]<='9')&&(command[limit*vuelta]>='0')) modo=2; //Numeros else if ((command[limit*vuelta]<'N')&&(command[limit*vuelta]>='A')) modo=3; //Letras de la 'A' a la 'M' else if ((command[limit*vuelta]<='Z')&&(command[limit*vuelta]>='N')) modo=5; //Letras de la 'N' a la 'Z' y la flecha else if ((command[limit*vuelta]<'n')&&(command[limit*vuelta]>='a')) modo=4; //Letras de la 'a' a 'm' else if ((command[limit*vuelta]<='z')&&(command[limit*vuelta]>='n')) modo=6; //Letras de la 'n' a la 'z' //else modo=7; switch (modo) { case 1: if (finish) {letra(espacio,espacio); modo=0;} break; case 2: if (finish) {letra(numero[command[limit*vuelta] - '0'],espacio); modo=0;} break; case 3: if (finish) {letra(caracterA[command[limit*vuelta] - 'A'],espacio); modo=0;} break; case 4: if (finish) {letra(caracterA[command[limit*vuelta] - 'a'],espacio); modo=0;} break; case 5: if (finish) {letra(caracterB[command[limit*vuelta] - 'N'],espacio); modo=0;} break; case 6: if (finish) {letra(caracterB[command[limit*vuelta] - 'n'],espacio); modo=0;} break; //case 7: if (finish) {letra(sonrisa,espacio); modo=0;} break; case 8: letra(espacio,espacio); if (modo==8) modo=0; finish=1; break; case 9: letra(test,espacio); if (modo==9) modo=0; finish=1; break; } bloqueo = true; int n = 0; if (count > 3*limit) n = 3; else if (count > 2*limit) n = 2; else if (count > limit) n = 1; else n = 0; if (vuelta < n) vuelta++; else vuelta = 0; } } void makemagic(){ setGreysW1(); feedPorts(); setGreysW2(); feedPorts(); } void setGreysW1() { digitalWrite(BLANK, HIGH); digitalWrite(XLAT,LOW); for(int i = 21; i>=0; i--){ spi_transfer(0x00); spi_transfer( (0x00) | ((levelW[2*i] & 0x0F00) >> 8) ); spi_transfer( levelW[2*i] & 0xFF); } digitalWrite(XLAT,HIGH); digitalWrite(XLAT,LOW); digitalWrite(BLANK, LOW); } void setGreysW2() { digitalWrite(BLANK, HIGH); digitalWrite(XLAT,LOW); for(int i = 21; i>=0; i--){ spi_transfer( (levelW[2*i+1] & 0x0FF0) >> 4 ); spi_transfer( ((levelW[2*i+1] & 0xF) << 4) | (0x00) ); spi_transfer(0x00); } digitalWrite(XLAT,HIGH); digitalWrite(XLAT,LOW); digitalWrite(BLANK, LOW); } void feedPorts() { // Clock for TLC5940's PWM digitalWrite(BLANK, HIGH); digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle for (int i=0; i<4096; i++) { pulseGSCLK(); } } void pulseGSCLK() { //ultra fast pulse trick, using digitalWrite caused flickering PORTD |= 0x80 ; // bring pin 7 high, but don't touch any of the other pins in PORTB //16 nanosecs is the min pulse width for the 5940, but no pause seems needed here PORTD &= 0x7F; // bring pin 7 low without touching the other pins in PORTB } byte letra(byte let[7], byte let_ant[7]) { byte letbool=0; byte let_new[7] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000}; for(byte j = 1; j <6; ++j){ for(byte h = 0; h <7; ++h){ let_new[h]=((0X1F&(let_ant[h]<>(5-j))); } letbool=0; for(byte x = 0; x < 7; ++x){ //Actualizacion de los leds for(byte y = 0; y <5; ++y){ if (0x01&let_new[letbool]>>y) levelW[remap[x][y]] = 16*intensidad; else levelW[remap[x][y]] = 0; } //Serial.println(let_new[letbool], BIN); ++letbool; } for(int i = 0; i <20; ++i) makemagic(); } } byte letraWrite(byte let[7]) { byte letbool=0; letbool=0; for(byte x = 0; x < 7; ++x){ //Actualizacion de los leds for(byte y = 0; y <5; ++y){ if (0x01&let[letbool]>>y) levelW[remap[x][y]] = 16*intensidad; else levelW[remap[x][y]] = 0; } ++letbool; } for(int i = 0; i <20; ++i) makemagic(); }