/* TODO: Add video games and code to support 3D use program memory for constant variables like DIR_LUT */ /* Fudge factors LED ROM update using while(!(SPSR & (1< #include //allows software delays #include //allows easy eeprom access #include //includes from AVRlib to make USART traffic more streamlined #include "AvrLib/buffer.h" #include "AvrLib/rprintf.h" #include "AvrLib/uart.h" //Bit Operation Macros //------------------------------------- //single command to send a byte to SPI, can also be used to read since data #define SPI_SEND(DATA) SPDR=(DATA);while(!(SPSR&(1<> (N) & 1u) //read a bit in U #define SET(U, N) ((void)((U) |= 1u << (N))) //set a bit in U #define CLR(U, N) ((void)((U) &= ~(1u << (N)))) //clear a bit in U #define FLIP(U, N) ((void)((U) ^= 1u << (N))) //flip a bit in U #define SELECT_ALL() PORTD&=~(_BV(PD3)|_BV(PD4)|_BV(PD5)|_BV(PD2)) //select all roms #define DESELECT_ALL() PORTD|=(_BV(PD3)|_BV(PD4)|_BV(PD5)|_BV(PD2)) //deselect all roms...also writes to them #define ROM_CONTROL() PORTD&=~_BV(PD7);DDRC=0 //allow ROM control and disable direct control #define SELECT_ROM(U) PORTD&=~_BV(PD2+U) //enable a specific ROM #define DIR_CONTROL() SPCR=0;DESELECT_ALL();PORTD|=_BV(PD7);DDRC=0xFF //set up dir control and disable ROM control #define LATCH_LEDS() PORTB|=_BV(PB4) //allow LEDs to update values #define UNLATCH_LEDS() PORTB&=~_BV(PB4) //lock LED values //sets whether the display toggles through the modes uint8_t toggleMode=0; //Serial Command Character Set. //------------------------------------- #define ADD_PIC 'A' #define END_BLOCK 'E' #define GET_PERIOD 'P' #define LIST_PICS 'L' #define DEL_PIC 'D' #define SHOW_PIC 'S' #define CHANGE_MODE 'C' #define MESSAGE 'M' #define SET_TIME 'T' #define SET_TEXT 'B' //EEPROM instructions //------------------------------------- #define SPI_READ 0b00000011 //Read data from memory array beginning at selected address #define SPI_WRITE 0b00000010 //Write data to memory array beginning at selected address #define SPI_WREN 0b00000110 //Set the write enable latch (enable write operations) #define SPI_RDSR 0b00000101 //Read STATUS register //EEPROM storage setup //------------------------------------- //Internal EEprom used just for Image bookkeeping. uint8_t EEMEM imageNumPtr=0; //1st 2 bytes is number of pictures (256 max) need second byte since 0 is value uint8_t EEMEM isbits3DPtr[32]; //1 byte with each bit telling whether each frame is 2D or 3D. 32*8 = 256...so this corresponds to all the frames uint8_t EEMEM startPtr[256]; //256 bytes with the start of each image, the end is the start of the next, if it is the last the end is the max address uint8_t EEMEM repeatPtr[256]; //256 bytes corresponding to 256 frames showing how many times each frame should repeat. uint8_t EEMEM namePtr[1280]; //1280 bytes with 5 bytes to name each image //UART variables/constants //------------------------------------ uint8_t UARTState; uint16_t bytesGot; uint16_t messageSize; uint8_t currentRom; //possible UART States #define GET_PIC_SIZE 1 //Gets number of frames #define GET_PIC 2 //Get data pictures to be stored in eeprom #define GET_REP 3 //Getting number of repetitions for each frame and gets stored in local eeprom #define GET_DIM 4 //2D or 3D(not implemented) picture #define GET_NAME 5 //Gets name of picture #define END_TRANS 6 //Ends transmission #define GET_DEL_ID 7 //Get ID of picture you want to delete #define GET_MODE 8 //Get the mode to transisition to...set method #define GET_PIC_ID 9 //Get PIC_ID from java and setting it in the microcontroller #define GET_HOUR 10 //get hours to set clock #define GET_AMPM 11 //Get PIC_ID from java and setting it in the microcontroller #define GET_DATE 12 //get date to set clock #define GET_DAY 13 //get day to set clock #define GET_MONTH 14 //get month to set clock #define GET_MIN 15 //get to set clock #define GET_TEXT_SIZE 16 //get size of text message #define GET_TEXT_DATA 17 //get text data //CLOCK RELATED VARIABLES //------------------------------------- volatile uint16_t milli = 0; //milliseconds...used for CLOCK /*date keeping variables*/ uint8_t hour = 7; //default hours uint8_t min = 30; //default minutes uint8_t sec = 0; //default seconds uint8_t day =1; uint8_t date = 5; uint8_t month = 0; uint8_t ampm =0;//am is 0 //buffers for message displays uint8_t message1[20]; uint8_t message2[50]; //data to describe an Image/Animation 5 char name max (null terminated) //------------------------------------- typedef struct struct_image{ uint8_t ID;//the unique identifier for the image goes up to 256 uint8_t repetitions;//# of times to repeat frame in animation goes up to 256 uint8_t curRepetitions;//current repetition goes up to 256 //EEPROM addresses are 8bit each representing 512 bytes on the EEPROM that makes up a single frame uint8_t startAddr; //start location in EEPROM epresents goes up to 256 uint8_t endAddr; //the adress after the last frame goes up to 256 uint8_t index; //current frame } Image; Image curImage; //image currenting being displayed //Miscellaneous //------------------------------------- #define ICP_DELAY 30 //time between pin going low and first instr in interrupt. Fudge factor that reduces error...we add this to our spin period time that is reset in the interrupt #define SCREEN_SIZE 512 //128 bits*128 angles/4 EEPROMS(8bits each) =128*128/(4*32)=512 bytes per eeprom... uint16_t angle; // angular resolution uint16_t imageNum;//name of image uint16_t counter;//used to keep track of position in scrolling text uint16_t counter1;//used to keep track of position in scrolling text volatile uint8_t lineNum=0; //line number from 0-ANG_RES-1 volatile uint32_t spinPeriod;//period of rotation not needed necesarily but can be used for debug info volatile uint32_t nextTime;//time of next update volatile uint32_t increment;//amount between updates volatile uint8_t overflows1;//number of times timer1 overflows before getting into interrupt //Look up table for direct control uint8_t DIR_LUT[96]={0,8,16, 24, 32,255, 48, 56, 255, 112, 104, 96, 88, 86, 72, 64, 1, 9, 17, 25, 255, 41, 255, 255, 121, 113, 105, 97, 89, 81, 255, 255, 2, 10, 18, 26, 34, 42, 50, 58, 122, 114, 106, 98, 90, 82, 255, 255, 3, 11, 19, 27, 35, 255, 255, 59, 123, 255, 107, 255, 255, 83, 255, 255, 4, 12, 20, 28, 255,44, 52, 60, 124, 116, 108, 100, 92, 84, 68, 255, 5, 13, 21, 255, 255, 45, 29, 61, 255, 117, 109, 101, 93, 85, 77, 69}; //Controls What the Device is Doing //-------------------------------------- uint8_t masterState; //possible states #define START 0 //start state...can be any of the ones below #define TEST_RGB 0 //tests RGB, Displays alternating red, green, blue lines #define ROM_ANIMATE 2 //runs animation that is stored on the eeprom #define RECEIVING 1 //stop display for update duration #define CLOCK 3 //Displays a clock. Default time is set up above under CLOCK RELATED VARIABLES #define TEXT 4 //Displays a clock. Default time is set up above under CLOCK RELATED VARIABLES #define CLOCK2 5 //display secondary clock face //PROTOTYPES //--------------------------------------- void init(void); //initializes values and settings void startRead(uint8_t addr); //initialize EEPROM read void startWrite(uint8_t currentRom,uint8_t addr,uint8_t isSecondHalf );//initialize EEPROM in preparation for a write void spiInit(void); //Resets the eeproms and turns on SPI control. When you have Direct Control, you can have the SPI running. void updateFromROM(Image * image,uint8_t line); //read bytes to LEDs void displayImage(Image* image,uint8_t ID); //prepare to display image from EEPROMs void handleSerial(cBuffer* rxBuff); //react to received byte void sendMsg(char * str,uint8_t len); //send formatted debug info void setRGB(uint8_t* buff,uint8_t LED,uint8_t color); //sets the RGB colors...buff holds the LED information. It gets updated by turning on LED(a number) with the designated color. void chgMode(uint8_t mode); //changes the masterState and changes initialization so they work void simpleTest(uint8_t line); //Test that toggles the 1 LED next to the microcontroller on and off void updateTestRGB(uint8_t line); // Runs under the TEST_RGB masterState... void updateClock(uint8_t hours, uint8_t minutes, uint8_t seconds); //Runs under the CLOCK masterState void StrCpyRAM(char* to,char* from); //copy a string from one mem location to another void updateText(uint8_t* message, uint8_t height, uint8_t line, uint8_t type, uint8_t color, uint8_t length, uint8_t time);//update display in text mode //************************************************************************ //Functions //************************************************************************ //CHANGE MODE //--------------------------------------- //changes the masterState and initializes the board so that they will work correctly (Dir VS EEprom and SPI control). Also angular resolution is set here. //resolution must be 128 for EEPROMs becuase of image sizing but can be set arbitrarily for other modes. void chgMode(uint8_t mode){ masterState=mode; switch(mode){ case TEST_RGB: DIR_CONTROL(); angle=512; break; case ROM_ANIMATE: ROM_CONTROL(); spiInit(); angle=128; break; case RECEIVING: ROM_CONTROL(); spiInit(); angle=128; break; case CLOCK: DIR_CONTROL(); angle=180; break; case CLOCK2: DIR_CONTROL(); angle=180; break; case TEXT: DIR_CONTROL(); angle=255; break; default: masterState=CLOCK; DIR_CONTROL(); angle=180; break; } } //SEND MESSAGE //--------------------------------------- //Sends the message along with its length and a start char void sendMsg(char * str,uint8_t len){ uartSendByte(MESSAGE); uartSendByte(len); rprintfStr(str); //prints it to the uart } //send a list of pics and the start char void listPics(void){ uartSendByte('C'); uartSendByte(imageNum); //read image name for(int i=0;i>24)&0xff); uartSendByte((spinPeriod>>16)&0xff); uartSendByte((spinPeriod>>8)&0xff); uartSendByte(spinPeriod&0xff); break; case LIST_PICS://list currently stored pictures listPics(); break; case DEL_PIC://remove last received picture all that must be done is decrement the num of images if(imageNum>0){ chgMode(START); sendMsg("Deleting Pic",12); imageNum--; eeprom_write_byte(&imageNumPtr,imageNum); listPics(); } break; case SHOW_PIC:// get the picture ID and start showing it UARTState=GET_PIC_ID; break; case CHANGE_MODE://switch to the mode corrasponding to the next received byte UARTState=GET_MODE; break; case SET_TIME:// sets the current time for clock displays must receive byte for each time UARTState=GET_MONTH; break; case SET_TEXT://get the size of message being sent then switch to displaying received message of under 50 chars UARTState=GET_TEXT_SIZE; break; } break; case GET_TEXT_SIZE://get size of text messageSize=dataIn; UARTState=GET_TEXT_DATA; bytesGot=0; break; case GET_TEXT_DATA://get the text one char at a time message2[bytesGot++]=dataIn; if(messageSize==bytesGot){ message2[bytesGot]=0; UARTState=START; chgMode(TEXT); } break; //get time information one byte after another case GET_MONTH: month=dataIn; UARTState=GET_DAY; break; case GET_DAY: day=dataIn; UARTState=GET_DATE; break; case GET_DATE: date=dataIn; UARTState=GET_AMPM; break; case GET_AMPM: ampm=dataIn; UARTState=GET_HOUR; break; case GET_HOUR: hour=dataIn; UARTState=GET_MIN; break; case GET_MIN: min=dataIn; chgMode(CLOCK); UARTState=START; break; case GET_PIC_ID://if image is in range show it if(dataIn>9 is the number of frames that have been completed if(curImage.startAddr+(bytesGot>>9)==curImage.endAddr){ //end receive UARTState=GET_REP; bytesGot=0; sendMsg("Got data send Repetitions\n",26); break; } //else start next write out to the EEPROMs startWrite(currentRom,curImage.startAddr+bytesGot/512,READ(bytesGot,8)); } break; case GET_REP://get number of repetitions for each frame eeprom_write_byte(&repeatPtr[curImage.startAddr+bytesGot++],dataIn);//for each frame, write how many repetitions you will do //When all the repetitions are filled in, everything is reset once more. Next we go to see what kind of dimension this picture is. if(bytesGot==curImage.endAddr-curImage.startAddr){ bytesGot=0; UARTState=GET_DIM; sendMsg("1",1); } break; case GET_DIM://get the dimension of the image 3D vs 2D bits3D=eeprom_read_byte(&isbits3DPtr[imageNum/8]); if(dataIn&1){ bits3D|=1<<(imageNum%8); //moves it so that the byte gets updated in the right place } else{ bits3D&=~(1<<(imageNum%8)); //moves it so that the byte gets updated in the right place } sendMsg("2",1); eeprom_write_byte(&isbits3DPtr[imageNum/8],bits3D); //modified byte that includes dimension information on current frame is updated UARTState=GET_NAME; break; case GET_NAME://get 5 byte name of image eeprom_write_byte(&namePtr[imageNum*5+bytesGot++],dataIn); //write byte of name one letter at a time if(bytesGot==5){ sendMsg("3",1); UARTState=END_TRANS; //go to end transmission } break; case END_TRANS://do handshake before updating number of pictures if fail not updating image num will ignore whole change if(dataIn==END_TRANS){ sendMsg("Pic loaded",10); displayImage(&curImage,imageNum); eeprom_write_byte(&imageNumPtr,imageNum+1); imageNum++; eeprom_busy_wait(); chgMode(ROM_ANIMATE); listPics(); } else{ sendMsg("Bad HandShake",1); chgMode(START); } UARTState=START; break; } } } //TURN ON LEDS GIVEN THE BITS FOR PORTC //--------------------------------------- void slowDirSet(uint8_t* bits){ //set all 16 LED driver bits for(int i=0;i<16;i++){ PORTB&=~_BV(PB7); //Serial Clock...so simulating the clock edges PORTC=bits[i]; //each bit of portc acts as the input to one driver PORTB|=_BV(PB7); //This is the other edge of the clock. When this is given, the portC bits will be accepted } LATCH_LEDS(); //Officially accept the changes in the LEDS UNLATCH_LEDS(); //Makes it so that changes to the LEDS will not do anything until the LEDS are latched again } //DECIDES WHAT TO PRINT //---------------------------------------- //start is the position of the lower left hand corner's height. line is when it should start printing the upper right hand corner. Numbers are 3W*5H. Letters are 4W*5H with a few that's 5W*5H void printSymbol(uint8_t* buff, uint8_t symbol, uint8_t height, uint8_t line,uint8_t color){ switch(symbol){ case '0': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '1': if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '2': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } break; case '3': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '4': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } else if(lineNum==line+1){ setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '5': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '6': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '7': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+1, color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } break; case '8': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case '9': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'A': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'B': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+3, color); setRGB(buff, height+1, color); } break; case 'C': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height , color); } break; case 'D': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); } break; case 'E': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } break; case 'F': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } break; case 'G': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'H': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'I': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height , color); } break; case 'J': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); } break; case 'K': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+3, color); setRGB(buff, height+1, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height , color); } break; case 'L': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height , color); } break; case 'M': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+3, color); } else if(lineNum==line+2){ setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+3, color); } else if (lineNum==line+4){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'N': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+3, color); } else if(lineNum==line+2){ setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'O': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'P': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } break; case 'Q': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height , color); } break; case 'R': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+3, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'S': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'T': if(lineNum==line){ setRGB(buff, height+4, color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); } break; case 'U': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'V': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } else if(lineNum==line+1){ setRGB(buff, height+1, color); } else if(lineNum==line+2){ setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+1, color); } else if(lineNum==line+4){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } break; case 'W': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+1, color); } else if(lineNum==line+2){ setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+1, color); } else if(lineNum==line+4){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'X': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+2, color); } else if(lineNum==line+2){ setRGB(buff, height+2, color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } break; case 'Y': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } else if(lineNum==line+1){ setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+2, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height+2, color); } break; case 'Z': if(lineNum==line){ setRGB(buff, height+4, color); setRGB(buff, height , color); } else if(lineNum==line+1){ setRGB(buff, height+4, color); setRGB(buff, height+1, color); setRGB(buff, height , color); } else if(lineNum==line+2){ setRGB(buff, height+4, color); setRGB(buff, height+2, color); setRGB(buff, height , color); } else if (lineNum==line+3){ setRGB(buff, height+4, color); setRGB(buff, height+3, color); setRGB(buff, height , color); } break; } } //prints all the symbols so they face outwards. You mark the lower left hand corner void printSymbolU(uint8_t* buff, uint8_t symbol, uint8_t height, uint8_t line,uint8_t color){ switch(symbol){ case '0': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '1': if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '2': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } break; case '3': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '4': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } else if(lineNum==line-1){ setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '5': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '6': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '7': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-1, color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } break; case '8': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case '9': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'A': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'B': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-3, color); setRGB(buff, height-1, color); } break; case 'C': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height , color); } break; case 'D': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); } break; case 'E': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } break; case 'F': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } break; case 'G': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'H': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'I': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height , color); } break; case 'J': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); } break; case 'K': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-3, color); setRGB(buff, height-1, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height , color); } break; case 'L': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height , color); } break; case 'M': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-3, color); } else if(lineNum==line-2){ setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-3, color); } else if (lineNum==line-4){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'N': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-3, color); } else if(lineNum==line-2){ setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'O': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'P': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } break; case 'Q': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height , color); } break; case 'R': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-3, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'S': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'T': if(lineNum==line){ setRGB(buff, height-4, color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); } break; case 'U': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'V': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } else if(lineNum==line-1){ setRGB(buff, height-1, color); } else if(lineNum==line-2){ setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-1, color); } else if(lineNum==line-4){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } break; case 'W': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-1, color); } else if(lineNum==line-2){ setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-1, color); } else if(lineNum==line-4){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'X': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-2, color); } else if(lineNum==line-2){ setRGB(buff, height-2, color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } break; case 'Y': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } else if(lineNum==line-1){ setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-2, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height-2, color); } break; case 'Z': if(lineNum==line){ setRGB(buff, height-4, color); setRGB(buff, height , color); } else if(lineNum==line-1){ setRGB(buff, height-4, color); setRGB(buff, height-1, color); setRGB(buff, height , color); } else if(lineNum==line-2){ setRGB(buff, height-4, color); setRGB(buff, height-2, color); setRGB(buff, height , color); } else if (lineNum==line-3){ setRGB(buff, height-4, color); setRGB(buff, height-3, color); setRGB(buff, height , color); } break; } } void printMessage(uint8_t* message, uint8_t* buff, uint8_t height, uint8_t line, uint8_t color, uint8_t type){ uint8_t modifier = 0; for(int i = 0;message[i];i++){ if (type == 0){ //face inwards if (line+modifier+5>angle) printSymbol(buff, message[i], height, 256-(angle-(line+modifier)), color); else printSymbol(buff, message[i], height, line+modifier, color); //takes care of int overflow...since angles < 255 and we can go up to 255 } else{ //takes care of int overflow...since angles < 255 and we can go up to 255 if (modifier+5>line) printSymbolU(buff, message[i], height, line+(angle-modifier)-1, color); else printSymbolU(buff, message[i], height, line-modifier, color); } if (message[i]=='M' || message[i]=='V' || message[i]=='W') modifier+=6; else modifier+=5; } } uint16_t getStrLen(uint8_t* str){ uint16_t i; for(i=0;str[i];i++); return i; } //length is in terms of pixel. time is in terms of rotation. void scrollMessage(uint8_t* message, uint8_t* buff, uint8_t height, uint8_t line, uint8_t color, uint8_t type, uint8_t length, uint8_t time){ if (lineNum == 1) counter++; if (counter == time){ counter1++; counter =0; } if (counter1 == getStrLen(message)*5+length) counter1 =0; if (type == 0) //low number...counterclockwise printMessage(message, buff, height, line+length-counter1, color, 0); else //high number...clockwise printMessage(message, buff, height, line-length+counter1, color, 1); if (type ==0 && (lineNum (line+length)%angle))){ for(int i=0;i<16;i++){ buff[i]=0; } } else if (type ==1 && (lineNum>line || (lineNum < (line-length)%angle))){ for(int i=0;i<16;i++){ buff[i]=0; } } } //SET LED COLOR //---------------------------------------- //buff: buffer where each bit corresponds with the LED to turn on. LED: Which LED to turn on. For 2D goes from 0-31. Color: Choose the color that the LED should be...can be 0:red, 1:green, 2:blue , 3:all void setRGB(uint8_t* buff,uint8_t LED,uint8_t color){ if (color != 3){ uint8_t bit=DIR_LUT[LED*3+color]; //picks the bit to enable SET(buff[bit/8],bit%8); //puts it in the right place...first determines which buff index to go. Second decides which bit. } else{ //turns all the LEDS for a single LED package uint8_t bit0=DIR_LUT[LED*3]; uint8_t bit1=DIR_LUT[LED*3+1]; uint8_t bit2=DIR_LUT[LED*3+2]; SET(buff[bit0/8],bit0%8); SET(buff[bit1/8],bit1%8); SET(buff[bit2/8],bit2%8); } } //copy data one byte at a time from a null terminated string void StrCpy(char* to,char* from){ uint8_t i=0; while((to[i]=from[i++])){} } //SIMPLE LED TEST //--------------------------------------- //This toggles the LED next to the microcontroller void simpleTest(uint8_t line){ if (lineNum==0) PORTB=0; else PORTB^=1; nextTime+=increment; } //RADIAL LED TEST //--------------------------------------- //This makes it so that device makes alternating red, green, blue lines void updateTestRGB(uint8_t line){ uint8_t dirBuff[16]; //buffer that holds bits of which LED to turn on uint8_t col = line%3; //Determines the color of the LED to turn on //This resets the dirBuff so that no LEDS will be initialized for(int i=0;i<16;i++){ dirBuff[i]=0; } //This sets it up so that all the LEDS of a certain color is lit up for (int i=0; i<32;i++) setRGB(dirBuff, i, col); //This is fed into the function that will actually display the LEDS slowDirSet(dirBuff); } void updateText(uint8_t* message, uint8_t height, uint8_t line, uint8_t type, uint8_t color, uint8_t length, uint8_t time){ uint8_t dirBuff[16]; for(int i=0;i<16;i++){ dirBuff[i]=0; } scrollMessage(message, dirBuff, height, line, color, type, length, time); slowDirSet(dirBuff); } void updateClock(uint8_t hours, uint8_t minutes, uint8_t seconds){ uint8_t dirBuff[16]; uint8_t index = 0; for(int i=0;i<16;i++){ dirBuff[i]=0; } switch(day){ case 1: StrCpy(message1, "SUN "); index+=4; break; case 2: StrCpy(message1, "MON "); index+=4; break; case 3: StrCpy(message1, "TUES "); index+=5; break; case 4: StrCpy(message1, "WED "); index+=4; break; case 5: StrCpy(message1, "THUR "); index+=5; break; case 6: StrCpy(message1, "FRI "); index+=4; break; case 7: StrCpy(message1, "SAT "); index+=4; break; } switch(month){ case 0: StrCpy(message1+index, "JANUARY "); index+=8; break; case 1: StrCpy(message1+index, "FEBRUARY "); index+=9; break; case 2: StrCpy(message1+index, "MARCH "); index+=6; break; case 3: StrCpy(message1+index, "APRIL "); index+=6; break; case 4: StrCpy(message1+index, "MAY "); index+=4; break; case 5: StrCpy(message1+index, "JUNE "); index+=5; break; case 6: StrCpy(message1+index, "JULY "); index+=5; break; case 7: StrCpy(message1+index, "AUGUST "); index+=7; break; case 8: StrCpy(message1+index, "SEPTEMBER "); index+=10; break; case 9: StrCpy(message1+index, "OCTOBER "); index+=8; break; case 10: StrCpy(message1+index, "NOVEMBER "); index+=9; break; case 11: StrCpy(message1+index, "DECEMBER "); index+=9; break; } itoa(date,message1+index,10); if (masterState == CLOCK2){ uint8_t pos =15; //printMessage(message1, dirBuff, pos, 150, 3, 0); scrollMessage(message1, dirBuff, pos, 120, 3, 1, 60, 1); } if ((hours*15+minutes/4)==lineNum) { for (int i=0; i<20;i++) setRGB(dirBuff, i, 0); } if (minutes==lineNum/3) { for (int i=0; i<24;i++) setRGB(dirBuff, i, 1); } if (seconds==lineNum/3) { for (int i=0; i<24;i++) setRGB(dirBuff, i, 2); } uint8_t type = 0; if (type == 0){ //for numbers facing outwards uint8_t pos = 30; printSymbolU(dirBuff, '1', pos, 3*5-1,3); printSymbolU(dirBuff, '2', pos, 3*10-1,3); printSymbolU(dirBuff, '3', pos, 3*15-1,3); printSymbolU(dirBuff, '4', pos, 3*20-1,3); printSymbolU(dirBuff, '5', pos, 3*25-1,3); printSymbolU(dirBuff, '6', pos, 3*30-1,3); printSymbolU(dirBuff, '7', pos, 3*35-1,3); printSymbolU(dirBuff, '8', pos, 3*40-1,3); printSymbolU(dirBuff, '9', pos, 3*45-1,3); printSymbolU(dirBuff, '0', pos, 3*50-3,3); printSymbolU(dirBuff, '1', pos, 3*50, 3); printSymbolU(dirBuff, '1', pos, 3*55-3,3); printSymbolU(dirBuff, '1', pos, 3*55,3); printSymbolU(dirBuff, '2', pos, 180-3,3); printSymbolU(dirBuff, '1', pos, 0, 3); printSymbolU(dirBuff, '1', pos, 180, 3); } else if(type == 1){ //for numbers facing inwards uint8_t pos = 25; printSymbol(dirBuff, '1', pos, 3*5-1,3); printSymbol(dirBuff, '2', pos, 3*10-1,3); printSymbol(dirBuff, '3', pos, 3*15-1,3); printSymbol(dirBuff, '4', pos, 3*20-1,3); printSymbol(dirBuff, '5', pos, 3*25-1,3); printSymbol(dirBuff, '6', pos, 3*30-1,3); printSymbol(dirBuff, '7', pos, 3*35-1,3); printSymbol(dirBuff, '8', pos, 3*40-1,3); printSymbol(dirBuff, '9', pos, 3*45-1,3); printSymbol(dirBuff, '1', pos, 3*50-3,3); printSymbol(dirBuff, '0', pos, 3*50, 3); printSymbol(dirBuff, '1', pos, 3*55-3,3); printSymbol(dirBuff, '1', pos, 3*55,3); printSymbol(dirBuff, '1', pos, 180-3,3); printSymbol(dirBuff, '2', pos, 0, 3); printSymbol(dirBuff, '2', pos, 180, 3); } else if (type == 3){ //Letters face inwards uint8_t pos = 25; printSymbol(dirBuff, 'A', pos, 0, 3); printSymbol(dirBuff, 'A', pos, 180, 3); printSymbol(dirBuff, 'B', pos, 5,3); printSymbol(dirBuff, 'C', pos, 10,3); printSymbol(dirBuff, 'D', pos, 15,3); printSymbol(dirBuff, 'E', pos, 20,3); printSymbol(dirBuff, 'F', pos, 25,3); printSymbol(dirBuff, 'G', pos, 30,3); printSymbol(dirBuff, 'H', pos, 35,3); printSymbol(dirBuff, 'I', pos, 40,3); printSymbol(dirBuff, 'J', pos, 45,3); printSymbol(dirBuff, 'K', pos, 50,3); printSymbol(dirBuff, 'L', pos, 55,3); printSymbol(dirBuff, 'M', pos, 60,3); printSymbol(dirBuff, 'N', pos, 65,3); printSymbol(dirBuff, 'O', pos, 70,3); printSymbol(dirBuff, 'P', pos, 75,3); printSymbol(dirBuff, 'Q', pos, 80,3); printSymbol(dirBuff, 'R', pos, 85,3); printSymbol(dirBuff, 'S', pos, 90,3); printSymbol(dirBuff, 'T', pos, 95,3); printSymbol(dirBuff, 'U', pos, 100,3); printSymbol(dirBuff, 'V', pos, 105,3); printSymbol(dirBuff, 'W', pos, 110,3); printSymbol(dirBuff, 'X', pos, 115,3); printSymbol(dirBuff, 'Y', pos, 120,3); printSymbol(dirBuff, 'Z', pos, 125,3); } else if (type == 4){ //Letters face inwards uint8_t pos = 30; printSymbolU(dirBuff, 'A', pos, 0, 3); printSymbolU(dirBuff, 'A', pos, 180, 3); printSymbolU(dirBuff, 'B', pos, 5,3); printSymbolU(dirBuff, 'C', pos, 10,3); printSymbolU(dirBuff, 'D', pos, 15,3); printSymbolU(dirBuff, 'E', pos, 20,3); printSymbolU(dirBuff, 'F', pos, 25,3); printSymbolU(dirBuff, 'G', pos, 30,3); printSymbolU(dirBuff, 'H', pos, 35,3); printSymbolU(dirBuff, 'I', pos, 40,3); printSymbolU(dirBuff, 'J', pos, 45,3); printSymbolU(dirBuff, 'K', pos, 50,3); printSymbolU(dirBuff, 'L', pos, 55,3); printSymbolU(dirBuff, 'M', pos, 60,3); printSymbolU(dirBuff, 'N', pos, 65,3); printSymbolU(dirBuff, 'O', pos, 70,3); printSymbolU(dirBuff, 'P', pos, 75,3); printSymbolU(dirBuff, 'Q', pos, 80,3); printSymbolU(dirBuff, 'R', pos, 85,3); printSymbolU(dirBuff, 'S', pos, 90,3); printSymbolU(dirBuff, 'T', pos, 95,3); printSymbolU(dirBuff, 'U', pos, 100,3); printSymbolU(dirBuff, 'V', pos, 105,3); printSymbolU(dirBuff, 'W', pos, 110,3); printSymbolU(dirBuff, 'X', pos, 115,3); printSymbolU(dirBuff, 'Y', pos, 120,3); printSymbolU(dirBuff, 'Z', pos, 125,3); } slowDirSet(dirBuff); } //set up current image to display selected image correctly void displayImage(Image* image,uint8_t ID){ image->ID=ID; image->startAddr=eeprom_read_byte(&startPtr[ID]); if(ID!=255){ image->endAddr=eeprom_read_byte(&startPtr[ID+1]); } else{ image->endAddr=0; } curImage.index=-2; curImage.repetitions=0; curImage.curRepetitions=0; } //prepare next line by loading off of EEPROM void updateFromROM(Image * image,uint8_t line){ //if new frame started if (line==1){ //if max repetitions is reached then load next frame if(image->curRepetitions++>=image->repetitions){ image->curRepetitions=0; image->index++; //if end of animation is reached restart if(image->endAddr<=image->index){ image->index=image->startAddr; } //get repetitions for current frame image->repetitions=eeprom_read_byte(&repeatPtr[image->index]); } //start reading at index address startRead(image->index); } if(line<128){ //read four bytes to update the 16 bits of the two daisy chained EEPROMS SPI_SEND(0xFF); SPI_SEND(0xFF); SPI_SEND(0xFF); SPI_SEND(0xFF); LATCH_LEDS(); UNLATCH_LEDS(); } } //initialize read starting at addr void startRead(uint8_t addr){ //reset ROM DESELECT_ALL(); SELECT_ALL(); //send read command SPI_SEND(SPI_READ); //send address: address space is 17 bits and all frames are 512 aligned that means we don't care about bits 0-8 or 17-23 SPI_SEND(addr>>7); SPI_SEND((addr<<1)&0xFF); SPI_SEND(0); //don't disable until read is finished } //initialize write starting at addr void startWrite(uint8_t currentRom,uint8_t addr,uint8_t isSecondHalf ){ //Write enable SELECT_ROM(currentRom); SPI_SEND(SPI_WREN); DESELECT_ALL(); //send read command SELECT_ROM(currentRom); SPI_SEND(SPI_WRITE); /* uartSendByte(currentRom); uartSendByte(addr); uartSendByte(isSecondHalf);*/ //send address: since writes must be <=256 bytes we must break each frame into two writes and use an extra bit to specify which half we're on SPI_SEND(addr>>7); SPI_SEND(((addr<<1)&0xFF)|isSecondHalf); SPI_SEND(0); //don't disable till all 256 data bytes are sent } //enable SPI and reset EEPROMs void spiInit(void){ //Enable SPI, Master, set clock rate fck/4 SPCR = (1<((uint8_t*)&nextTime)[2])||((overflows1==((uint8_t*)&nextTime)[2])&&TCNT1>(uint16_t)nextTime)){ update=1; nextTime+=increment; lineNum++; } sei(); //if its time to update go through proper update methods if(update){ update=0; switch(masterState){ case TEST_RGB: updateTestRGB(lineNum); //simpleTest(lineNum); break; case ROM_ANIMATE: updateFromROM(&curImage,lineNum); break; case RECEIVING: break; //for the clocks the specific type is handled in the method case CLOCK: case CLOCK2: updateClock(hour, min, sec); break; case TEXT: updateText(message2, 25, 1, 0, 3, 170, 1); break; } } //check if there is a byte in the serial buffer and handle it if there is if(!uartReceiveBufferIsEmpty()){ // PORTB=0; handleSerial(rxBuff); } //update time values if(milli >= 1000){ milli = 0; if((sec%15)==0&&toggleMode){ masterState=(masterState==5)?2:masterState+1; chgMode(masterState); } sec++; } if(sec >=60){ sec = 0; min++; } if (min >= 60){ min = 0; hour++; } if (hour >= 12){ hour = 0; ampm^=1; if (ampm == 0 && hour == 0){ date++; day++; day%= 7; } } switch (month){ case 0: if (date > 31) date =0; break; case 1: if (date > 28) date =0; break; case 2: if (date > 31) date =0; break; case 3: if (date > 30) date =0; break; case 4: if (date > 31) date =0; break; case 5: if (date > 30) date =0; break; case 6: if (date > 31) date =0; break; case 7: if (date > 31) date =0; break; case 8: if (date > 30) date =0; break; case 9: if (date > 31) date =0; break; case 10: if (date > 30) date =0; break; case 11: if (date > 31) date =0; break; } } } //INTERRUPTS //********************************************************** //use to keep track of milli seconds for clocks ISR (TIMER0_COMPA_vect) { milli++; } //---------------------------------------------------------------------------------------- //Input Capture when hall sensor detects magnet (PD6 goes low) ISR(SIG_INPUT_CAPTURE1) { //reset cycle counter to get accurate timing of period TCNT1=ICP_DELAY; //get cycles that rotation took spinPeriod=((uint32_t)overflows1<<16)|ICR1; //reset spin tracking vars overflows1=0; nextTime=0; //the shift amount determines the angular resolution //this sets how many lines to update during next rotation increment=(spinPeriod/angle); lineNum=0; } //keep track of time over long period by counting overflows ISR (SIG_OVERFLOW1) { overflows1++; // PORTB^=1; }