version for testing not implemented: delta loop safety, power surge, calibration mode

Dependencies:   mbed TextLCD

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include <string>
00003 #include <stdarg.h>
00004 #include "TextLCD.h"
00005 #include "MCP23017.h"
00006 #include "math.h"
00007 #include <list>    
00008 
00009 const bool test = false;
00010 int iter;
00011 std::list<int> passedMarkers;
00012 std::list<int>::iterator it;
00013 int speedsetting; 
00014 
00015 //BOX CONNECTIONS
00016 DigitalIn button1 (p8);
00017 DigitalIn button2 (p9);
00018 DigitalIn button3 (p10);
00019 DigitalIn button4 (p30);
00020 AnalogIn potentio (p15); // configures pin15 for analog input. Creates object Ain. It is the potentiometer.
00021 TextLCD lcd(p22, p21, p23, p24, p25, p26); // configures the LCD pins. Creates object lcd
00022 DigitalOut led1(LED1);
00023 DigitalOut led2(LED2);
00024 DigitalOut led3(LED3);
00025 DigitalOut led4(LED4);
00026 DigitalOut boxled1 (p19);
00027 DigitalOut boxled2 (p20);
00028 DigitalOut buzzer (p29);
00029 Serial pc(USBTX, USBRX); // Initialise the serial connection for terminal output
00030 InterruptIn int0(p13);
00031 InterruptIn int1(p14);
00032 I2C i2c(p28, p27);
00033 MCP23017 *mcp;  //hall detectors
00034 DigitalOut data(p16); // configures pin16 for digital output. Creates object train. This signal should go to the booster
00035 DigitalOut enable(p17); //configures pin 17 for digital output. creates object enable, this enables the train track or disables it in case of emergency
00036 
00037 //CONSTANTS
00038 const unsigned int DCCaddress_train1 = 0x01;
00039 const unsigned int DCCaddress_train2 = 0x02;
00040 const unsigned int DCCaddress_decoder = 0x06;
00041 const unsigned int DCCinst_stop = 0x70;         //stop 01 1 1 0000
00042 const unsigned int DCCinst_estop = 0x71;        //01 1 1 0001
00043 const unsigned int DCCswitchneutral = 0b10000000;
00044 const unsigned int DCCswitch1 = 0b10000001;
00045 const unsigned int DCCswitch2 = 0b10000010;
00046 const unsigned int DCCswitch3 = 0b10000100;
00047 const unsigned int DCCswitch4 = 0b10001000;
00048 const double stationWaitTime = 5.;
00049 const double switchsafety = 4.; //contant time limit between uses of same switch
00050 const int switchwait = 1500; //time inbetween different switch commands
00051 
00052 //interrupt flags
00053 bool int0flag;
00054 bool int1flag;
00055 
00056 //global variables for train1
00057 bool dir1;
00058 bool light1;
00059 int speed1;
00060 int prev1;
00061 int curr1;
00062 int next1;
00063 Timer station1;
00064 bool boarding1;
00065 bool command1;
00066 
00067 bool collision;
00068 
00069 //global variables for train2
00070 bool dir2;
00071 bool light2;
00072 int speed2;
00073 int prev2;
00074 int curr2;
00075 int next2;
00076 Timer station2;
00077 bool boarding2;
00078 bool command2;
00079 
00080 //global variables for switches
00081 std::time_t switch1action;
00082 std::time_t switch2action;
00083 std::time_t switch3action;
00084 std::time_t switch4action;
00085 bool switch1;
00086 bool switch2;
00087 bool switch3;
00088 bool switch4;
00089 
00090 //FUNCTION PROTOTYPES
00091 void init_mcp(void);
00092 void on_int0_change(void);
00093 void on_int1_change(void);
00094 std::list<int> circuit0markers(int sensor_data);
00095 std::list<int> circuit1markers(int sensor_data);
00096 
00097 void displayTerminalStatus(void);
00098 void displayLCDstatus(void);
00099 
00100 void init(void);
00101 void initSwitches(void);
00102 void startupWait(void);
00103 void emergencyStop(void);
00104 void handleInt0(void);
00105 void handleInt1(void);
00106 void trainCommand(void);
00107 void updateTrainStatus(int marker);
00108 int predictNextMarker(int prev, int curr);
00109 void iterAction(void);
00110 
00111 void changeSwitch1(bool);
00112 void changeSwitch2(bool);
00113 void changeSwitch3(bool);
00114 void changeSwitch4(bool);
00115 void updateTrainPredictions(void);
00116 
00117 unsigned int trainInstruction(bool direction, bool light, int speed);
00118 void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count);
00119 
00120 void driveTrain(int train);
00121 void reverseTrain(int train);
00122 void stopTrain(int train);
00123 
00124 void atStation2(int train);
00125 void atStation12(int train);
00126 void atSwitch3(int train);
00127 void atSwitch4(int train);
00128 void headCollision(void);
00129 void sideCollision(void);
00130 void xCollision(void);
00131 bool isXCollision(void);
00132 void tailCollision(int backTrain);
00133 void atStation(int train);
00134 //void loopDeltaCrossing(int train);
00135 
00136 int main() {
00137     buzzer = 0;
00138     wait_ms(1000); //safety wait when starting (power surge)
00139     enable = false; //track off while doing startup
00140     while(1){
00141         init(); // initialize all the things to starting values
00142         startupWait(); //wait for user to press button 3 to begin
00143         enable = true;
00144         initSwitches(); //put switches in starting position
00145         wait_ms(2000); //power surge safety
00146         if(int0flag || int1flag){
00147             pc.printf("WARNING: Initialization power surge! Sensor ignored\n\r"); 
00148             if(int0flag){
00149                 int trash = mcp->_read(INTCAPA);
00150                 int0flag = false;
00151             }
00152             if(int1flag){
00153                 int trash = mcp->_read(INTCAPB);
00154                 int1flag = false;
00155             }  
00156         }
00157         
00158         if(!test){
00159             iter = 0; //iter count   
00160             while(enable){
00161                 if(!button4){ 
00162                     emergencyStop();
00163                     break;
00164                 }          
00165                 
00166                 if(int0flag){
00167                     handleInt0(); //store passed circuit 0 markers in the list passed markers
00168                 }
00169             
00170                 if(int1flag){
00171                     handleInt1(); //same for circuit 1
00172                 }
00173                 
00174                 if(!passedMarkers.empty()){ 
00175                     for (it=passedMarkers.begin(); it!=passedMarkers.end(); ++it){
00176                         if(*it != next1 && *it != next2 && *it != curr1 && *it != curr2){  //TODO check if safe
00177                             pc.printf("ERROR: Unexpected marker %d. Expected train1: %d or train2: %d. Sensor failure or unknown object on track. Aborting.\n\r", *it, next1, next2);
00178                             enable = false;
00179                             break;   
00180                         }        
00181                         updateTrainStatus(*it);
00182                     }
00183                     passedMarkers.clear();  
00184                 }
00185                 
00186                 trainCommand(); //decides for a command to send to the track
00187                 
00188                 iterAction(); //every X iterations display some stuff
00189                 iter++;
00190             }
00191         } else {
00192             //test scripts   
00193         }
00194     }
00195 }
00196 
00197 //MAIN LOOP ROUTINES
00198 void init(){  
00199     command1 = false;
00200     command2 = false;
00201     collision = false;
00202       
00203     //initialize clock time
00204     set_time(1);
00205     switch1action = time(NULL);
00206     switch2action = time(NULL);
00207     switch3action = time(NULL);
00208     switch4action = time(NULL);
00209     
00210     led1 = 0;
00211     led2 = 0;
00212     led3 = 0;
00213     buzzer = 0;
00214     boxled1 = 0;
00215     boxled2 = 0;
00216     
00217     speedsetting = 7;
00218     
00219     //pc.baud(921600); //faster printing
00220     pc.baud(19200);
00221     
00222     //initialize mcp   //(initialize interrupt flags)
00223     init_mcp();
00224   
00225     //initialize train globals
00226     dir1 = true;
00227     light1 = true;
00228     speed1 = speedsetting;
00229     boarding1 = false;
00230     //train 1 starting position
00231     prev1 = 0;
00232     curr1 = 1;
00233     next1 = predictNextMarker(prev1, curr1); //2
00234 
00235     //global variables for train2
00236     dir2 = true;
00237     light2 = true;
00238     speed2 = speedsetting;
00239     boarding2 = false;
00240     //train 2 starting position
00241     prev2 = 4;
00242     curr2 = 6;
00243     next2 = predictNextMarker(prev2, curr2); //7
00244 
00245     //initialize presumed switch positions
00246     switch1 = false;
00247     switch2 = false;
00248     switch3 = false;
00249     switch4 = false;
00250 }
00251 
00252 void startupWait(){
00253     lcd.cls();
00254     lcd.printf("Press START when ready");
00255     pc.printf("Press START when ready. Starting position: train 1 between marker 1 and 2, train 2 between marker 6 and 7.\n\r");  
00256     while(button3){
00257         //do nothing   
00258     }
00259     pc.printf("Starting...\n\r");  
00260 }
00261 
00262 void initSwitches(){
00263     wait_ms(switchwait);
00264     changeSwitch1(switch1);
00265     wait_ms(switchwait);
00266     changeSwitch2(switch2);
00267     wait_ms(switchwait);
00268     changeSwitch3(switch3);
00269     wait_ms(switchwait);
00270     changeSwitch4(switch4);
00271     wait_ms(500);
00272 }
00273 
00274 void emergencyStop(){
00275     enable = false;
00276     pc.printf("Emergency stop! Press button 3 when ready to restart\n\r");
00277     
00278     lcd.cls();
00279     lcd.printf("Press START when ready to restart");
00280     while(button3){
00281         //do nothing   
00282     }
00283 }
00284 
00285 void handleInt0(){
00286     wait_us(2000);
00287     int sensor_data = mcp->_read(INTCAPA);
00288     int0flag = false;
00289     std::list<int> temp = circuit0markers(sensor_data);
00290     passedMarkers.splice(passedMarkers.end(), temp);
00291 }
00292 
00293 void handleInt1(){
00294     wait_us(2000);
00295     int sensor_data = mcp->_read(INTCAPB);
00296     int1flag = false;  
00297     std::list<int> temp = circuit1markers(sensor_data);
00298     passedMarkers.splice(passedMarkers.end(), temp); 
00299 }
00300 
00301 void updateTrainStatus(int marker){
00302     if(marker == 21){
00303         return; //marker 21 is unused    
00304     }
00305     
00306     if(marker == next1){
00307         prev1 = curr1;
00308         curr1 = next1;
00309         next1 = predictNextMarker(prev1, curr1);
00310         command1 = false;
00311         collision = false;
00312         pc.printf("STATUS: Train 1 reached marker %d from marker %d. Predicted marker %d\n\r", curr1, prev1, next1);
00313     } else { //marker == next2
00314         prev2 = curr2;
00315         curr2 = next2;
00316         next2 = predictNextMarker(prev2, curr2);
00317         command2 = false;
00318         collision = false;
00319         pc.printf("STATUS: Train 2 reached marker %d from marker %d. Predicted marker %d\n\r", curr2, prev2, next2);
00320     }   
00321 }
00322 
00323 int predictNextMarker(int prev, int curr){
00324     switch(prev){
00325         case 0: switch(curr){
00326                     case 1: return 2;
00327                     case 13: return 12;
00328                 }
00329         case 1: switch(curr){
00330                     case 2: return switch2?3:4;
00331                     case 0: return 13;
00332                 }
00333         case 2: switch(curr){
00334                     case 3: return 9;
00335                     case 4: return 6;
00336                     case 1: return 0;
00337                 }
00338         case 3: switch(curr){
00339                     case 9: return 8;
00340                     case 2: return 1;
00341                 }
00342         case 4: switch(curr){
00343                     case 6: return 7;
00344                     case 2: return 1;
00345                 }
00346         case 5: switch(curr){
00347                     case 6: return 7;
00348                     case 11: return 12;
00349                 }
00350         case 6: switch(curr){
00351                     case 4: return 2;
00352                     case 5: return 11;
00353                     case 7: return 8;
00354                 }
00355         case 7: switch(curr){
00356                     case 6: return switch3?5:4;
00357                     case 8: return switch4?9:10;
00358                 }
00359         case 8: switch(curr){
00360                     case 7: return 6;
00361                     case 9: return 3;
00362                     case 10: return 12;
00363                 }
00364         case 9: switch(curr){
00365                     case 3: return 2;
00366                     case 8: return 7;
00367                 }
00368         case 10: switch(curr){
00369                     case 8: return 7;
00370                     case 12: return 13;
00371                 }
00372         case 11: switch(curr){
00373                     case 5: return 6;
00374                     case 12: return 13;
00375                 }
00376         case 12: switch(curr){
00377                     case 10: return 8;
00378                     case 11: return 5;
00379                     case 13: return 0;
00380                 }
00381         case 13: switch(curr){
00382                     case 0: return 1;
00383                     case 12: return switch1?11:10;
00384                 }       
00385     }
00386     return 666; //TODO default
00387 }  
00388 
00389 void iterAction(){
00390     displayLCDstatus();
00391     if(iter % 100 == 0){
00392         displayTerminalStatus();
00393     }
00394 }
00395 
00396 //TRAIN COMMAND
00397 void trainCommand(){
00398     float Vin = potentio.read() * 3.3;
00399     speedsetting = floor(Vin/0.22);  //0.22 = 3.3/15  
00400     
00401     if(boarding1 || boarding2){
00402         if(station1.read() > stationWaitTime){ //timer works? TODO
00403              boarding1 = false;
00404              led1 = 0;
00405              station1.stop();          
00406         } 
00407                     
00408         if(station2.read() > stationWaitTime){
00409              boarding2 = false;
00410              led2 = 0;
00411              station2.stop();          
00412         }
00413     }
00414     speed1 = boarding1?0:speedsetting;
00415     speed2 = boarding2?0:speedsetting;
00416     
00417     if(next1 == next2 && !collision){
00418         headCollision();
00419         collision = true;
00420     } else if ((next1 == curr2 || next2 == curr1) && !collision){
00421         sideCollision();
00422         collision = true;
00423     } else if (isXCollision() && !collision){
00424         xCollision();
00425         collision = true;
00426     } else if (next1 == prev2 && !command1){
00427         tailCollision(1);
00428         command1 = true;
00429     } else if (next2 == prev1 && !command1){
00430         tailCollision(2);
00431         command1 = true;
00432     } else if (curr1 == 2 && !command1){
00433         atStation2(1);
00434         command1 = true;
00435     } else if (curr1 == 6 && !command1){
00436         atSwitch3(1);
00437         command1 = true;
00438     } else if (curr1 == 8 && !command1){
00439         atSwitch4(1);
00440         command1 = true;
00441     } else if (curr1 == 12 && !command1){
00442         atStation12(1);
00443         command1 = true;
00444     } else if (curr2 == 2 && !command2){
00445         atStation2(1);
00446         command2 = true;
00447     } else if (curr2 == 6 && !command2){
00448         atSwitch3(2);
00449         command2 = true;
00450     } else if (curr2 == 8 && !command2){
00451         atSwitch4(2);
00452         command2 = true;
00453     } else if (curr2 == 12 && !command2){
00454         atStation12(2);
00455         command2 = true;
00456     }
00457     
00458     driveTrain(2);
00459     driveTrain(1);
00460     
00461     /*
00462     else if (!command1 && (curr1 == 9 && next1 == 3) || (curr1 == 5 && next1 == 11)){
00463         loopDeltaCrossing(1);
00464         command1 = true;
00465     } else if (!command2 && (curr2 == 9 && next2 == 3) || (curr2 == 5 && next2 == 11)){
00466         loopDeltaCrossing(2);
00467         command2 = true;
00468     } 
00469     */
00470 }
00471 
00472 bool isXCollision(){
00473     return (curr1 == 3 && next1 == 9) && (next2 == 5 || next2 == 11)
00474         || (curr1 == 5 && next1 == 11) && (next2 == 3 || next2 == 9)
00475         || (curr1 == 9 && next1 == 3) && (next2 == 5 || next2 == 11)
00476         || (curr1 == 11 && next1 == 5) && (next2 == 3 || next2 == 9)
00477         || (curr2 == 3 && next2 == 9) && (next1 == 5 || next1 == 11)
00478         || (curr2 == 5 && next2 == 11) && (next1 == 3 || next1 == 9)
00479         || (curr2 == 9 && next2 == 3) && (next1 == 5 || next1 == 11)
00480         || (curr2 == 11 && next2 == 5) && (next1 == 3 || next1 == 9);
00481 }
00482 
00483 void stopTrain(int train){
00484     if(train == 1){
00485         DCC_send_command(DCCaddress_train1, DCCinst_estop, 10);
00486         pc.printf("STATUS: Train 1 stopped\n\r");
00487     } else { //train == 2
00488         DCC_send_command(DCCaddress_train2, DCCinst_estop, 10);
00489         pc.printf("STATUS: Train 2 stopped\n\r");
00490     }
00491 }
00492 
00493 void reverseTrain(int train){ //always stop before reversing
00494     if(train == 1){
00495         int stupid;
00496         dir1 = !dir1;
00497         stupid = next1;
00498         next1 = curr1;
00499         curr1 = stupid;
00500         prev1 = predictNextMarker(curr1, next1);
00501         pc.printf("STATUS: Train 1 reversed\n\r");
00502     } else { //train == 2
00503         int swap;
00504         dir2 = !dir2;
00505         swap = next2;
00506         next2 = curr2;
00507         curr2 = swap;
00508         prev2 = predictNextMarker(curr2, next2);
00509         pc.printf("STATUS: Train 2 reversed\n\r");
00510     }
00511 }
00512 
00513 void driveTrain(int train){
00514     if(train == 1){
00515         DCC_send_command(DCCaddress_train1, trainInstruction(dir1, light1, speed1), 25);
00516     } else { //train == 2
00517         DCC_send_command(DCCaddress_train2, trainInstruction(dir2, light2, speed2), 25);  
00518     }
00519 }
00520 
00521 void atStation2(int train){
00522     if(train == 1){
00523         if(next1 != 22){
00524             pc.printf("STATUS: train 1 reached switch 2\n\r");
00525             std::time_t current = time(NULL);
00526             if(difftime(current, switch2action) < switchsafety){
00527                 pc.printf("STATUS: Switch 2 on overheat cooldown!\n\r"); 
00528                 return;
00529             }
00530             stopTrain(1);
00531             if(curr2 == 6 || next2 == 6){
00532                 switch2 = true;
00533             } else if(curr2 == 9 || next2 == 9){
00534                 switch2 = false;
00535             } else { //other train far away
00536                 switch2 = rand()%2;
00537             }
00538             changeSwitch2(switch2);
00539             switch2action = time(NULL);
00540         }
00541         atStation(1);
00542     } else { //train == 2
00543         if(next2 != 22){
00544             pc.printf("STATUS: train 2 reached switch 2\n\r");
00545             std::time_t current = time(NULL);
00546             if(difftime(current, switch2action) < switchsafety){
00547                 pc.printf("STATUS: Switch 2 on overheat cooldown!\n\r"); 
00548                 return;
00549             }
00550             stopTrain(2);
00551             if(curr1 == 6 || next1 == 6){
00552                 //switch2 = true;
00553             } else if(curr1 == 9 || next1 == 9){
00554                 //switch2 = false;
00555             } else { //other train far away
00556                 switch2 = rand()%2;
00557             }
00558             changeSwitch2(switch2);
00559             switch2action = time(NULL); 
00560         }
00561         atStation(2);
00562     }
00563 }
00564 
00565 void atStation12(int train){
00566     if(train == 1){
00567         if(next1 != 22){
00568             pc.printf("STATUS: train 1 reached switch 1\n\r");
00569             std::time_t current = time(NULL);
00570             if(difftime(current, switch1action) < switchsafety){
00571                 pc.printf("STATUS: Switch 1 on overheat cooldown!\n\r"); 
00572                 return;
00573             }
00574             stopTrain(1);
00575             if(curr2 == 8 || next2 == 8){
00576                 //switch1 = true;
00577             } else if(curr2 == 5 || next2 == 5){
00578                 //switch1 = false;
00579             } else { //other train far away
00580                 switch1 = rand()%2;
00581             }
00582             changeSwitch1(switch1);
00583             switch1action = time(NULL);
00584         }
00585         atStation(1);
00586     } else { //train == 2
00587         if(next2 != 22){
00588             pc.printf("STATUS: train 2 reached switch 1\n\r");
00589             std::time_t current = time(NULL);
00590             if(difftime(current, switch1action) < switchsafety){
00591                 pc.printf("STATUS: Switch 1 on overheat cooldown!\n\r"); 
00592                 return;
00593             }
00594             stopTrain(2);
00595             if(curr1 == 8 || next1 == 8){
00596                 //switch1 = true;
00597             } else if(curr1 == 5 || next1 == 5){
00598                 //switch1 = false;
00599             } else { //other train far away
00600                 switch1 = rand()%2;
00601             }
00602             changeSwitch1(switch1);
00603             switch1action = time(NULL); 
00604         }
00605         atStation(2);
00606     }
00607 }
00608 
00609 void atStation(int train){
00610     if(train == 1){
00611         pc.printf("STATUS: Train 1 reached station!\n\r");
00612         boxled1 = 1;
00613         speed1 = 0;
00614         station1.start();
00615         boarding1 = true;
00616     } else { //train == 2
00617         pc.printf("STATUS: Train 2 reached station!\n\r");
00618         boxled2 = 1;
00619         speed2 = 0;
00620         station2.start();
00621         boarding2 = true;
00622     }
00623 }
00624 
00625 void atSwitch3(int train){
00626     if(train == 1){
00627         if(next1 == 7){ return; }
00628         pc.printf("STATUS: train 1 reached switch 3\n\r");
00629         std::time_t current = time(NULL);
00630         if(difftime(current, switch3action) < switchsafety){
00631                 pc.printf("STATUS: Switch 3 on overheat cooldown!\n\r"); 
00632                 return;
00633         }
00634         stopTrain(1);
00635         if(curr2 == 2 || next2 == 2){
00636             //switch3 = true; TODO complicated
00637         } else if(curr2 == 11 || next2 == 11){
00638             //switch3 = false;
00639         } else { //other train far away
00640             switch3 = rand()%2;
00641         }
00642         changeSwitch3(switch3);
00643         switch3action = time(NULL);
00644     } else { //train == 2
00645         if(next2 == 7){ return; }
00646         pc.printf("STATUS: train 2 reached switch 3\n\r");
00647         std::time_t current = time(NULL);
00648         if(difftime(current, switch3action) < switchsafety){
00649             pc.printf("STATUS: Switch 3 on overheat cooldown!\n\r"); 
00650             return;
00651         }
00652         stopTrain(2);
00653         if(curr1 == 2 || next1 == 2){
00654             //switch3 = true;
00655         } else if(curr1 == 11 || next1 == 11){
00656             //switch3 = false;
00657         } else { //other train far away
00658             switch3 = rand()%2;
00659         }
00660         changeSwitch3(switch3);
00661         switch3action = time(NULL);
00662     }
00663 }
00664 
00665 void atSwitch4(int train){
00666     if(train == 1){
00667         if(next1 == 7){ return; }
00668         pc.printf("STATUS: train 1 reached switch 4\n\r");
00669         std::time_t current = time(NULL);
00670         if(difftime(current, switch4action) < switchsafety){
00671             pc.printf("STATUS: Switch 4 on overheat cooldown!\n\r"); 
00672             return;
00673         }
00674         stopTrain(1);
00675         if(curr2 == 2 || next2 == 2){
00676             //switch4 = true;
00677         } else if(curr2 == 11 || next2 == 11){
00678             //switch4 = false;
00679         } else { //other train far away
00680             switch4 = rand()%2;
00681         }
00682         changeSwitch4(switch4);
00683         switch4action = time(NULL);
00684     } else { //train == 2
00685         if(next2 == 7){ return; }
00686         pc.printf("STATUS: train 2 reached switch 4\n\r");
00687         std::time_t current = time(NULL);
00688         if(difftime(current, switch4action) < switchsafety){
00689             pc.printf("STATUS: Switch 4 on overheat cooldown!\n\r"); 
00690             return;
00691         }
00692         stopTrain(2);
00693         if(curr1 == 2 || next1 == 2){
00694             //switch4 = true;
00695         } else if(curr1 == 11 || next1 == 11){
00696             //switch4 = false;
00697         } else { //other train far away
00698             switch4 = rand()%2;
00699         }
00700         changeSwitch4(switch4);
00701         switch4action = time(NULL);   
00702     }
00703 }
00704 
00705 void headCollision(void){
00706     buzzer = 1;
00707     pc.printf("WARNING: inbound head collision\n\r");
00708     stopTrain(1);
00709     stopTrain(2);
00710     reverseTrain(1);
00711     reverseTrain(2);
00712     buzzer = 0;
00713 }
00714 
00715 void sideCollision(void){
00716     buzzer = 1;
00717     pc.printf("WARNING: possible side collision\n\r");
00718     stopTrain(1);
00719     stopTrain(2);
00720     reverseTrain(1);
00721     reverseTrain(2);
00722     buzzer = 0;
00723 }
00724 
00725 void xCollision(void){
00726     buzzer = 1;
00727     pc.printf("WARNING: possible cross collision\n\r");
00728     stopTrain(1);
00729     stopTrain(2);
00730     reverseTrain(1);
00731     reverseTrain(2);
00732     buzzer = 0;
00733 }
00734 
00735 void tailCollision(int backTrain){
00736     buzzer = 1;
00737     pc.printf("WARNING: possible tail collision\n\r");
00738     stopTrain(backTrain);
00739     reverseTrain(backTrain);
00740     buzzer = 0;
00741 }
00742 /*
00743 void loopDeltaCrossing(int train){
00744     buzzer = 1;
00745     pc.printf("WARNING: attempting to exit the loop\n\r");
00746     if(train == 1){
00747         if(curr2 != 13 && curr2 != 0 && curr2 != 1 && curr2 != 2){
00748             stopTrain(1);
00749             reverseTrain(1);   
00750         }
00751         //if train 2 in loop
00752             //stop, reverse
00753     } else { //train == 2    
00754         //if train 1 in loop
00755             //stop, reverse
00756         if(curr1 != 13 && curr1 != 0 && curr1 != 1 && curr1 != 2){
00757             stopTrain(1);
00758             reverseTrain(1);   
00759         }
00760     }
00761     buzzer = 0;
00762 }
00763 */
00764 
00765 
00766 
00767 
00768 //TRACK COMMANDS
00769 //code from the tutorial, sends a message to the track through the train pin
00770 void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){
00771     switch(address){
00772         case DCCaddress_train1: led1 = 1; break;
00773         case DCCaddress_train2: led2 = 1; break;
00774         case DCCaddress_decoder: led3 = 1; break;    
00775     }
00776     
00777     unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type
00778     unsigned __int64 temp_command = 0x0000000000000000;
00779     unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start
00780     unsigned int error = 0x00; //error byte
00781     //calculate error detection byte with xor
00782     error = address ^ inst;
00783     //combine packet bits in basic DCC format
00784     command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01;
00785     //printf("\n\r %llx \n\r",command);
00786     int i=0;
00787     //repeat DCC command lots of times
00788     while(i < repeat_count) {
00789         temp_command = command;
00790     //loops through packet bits encoding and sending out digital pulses for a DCC command
00791         for (int j=0; j<64; j++) {
00792             if((temp_command&0x8000000000000000)==0) { //test packet bit
00793                 //send data for a "0" bit
00794                 data=0;
00795                 wait_us(100);
00796                 data=1;
00797                 wait_us(100);
00798                 //printf("0011");
00799             } else {
00800                 //send data for a "1"bit
00801                 data=0;
00802                 wait_us(58);
00803                 data=1;
00804                 wait_us(58);
00805                 //printf("01");
00806             }
00807             // next bit in packet
00808             temp_command = temp_command<<1;
00809         }
00810         i++;
00811     }
00812     
00813     led1 = 0;
00814     led2 = 0;
00815     led3 = 0;
00816 }
00817 
00818 void changeSwitch1(bool inwards){
00819     if(inwards){
00820         DCC_send_command(DCCaddress_decoder, DCCswitch1, 1);
00821         pc.printf("STATUS: Switch 1 changed inward\n\r");
00822     } else {
00823         DCC_send_command(DCCaddress_decoder, DCCswitch1, 1);
00824         DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1);
00825         pc.printf("STATUS: Switch 1 changed outward\n\r");        
00826     }
00827     updateTrainPredictions();
00828 }
00829 
00830 void changeSwitch2(bool inwards){
00831     if(inwards){
00832         DCC_send_command(DCCaddress_decoder, DCCswitch2, 1);
00833         pc.printf("STATUS: Switch 2 changed inward\n\r");
00834     } else {
00835         DCC_send_command(DCCaddress_decoder, DCCswitch2, 1);
00836         DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1);
00837         pc.printf("STATUS: Switch 2 changed outward\n\r");        
00838     }
00839     updateTrainPredictions();    
00840 }
00841 
00842 void changeSwitch3(bool inwards){
00843     if(inwards){
00844         DCC_send_command(DCCaddress_decoder, DCCswitch3, 1);
00845         DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1);  //switch 3 has reverse behavior
00846         pc.printf("STATUS: Switch 3 changed inward\n\r");
00847     } else {
00848         DCC_send_command(DCCaddress_decoder, DCCswitch3, 1);
00849         pc.printf("STATUS: Switch 3 changed outward\n\r");
00850     }
00851     updateTrainPredictions();    
00852 }
00853 
00854 void changeSwitch4(bool inwards){
00855     if(inwards){
00856         DCC_send_command(DCCaddress_decoder, DCCswitch4, 1);
00857         pc.printf("STATUS: Switch 4 changed inward\n\r");
00858     } else {
00859         DCC_send_command(DCCaddress_decoder, DCCswitch4, 1);
00860         DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1);
00861         pc.printf("STATUS: Switch 4 changed outward\n\r");        
00862     }
00863     updateTrainPredictions();    
00864 }
00865 
00866 void updateTrainPredictions(){  
00867     next1 = predictNextMarker(prev1, curr1);
00868     next2 = predictNextMarker(prev2, curr2);   
00869 }
00870 
00871 unsigned int trainInstruction(bool direction, bool light, int speed){
00872     unsigned int result = 0x40; //0100 0000
00873     if(direction){
00874         result += 0x20;  //0010 0000
00875     } 
00876     if(light){
00877         result += 0x10;  //0001 0000
00878     }
00879     if(speed>0 && speed<15){
00880         result += speed + 1;   
00881     }
00882     return result;   
00883 }
00884 
00885 //INTERPRET INTERRUPT SIGNALS
00886 //INTERRUPTS
00887 //code from the tutorial, initializes MCP and sets it up for interrupts
00888 void init_mcp() {
00889     // Initialisation of MCP registers, documentation on registers is available at
00890     //Niels/Abel/Robert/Natalia
00891     mcp = new MCP23017(i2c, 0x40);
00892     mcp->_write(IODIRA, (unsigned char )0xff);
00893     mcp->_write(IODIRB, (unsigned char )0xff);
00894     mcp->_write(IPOLA, (unsigned char )0x00);
00895     mcp->_write(IPOLB, (unsigned char )0x00);
00896     mcp->_write(DEFVALA, (unsigned char )0xff);
00897     mcp->_write(DEFVALB, (unsigned char )0xff);
00898     mcp->_write(INTCONA, (unsigned char )0xff);
00899     mcp->_write(INTCONB, (unsigned char )0xff);
00900     mcp->_write(IOCONA, (unsigned char )0x2);
00901     mcp->_write(IOCONB, (unsigned char )0x2);
00902     mcp->_write(GPPUA, (unsigned char )0xff);
00903     mcp->_write(GPPUB, (unsigned char )0xff);
00904 
00905     // Clear current interrupts
00906     mcp->_read(GPIOA);
00907     mcp->_read(GPIOB);
00908     // Register callbacks
00909     int0.fall(&on_int0_change);
00910     int1.fall(&on_int1_change);
00911     // Enable interrupts on the MCP
00912     mcp->_write(GPINTENA, (unsigned char )0xff);
00913     mcp->_write(GPINTENB, (unsigned char )0xff);
00914     
00915     int0flag = false;
00916     int1flag = false;
00917 }
00918 
00919 void on_int0_change() {
00920     int0flag = true;
00921 }
00922 
00923 void on_int1_change() {
00924     int1flag = true;
00925 }
00926 
00927 std::list<int> circuit0markers(int sensor_data){
00928     std::list<int> result;
00929     sensor_data = ~sensor_data;
00930     if((sensor_data & 0b00000001) == 0b00000001){
00931         result.push_back(0);
00932     }
00933     if((sensor_data & 0b00000010) == 0b00000010){
00934         result.push_back(1);
00935     }
00936     if((sensor_data & 0b00000100) == 0b00000100){
00937         result.push_back(2);
00938     }
00939     if((sensor_data & 0b00001000) == 0b00001000){
00940         result.push_back(3);
00941     }
00942     if((sensor_data & 0b00010000) == 0b00010000){
00943         result.push_back(4);
00944     }
00945     if((sensor_data & 0b00100000) == 0b00100000){
00946         result.push_back(5);
00947     }
00948     if((sensor_data & 0b01000000) == 0b01000000){
00949         result.push_back(6);
00950     }
00951     if((sensor_data & 0b10000000) == 0b10000000){
00952         result.push_back(7);
00953     }
00954     return result;
00955 }    
00956     
00957 std::list<int> circuit1markers(int sensor_data){
00958     std::list<int> result;
00959     sensor_data = ~sensor_data;
00960     if((sensor_data & 0b00000001) == 0b00000001){
00961         result.push_back(8);
00962     }
00963     if((sensor_data & 0b00000010) == 0b00000010){
00964         result.push_back(9);
00965     }
00966     if((sensor_data & 0b00000100) == 0b00000100){
00967         result.push_back(10);
00968     }
00969     if((sensor_data & 0b00001000) == 0b00001000){
00970         result.push_back(11);
00971     }
00972     if((sensor_data & 0b00010000) == 0b00010000){
00973         result.push_back(12);
00974     }
00975     if((sensor_data & 0b00100000) == 0b00100000){
00976         result.push_back(13);
00977     }
00978     if((sensor_data & 0b01000000) == 0b01000000){
00979         //result.push_back(21); do nothing; sensor 21 badly positioned
00980     }
00981     if((sensor_data & 0b10000000) == 0b10000000){
00982         //result.push_back(22); do nothing; too close
00983     }
00984     return result;
00985 }
00986 
00987 //LOG OUTPUT
00988 void displayLCDstatus(){
00989     lcd.cls();
00990     lcd.printf("Train 1: %d \nTrain 2: %d", speed1, speed2);   
00991 }
00992 
00993 void displayTerminalStatus(){
00994     string dir1Text = dir1?"forward":"reverse";
00995     string dir2Text = dir2?"forward":"reverse";
00996     string light1Text = light1?"on, ":"off,";
00997     string light2Text = light2?"on, ":"off,";
00998     pc.printf("SYSTEM: Iteration %d\n\r", iter);
00999     pc.printf("Train 1: dir %s, light %s spd %d\n\rTrain 2: dir %s, light %s spd %d\n\r", dir1Text.c_str(), light1Text.c_str(), speed1, dir2Text.c_str(), light2Text.c_str(), speed2);   
01000 }