/* 2/25 1:40AM - Currently Blinks LED 4 and 6, should only blink LED 8. 2/25 2:30AM - No longer blinks, tried to add debug, serial is garbage output now 2/26 3:00AM - Messing with serial debug messages...added some comments...added Parenthesis in logic for GenerateCMDs 3/2 12:05AM - Can't have print statements inbetween wire statements... Runs but Some thing with 2 dem arrays screws up generate functions 3/3 5:00PM - Tried to integrate PROGMEM 3/5 2:00AM - Tried one dimensional array like adddressing but with two-dimensional data structures still - in new folder. 3/6 2:00AM - Trying with all one dimensional arrays, and also trying with ie. GPSdata + i, ie. pointer plus increment of size = datatype 3/10-3/12 - Trying new logic inside IF inside the 2nd For Loop... Works now! Blink0 lights LED3 3/12 - Initially all LEDs are ON solid, on Driver 1, THEN lights LED 1,3,5,7 on Driver 0. 3/24 2AM - Changed Variable names, Added tons of comments, Added Daniels testI2C function. 4/7/09 - Added setInternet() and setBlinkRate() functions, setInternet still needs stuff added from other file. - FindLatLonRed() FindLatLonGreen() and FindLatLonBlue() need to be created from the LatLonReader code. 4/8/09 - added everything above, but just made one FindLatLon(route), that takes in a route number form 0-3. Copied LatLonReader code from 4/9/09 -added ResetCurrentArrays() so that it does not use old data next time it refills the arrays. -added setInternet() commands, and some logic to check if online. 4/9/09 - Added ASCIIsubtract function, to correct the wrong GPS coordinates it was reporting when trying to type cast the numbers to integers. 4/9/09 - Changed the ascIIsubtract function again. Added Serial.Prints everywhere, determined the buffer is maybe overflowing because it never recieves tags. 4/11/09 - Succesfully parses a fake array of XML data. 4/14/09 - Succesfully able to parse a copy of XML code sent from serial monitoring device. 4/14/09 - CURRENTLY, receives data from Wi-Fi module on Matt's router, and parses 1 bus route and finds a matched location. 4/18/09 - TRACKS BUSES! for short period of time then freezes. 4/19/09 - Removed Debug code. Changed the way ICDrvNum and ICBankNum are initialized in the generateCMD functions. 4/20/09 - Code works, but need to add error condition checking */ #include "WaitLess.h" #include //#include #include //#include //HIGH, for type of LED illumination desired #define ON 0 #define BLINK0 1 #define BLINK1 0 //DEBUG values #define DEBUG 1 #define DEBUG2 0 //Values that are used to OR into arrays of LED Locations which //were cleared to be 00 after bitMask is subtracted. #define ONcmd B00 #define BLINK0cmd B10 //Addresses of each LED Controller #define DRV0_ADDR B1100000 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] // Address with three address pins grounded. = 0111000 // Note that the R/W' bit is not part of this address, // The wire library takes care of the LSB #define DRV1_ADDR B1100001 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] #define DRV2_ADDR B1100010 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] #define DRV3_ADDR B1100011 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] #define DRV4_ADDR B1100100 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] #define DRV5_ADDR B1100101 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] #define DRV6_ADDR B1100110 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] #define DRV7_ADDR B1100111 // CAT9552 chips are of address format 1100 [a2] [a1] [a0] //4th bit position is high to say sequentially do these commands, once one is given, for setup purposes. #define SETUP_REG0 B00010000 //INPUT0 / READ / Input Register 0 #define SETUP_REG1 B00010001 //INPUT1 / READ / Input Register 1 #define SETUP_REG2 B00010010 //PSC0 / READ/WRITE / Frequency Prescaler 0 #define SETUP_REG3 B00010011 //PWM0 / READ/WRITE / PWM Register 0 #define SETUP_REG4 B00010100 //PSC1 / READ/WRITE / Frequency Prescaler 1 #define SETUP_REG5 B00010101 //PWM1 / READ/WRITE / PWM Register 1 #define SETUP_BANK0 B00010110 //LS0 / READ/WRITE / LED 0-3 Selector #define SETUP_BANK1 B00010111 //LS1 / READ/WRITE / LED 4-7 Selector #define SETUP_BANK2 B00011000 //LS2 / READ/WRITE / LED 8-11 Selector #define SETUP_BANK3 B00011001 //LS3 / READ/WRITE / LED 12-15 Selector ///USED in FindLatLon()//////// #define LAT 0 #define LON 1 /*********Global Variables***********/ unsigned char i, j; //General indices unsigned char BUSi; //Index for traversing the array containing the current GPS locations unsigned char found; //1 if a GPS match is found unsigned char bitMask; //Used to subtract from exsisting LEDcmds location in array to clear previous OFF command that ResetLEDcmds inserted, and fill with 00 unsigned char CMD; //ORed with newly cleared LEDcmds location, to move in new value such as 10 for BLINK0 unsigned char ICDrvNum, ICBankNum; //For use in sending new commands in the SendNewCommands Function unsigned char OFF = 0x55; //Used ONLY in testI2C function #define MAXCHARS 12 //Size of array to hold incoming messages from the Wi-Fi module during setInternet function #define MAXCHARSRed 200 #define MACREGISTERALLOWANCE 30000 //This is how many milliseconds you will allow yourself to register the MAC address on GTwireless unsigned int currentRED[16]; unsigned int currentGREEN[16]; unsigned int currentBLUE[16]; unsigned int currentYELLOW[16]; /*********LEDcmds Data Array********* * Each row is an IC starting with IC #0 * Each column is an LED bank starting with LS0 * 0101 for each bank default at start, off ************************************/ unsigned char LEDcmds[7][4] = {{0x55, 0x55, 0x55, 0x55}, {0x55, 0x55, 0x55, 0x55}, {0x55, 0x55, 0x55, 0x55}, {0x55, 0x55, 0x55, 0x55}, {0x55, 0x55, 0x55, 0x55}, {0x55, 0x55, 0x55, 0x55}, {0x55, 0x55, 0x55, 0x55}}; /*********END OF Global Variables*****/ /* NOT REQUIRED *********Function Prototypes******** void ResetLEDcmds(void); void setInternet(void); void setBlinkRate(void); void ResetCurrentArrays(void); void SendNewCommands(void); int ASCIIsubtract(char *, char *); void FindLatLon(unsigned char); void GenerateRedCMDs(void); void GenerateGreenCMDs(void); void GenerateBlueCMDs(void); //void GenerateYellowCMDs(void); void setup(void); void loop(void); int availableMemory(void); int get_free_memory(void); /************************************ */ /************************** * ResetLEDcmds * Sets LEDcmds to all off (0x55) **************************/ void ResetLEDcmds(){ for(ICDrvNum = 0; ICDrvNum < 7; ICDrvNum++){ for(ICBankNum = 0; ICBankNum < 4; ICBankNum++){ LEDcmds[ICDrvNum][ICBankNum] = 0x55; } } }//End ResetLEDcmds /************************** * ResetCurrentArrays * Sets currentRED,currentGREEN,currentBLUE,currentYELLOW back to all FFFF's in the [0-8][0] <- which is the escape character * to let the generate[color]CMDs function know that data is empty for that possible bus. * Retrying with 0x0000 not 0xFFFF **************************/ void ResetCurrentArrays(){ //Reset CurrentArrays, so next time old data is not left behind unsigned char LatIndex; for(LatIndex = 0; LatIndex < 8; LatIndex++){ currentRED[LatIndex*2] = 0xFFFF; currentGREEN[LatIndex*2] = 0xFFFF; currentBLUE[LatIndex*2] = 0xFFFF; currentYELLOW[LatIndex*2] = 0xFFFF; } }// End ResetCurrentArrays /************************** * SendNewCommands * By increasing Driver Number and IC Bank Number * Sends out each of 28 bytes representing 28*4 possible LEDs settings. * Should run every 10 seconds, ie. LEDs blink for 10 seconds then change to new locations. **************************/ void SendNewCommands(){ for(ICDrvNum = 0; ICDrvNum < 7; ICDrvNum++){ for(ICBankNum = 0; ICBankNum < 4; ICBankNum++){ Wire.beginTransmission((0x60 | ICDrvNum)); //Send IC address, all drivers start with 0x60 = 1100000 Wire.send((0x06 + ICBankNum)); //Send LS bank number, all registers can be achieved with 6 + (0 thru 4) Wire.send(LEDcmds[ICDrvNum][ICBankNum]); //Send New entry in the LEDcmds Array Wire.endTransmission(); //Send Stop Condition } } }//End SendNewCommands Function /************************** * setInternet * Sets up all get on internet stuff, check for connection status, parse returned error or confirmation code, * when it is actually online, ie. says I/ONLINE wait few seconds, then exit setup loop * Then we can call this whenever trouble arises, any internet error conditions... MAC = 001988053CA4 **************************/ void setInternet(){ char incoming[MAXCHARS]; char eotCounter = 0; // increments and counts up to 4, to represent the indexes of the eotChars[] everytime it matches, if it doesn't, it will become zero. char eotChars[] = "I/ON"; // need \ before / ? we will see when we test it out char eotFlag = 0; // End of Transmission Flag, received what we were looking for, should drop from all while loops char next, i; // to increment the incoming array and save data to it from Serial.read() char iteration = 0; // When is zero starts overall while loop to get on internet, normally starts at 11 and decrements everytime a character is tried to match, // when it reaches zero without a eotFlag ever being set, then we know it never got the I/ON command returned to it, so it will go to // main while loop and try to get online again. Of course will reset iteration to 11 again to try again to recieve the I/ON message. // I expect I/OK I/ONLINE , 10 chars should be enough to cover to I/ON, but will include 1 more iteration to try anyway. // and the if(Serial.available() =0) will always get to that point because it should return at least 12 characters I/OK I/DONE // POSSIBLE ERROR TO CORRECT, if it doesn't count as a character, should reduce iteration to 10! while(!iteration && !eotFlag){ iteration = 11; //will count down to zero after reading 11 characters that don't match I/ON and then will try again Serial.print("AT+iUP:1\r"); // 1 go online and register IP, 0 just go online. delay(5000); // time for it to get IP registered if(DEBUG) Serial.println("Waiting MACREGISTERALLOWANCE MAC IS 001988053CA4");//0019881FF1F7"); delay(MACREGISTERALLOWANCE); //Wait how many seconds you set in MACREGISTERALLOWANCE to register MAC address online, MAC IS 001988053CA4 if(DEBUG) Serial.println("Chip should UP again"); Serial.flush(); Serial.print("AT+iUP:1\r"); delay(3000); //Wait for chip to respond //TRYING to look for I/ON meaning ONLINE now so move on, or else try to get online again. while(!eotFlag && (iteration > 0)){ //while I/ON has not been found, and while iteration is > 0. iteration--; //increment iteration so when has tried 11 times, just retries to get on internet.. when fails previous while loop condition for (i=0;i 0) { incoming[next] = Serial.read(); if(incoming[next] == eotChars[eotCounter]){ eotCounter++; } else{ eotCounter = 0; iteration--; } if(eotCounter == 4) eotFlag = 1; //2 for I/ 4 for I/ON next++; }//END if loop that reads in characters if it is available }//END FOR loop that captures incoming data from module }//END NESTED WHILE THAT RECEIVES and CHECKS incoming codes. }//END OVERALL WHILE }//END setInternet() /************************** * setBlinkRate * This For loop sets all Drivers' BLINK0 & BLINK1 rates to faster blink rate, to save power. **************************/ void setBlinkRate(){ for(unsigned char ICDrvNum = 0; ICDrvNum < 7; ICDrvNum++){ Wire.beginTransmission((0x60 | ICDrvNum)); //Send IC address, all drivers start with 0x60 = 110 0000 = adds MSB zero automatically Wire.send(SETUP_REG2); //Send LS bank number, all registers addresses can be achieved with 6 + (0 thru 4) Wire.send(B00000000); //PSC0 Frequency Prescaler 0 = 0 ->lower is faster blink ->default was 256 = 44hz Wire.send(B10000000); //PWM0 PWM Register 0 = 128 //default - 50% duty cycle Wire.send(B00000000); //PSC1 Frequency Prescaler 1 = 0 ->lower is faster blink ->default was 256 = 44hz Wire.send(B10000000); //PWM1 PWM Register 0 = 128 //default - 50% duty cycle Wire.endTransmission(); //Send Stop Condition } } /************************** * ASCIIsubtract * Returns A-B which it takes as inputs, as an integer output. This allows us to read Long numbers and convert to integers **************************/ unsigned int ASCIIsubtract(unsigned char *A, unsigned char *B){ //returns A - B as an integer char ASi = 0; char carry = 0; unsigned char resultStr[8]; //changed to resultStr unsigned long result = 0; unsigned long multi = 1; unsigned int resultI = 0; for(ASi = 7; ASi >= 0; ASi--){ //ASi ascii subtract index if((A[ASi] - carry) < B[ASi]){ resultStr[ASi] = (A[ASi] - carry + 10) - B[ASi]; carry = 1; } else { resultStr[ASi] = (A[ASi] - carry) - B[ASi]; carry = 0; } if(DEBUG2){ Serial.print("Index is currently: "); Serial.println(ASi, DEC); Serial.print("A[i], DECIMAL VALUE is currently: "); Serial.println(A[ASi], DEC); Serial.print("B[i], DECIMAL VALUE is currently: "); Serial.println(B[ASi], DEC); Serial.print("resultStr[i], DECIMAL VALUE is currently: "); Serial.println(resultStr[ASi], DEC); delay(5000); } } for(ASi = 7; ASi >= 0; ASi--){ result += resultStr[ASi] * multi; multi *= 10; } resultI = (unsigned int)result; if(DEBUG2){ Serial.print("resultI currently is: "); Serial.println(resultI, DEC); delay(5000); } return resultI; }//END ASCIIsubtract /************************** * FindLatLon * Parses XML Data recieved from NextBus. Saves GPS Locations in correct Colored Array. * ARGUMENTS, unsigned Char to select correct URL * RED = 0 * GREEN = 1 * BLUE = 2 * YELLOW = 3 **************************/ void FindLatLon(unsigned char routecolor){ /**************Variables for LatLonReader Code*********************/ unsigned char latMinStr[] = {'3','3','7','6','7','9','4','8'}; //unsigned char lattestStr[] = {'3','3','7','6','8','9','4','8'}; unsigned char lonMinStr[] = {'8','4','3','8','4','9','2','9'}; //unsigned char lontestStr[] = {'8','4','3','8','5','9','2','9'}; unsigned char currentChar; unsigned char done = 0; //gets set when lat lon pair are found. allows algorithm to find next lat and lon unsigned char iRED = 0; unsigned char iBLUE = 0; unsigned char iGREEN = 0; unsigned char iYELLOW = 0; //indecies for loading color arrays with the found lat and lon unsigned int i = 0; //for test array #define routeTagStrLength 10 char routeTagStr[] = "routeTag=\""; char RTMatchCnt = 0; enum{ RED, GREEN, BLUE, YELLOW }; enum{ //for read_mode switch statement find_route, find_lat_tag, find_lat, find_lon_tag, find_lon, process_data, eot_mode }; char read_mode = find_route; char route; char routeTagFOUND = 0; #define latTagStrLength 5 char latTagStr[] = "lat=\""; char latMatchCNT = 0; char latTagFOUND = 0; char latDONE = 0; char latReadI = 0; unsigned char latStr[8]; unsigned int latI = 0; #define lonTagStrLength 5 char lonTagStr[] = "lon=\""; char lonMatchCNT = 0; char lonTagFOUND = 0; char lonDONE = 0; char lonReadI = 0; unsigned char lonStr[8]; unsigned int lonI = 0; char matchCNT = 0; char eotStr[] = "= '0' && currentChar <= '9' && latReadI < 8) latStr[latReadI++] = currentChar; else if(currentChar == '"'){ read_mode = find_lon_tag; latReadI = 0; } break; //find_lat case find_lon_tag: if(currentChar == lonTagStr[lonMatchCNT]) lonMatchCNT++; //matchCNT counts the number successive character matches else lonMatchCNT = 0; if(lonMatchCNT == lonTagStrLength){ read_mode = find_lon; lonMatchCNT = 0; } break; //find_lon_tag case find_lon: if(currentChar >= '0' && currentChar <= '9' && lonReadI < 8) lonStr[lonReadI++] = currentChar; else if(currentChar == '"'){ read_mode = process_data; lonReadI = 0; } break; //find_lon case process_data: latI = ASCIIsubtract(latStr, latMinStr); //change latStr to lattestStr, to see if it gets 1000 as it should with test number. lonI = ASCIIsubtract(lonStr, lonMinStr); if(latI >= 0 && lonI >=0){ switch(route){ // store the data in the correct color array case RED: currentRED[(iRED*2)] = latI; //iRED*2 means array index for what would be the first column, or LATS, if it was a 2D array, but is a 1D array. currentRED[((iRED*2)+1)] = lonI; //(iRED*2) +1 means array index for what would be the second column, or LONS, if it was a 2D array, but is a 1D array. iRED++; break; case BLUE: currentBLUE[iBLUE*2] = latI; currentBLUE[(iBLUE*2)+1] = lonI; iBLUE++; break; case GREEN: currentGREEN[iGREEN*2] = latI; currentGREEN[(iGREEN*2)+1] = lonI; iGREEN++; break; case YELLOW: currentYELLOW[iYELLOW*2] = latI; currentYELLOW[(iYELLOW*2)+1] = lonI; iYELLOW++; break; } } //clear previous bus GPS strings, because next bus location will reuse it, and might have less digits for(i=0;i<8;i++){ latStr[i]=0; lonStr[i]=0; } read_mode = find_route; break; //process_data case eot_mode: eot = 1; if(iRED < 8) currentRED[iRED*2] = 0xFFFF; //Set 1st element of this row to 0xFF so when reading these arrays to determine if(iBLUE < 8) currentBLUE[iBLUE*2] = 0xFFFF; //which LED to light, we know when to stop reading the arrays, generateCMDs looks for this number 0xFF to know it is invalid bus if(iGREEN < 8) currentGREEN[iGREEN*2] = 0xFFFF; if(iYELLOW < 8) currentYELLOW[iYELLOW*2] = 0xFFFF; read_mode = find_route; break; // eot_mode } //end switch (read_mode) } // end while(!eot) }// END FindLatLon() /************************** * GenerateRedCMDs * Uses the Red color location arrays * to find determine which LEDs need to * be lit and modifies LEDcmds accordingly **************************/ void GenerateRedCMDs(){ unsigned char ICDrvNum; unsigned char ICBankNum; for(BUSi = 0; ((BUSi < 8) && (currentRED[BUSi*2] != 0xFFFF)); BUSi++){ //Goes through the six possible red locations found = 0; for(i = 0; ((i < 42) && !found); i++){ if((currentRED[BUSi*2] >= (pgm_read_word_near(GPSdata+(i*4)))) && (currentRED[BUSi*2] <= (pgm_read_word_near(GPSdata+((i*4)+1)))) && (currentRED[(BUSi*2)+1] >= (pgm_read_word_near(GPSdata+(i*4)+2))) && (currentRED[(BUSi*2)+1] <= (pgm_read_word_near(GPSdata+(i*4)+3)))) { if(BLINK0) CMD = (BLINK0cmd<<(2*(pgm_read_byte_near(RedInfo+(i*3)+2)))); // so if BLINK0 = 10, an led location is #3 in bank, 00 10 00 00 if(ON) CMD = (ONcmd<<(2*(pgm_read_byte_near(RedInfo+(i*3)+2)))); // so if ON = 00, and led location is #3 in bank, 00 00 00 00 ICDrvNum = (pgm_read_byte_near(RedInfo+(i*3))); // Which Driver LED is connected to = (i*3) ICBankNum = (pgm_read_byte_near(RedInfo+(i*3)+1)); // Which Bank on LED Driver = ((i*3)+1) bitMask = (0x01<<(2*(pgm_read_byte_near(RedInfo+(i*3)+2)))); // (Location in Bank=((i*3)+2) so if i=5, 17th value in red info = 2, *2, says shift in a 11, 4 places, // to represent the value/LED to modify 01<<4 = 00010000 // This bitmask is used so previous changes to the particular bank are not modified (LEDcmds[ICDrvNum][ICBankNum]) -= bitMask; // So if LEDcmds started at 01010101 and bitMask is now 00010000 // then 01010101 - 00010000 = is 01000101 is new LEDcmds entry (LEDcmds[ICDrvNum][ICBankNum]) |= CMD; // 01 00 01 01 | 00 10 00 00 = 01 10 01 01 is the final LEDcmds entry found = 1; // Found Entry so don't keep searching for matching LED/GPS location } } } }//END GenerateRedCMDs Function /************************** * GenerateGreenCMDs * Uses the Green color location arrays * to find determine which LEDs need to * be lit and modifies LEDcmds accordingly **************************/ void GenerateGreenCMDs(){ unsigned char ICDrvNum; unsigned char ICBankNum; for(BUSi = 0; ((BUSi < 8) && (currentGREEN[BUSi*2] != 0xFFFF)); BUSi++){ //Goes through the six possible green locations found = 0; for(i = 0; ((i < 42) && !found); i++){ if((currentGREEN[BUSi*2] >= (pgm_read_word_near(GPSdata+(i*4)))) && (currentGREEN[BUSi*2] <= (pgm_read_word_near(GPSdata+((i*4)+1)))) && (currentGREEN[(BUSi*2)+1] >= (pgm_read_word_near(GPSdata+(i*4)+2))) && (currentGREEN[(BUSi*2)+1] <= (pgm_read_word_near(GPSdata+(i*4)+3)))) { if(BLINK0) CMD = (BLINK0cmd<<(2*(pgm_read_byte_near(GreenInfo+(i*3)+2)))); // so if BLINK0 = 10, an led location is #3 in bank, 10 00 00 00 if(ON) CMD = (ONcmd<<(2*(pgm_read_byte_near(GreenInfo+(i*3)+2)))); // so if ON = 00, and led location is #3 in bank, 00 00 00 00 ICDrvNum = (pgm_read_byte_near(GreenInfo+(i*3))); // Which Driver LED is connected to = (i*3) ICBankNum = (pgm_read_byte_near(GreenInfo+(i*3)+1)); // Which Bank on LED Driver = ((i*3)+1) bitMask = (0x01<<(2*(pgm_read_byte_near(GreenInfo+(i*3)+2)))); // (Location in Bank=((i*3)+2) so if i=5, 17th value in green info = 3, *2, says shift in a 1, 6 places, // to represent the value/LED to modify 01<<6 = 01000000 // This bitmask is used so previous changes to the particular bank are not modified (LEDcmds[ICDrvNum][ICBankNum]) -= bitMask; // So if LEDcmds started at 01010101 and bitMask is now 01000000 // then 01010101 - 01000000 = is 00010101 is new LEDcmds entry (LEDcmds[ICDrvNum][ICBankNum]) |= CMD; // 00010101 | 10 00 00 00 = 10010101 is the final LEDcmds entry found = 1; // Found Entry so don't keep searching for matching LED/GPS location } } } }//END GenerateGreenCMDs Function /************************** * GenerateBlueCMDs * Uses the Blue color location arrays * to find determine which LEDs need to * be lit and modifies LEDcmds accordingly **************************/ void GenerateBlueCMDs(){ unsigned char ICDrvNum; unsigned char ICBankNum; for(BUSi = 0; ((BUSi < 8) && (currentBLUE[BUSi*2] != 0xFFFF)); BUSi++){ //Goes through the six possible blue locations found = 0; for(i = 0; ((i < 42) && !found); i++){ if((currentBLUE[BUSi*2] >= (pgm_read_word_near(GPSdata+(i*4)))) && (currentBLUE[BUSi*2] <= (pgm_read_word_near(GPSdata+((i*4)+1)))) && (currentBLUE[(BUSi*2)+1] >= (pgm_read_word_near(GPSdata+(i*4)+2))) && (currentBLUE[(BUSi*2)+1] <= (pgm_read_word_near(GPSdata+(i*4)+3)))) { if(BLINK0) CMD = (BLINK0cmd<<(2*(pgm_read_byte_near(BlueInfo+(i*3)+2)))); // so if BLINK0 = 10, an led location is #3 in bank, 10 00 00 00 if(ON) CMD = (ONcmd<<(2*(pgm_read_byte_near(BlueInfo+(i*3)+2)))); // so if ON = 00, and led location is #3 in bank, 00 00 00 00 ICDrvNum = (pgm_read_byte_near(BlueInfo+(i*3))); // Which Driver LED is connected to = (i*3) ICBankNum = (pgm_read_byte_near(BlueInfo+(i*3)+1)); // Which Bank on LED Driver = ((i*3)+1) bitMask = (0x01<<(2*(pgm_read_byte_near(BlueInfo+(i*3)+2)))); // (Location in Bank=((i*3)+2) so if i=5, 17th value in blue info = 3, *2, says shift in a 1, 6 places, // to represent the value/LED to modify 01<<6 = 01000000 // This bitmask is used so previous changes to the particular bank are not modified (LEDcmds[ICDrvNum][ICBankNum]) -= bitMask; // So if LEDcmds started at 01010101 and bitMask is now 01000000 // then 01010101 - 01000000 = is 00010101 is new LEDcmds entry (LEDcmds[ICDrvNum][ICBankNum]) |= CMD; // 00010101 | 10 00 00 00 = 10010101 is the final LEDcmds entry found = 1; // Found Entry so don't keep searching for matching LED/GPS location } } } }//END GenerateBlueCMDs Function /************************** * GenerateYellowCMDs * Uses the Yellow color location arrays * to find determine which LEDs need to * be lit and modifies LEDcmds accordingly **************************/ void GenerateYellowCMDs(){ unsigned char ICDrvNum; unsigned char ICBankNum; for(BUSi = 0; ((BUSi < 8) && (currentYELLOW[BUSi*2] != 0xFFFF)); BUSi++){ //Goes through the six possible red locations found = 0; for(i = 0; ((i < 42) && !found); i++){ if((currentYELLOW[BUSi*2] >= (pgm_read_word_near(GPSdata+(i*4)))) && (currentYELLOW[BUSi*2] <= (pgm_read_word_near(GPSdata+((i*4)+1)))) && (currentYELLOW[(BUSi*2)+1] >= (pgm_read_word_near(GPSdata+(i*4)+2))) && (currentYELLOW[(BUSi*2)+1] <= (pgm_read_word_near(GPSdata+(i*4)+3)))) { //Red Section if(BLINK0) CMD = (BLINK0cmd<<(2*(pgm_read_byte_near(RedInfo+(i*3)+2)))); // so if BLINK0 = 10, an led location is #3 in bank, 00 10 00 00 if(ON) CMD = (ONcmd<<(2*(pgm_read_byte_near(RedInfo+(i*3)+2)))); // so if ON = 00, and led location is #3 in bank, 00 00 00 00 ICDrvNum = (pgm_read_byte_near(RedInfo+(i*3))); // Which Driver LED is connected to = (i*3) ICBankNum = (pgm_read_byte_near(RedInfo+(i*3)+1)); // Which Bank on LED Driver = ((i*3)+1) bitMask = (0x01<<(2*(pgm_read_byte_near(RedInfo+(i*3)+2)))); // (Location in Bank=((i*3)+2) so if i=5, 17th value in red info = 2, *2, says shift in a 11, 4 places, // to represent the value/LED to modify 01<<4 = 00010000 // This bitmask is used so previous changes to the particular bank are not modified (LEDcmds[ICDrvNum][ICBankNum]) -= bitMask; // So if LEDcmds started at 01010101 and bitMask is now 00010000 // then 01010101 - 00010000 = is 01000101 is new LEDcmds entry (LEDcmds[ICDrvNum][ICBankNum]) |= CMD; // 01 00 01 01 | 00 10 00 00 = 01 10 01 01 is the final LEDcmds entry //End Red Section //Green Section if(BLINK0) CMD = (BLINK0cmd<<(2*(pgm_read_byte_near(GreenInfo+(i*3)+2)))); // so if BLINK0 = 10, an led location is #3 in bank, 00 10 00 00 if(ON) CMD = (ONcmd<<(2*(pgm_read_byte_near(GreenInfo+(i*3)+2)))); // so if ON = 00, and led location is #3 in bank, 00 00 00 00 ICDrvNum = (pgm_read_byte_near(GreenInfo+(i*3))); // Which Driver LED is connected to = (i*3) ICBankNum = (pgm_read_byte_near(GreenInfo+(i*3)+1)); // Which Bank on LED Driver = ((i*3)+1) bitMask = (0x01<<(2*(pgm_read_byte_near(GreenInfo+(i*3)+2)))); // (Location in Bank=((i*3)+2) so if i=5, 17th value in GREEN info = 2, *2, says shift in a 11, 4 places, // to represent the value/LED to modify 01<<4 = 00010000 // This bitmask is used so previous changes to the particular bank are not modified (LEDcmds[ICDrvNum][ICBankNum]) -= bitMask; // So if LEDcmds started at 01010101 and bitMask is now 00010000 // then 01010101 - 00010000 = is 01000101 is new LEDcmds entry (LEDcmds[ICDrvNum][ICBankNum]) |= CMD; // 01 00 01 01 | 00 10 00 00 = 01 10 01 01 is the final LEDcmds entry //End Green Section found = 1; // Found Entry so don't keep searching for matching LED/GPS location } } } }//END GenerateYellowCMDs Function /************************** * setup * Automatically Ran once when Arduino starts up, then continues on to run loop() forever. * Sets Serial Baud Rate. Sets Each Drivers Initial State including Setting Each Drivers * Blink Rates and setting all LEDs to OFF to begin with. **************************/ void setup(){ Wire.begin(); //starts Arduino as master I2C Serial.begin(38400); //serial for debugging delay(50); setBlinkRate(); //Sets all Drivers' BLINK0 rate to faster blink rate, to save power. setInternet(); //Attempts to get online, and retries until it is online and recieves the I/ONLINE command SendNewCommands(); //First time is ran, all locations are set to OFF as LEDcmds Array Banks are all 0x55. //Subsequent calls, result in only the newly updated LEDcmds[][] array sent out, //generated from GenerateCMDs function, when called within loop(). }//END setup Function /******************* * MAIN LOOP FUNCTION, runs forever after setup function runs once * Responsible for calling FinLatLon(of each color) , gets XML data and loads Current[color] arrays, then * calls each Generate[color]CMDs color, then sends new LEDcmds[][] to all the IC Drivers, * then waits 10 seconds, clears the LEDcmds array, clears Current[color] arrays of each color *********************/ void loop(){ delay(2500); FindLatLon(0); //FIND & PARSE RED XML DATA GenerateRedCMDs(); //Search currentRED Array data for any GPS Location Matches delay(2500); FindLatLon(1); //FIND & PARSE GREEN XML DATA GenerateGreenCMDs(); //Search currentGREEN Array data for any GPS Location Matches delay(2500); FindLatLon(2); //FIND & PARSE BLUE XML DATA GenerateBlueCMDs(); //Search currentBLUE Array data for any GPS Location Matches delay(2500); FindLatLon(3); //FIND & PARSE TROLLEY XML DATA GenerateYellowCMDs(); //Search currentYELLOW Array data for any GPS Location Matches SendNewCommands(); //Send all LED Bank Data out again, which previous 3 functions modified. ResetLEDcmds(); //Reset all to off so can be modified by Generate Functions before being sent out again. ResetCurrentArrays(); //Reset CurrentArrays, so next time old data is not left behind }//End Main Loop function // this function will return the number of bytes currently free in RAM // written by David A. Mellis // based on code by Rob Faludi http://www.faludi.com int availableMemory() { int size = 1024; byte *buf; while ((buf = (byte *) malloc(--size)) == NULL) ; free(buf); return size; } //another mem function extern int __bss_end; extern void *__brkval; int get_free_memory(){ int free_memory; if((int)__brkval == 0) free_memory = ((int)&free_memory) - ((int)&__bss_end); else free_memory = ((int)&free_memory) - ((int)__brkval); return free_memory; }