Denver / Mbed 2 deprecated denver_train_proj

Dependencies:   mbed TextLCD

Revision:
57:ee5da8a011e0
Parent:
56:fe999806787d
Child:
58:b60db1092088
Child:
60:a1b987ad45fb
--- a/main.cpp	Thu Jun 21 12:22:36 2018 +0000
+++ b/main.cpp	Thu Jun 21 15:39:05 2018 +0000
@@ -91,6 +91,12 @@
 #define D22 15
 
 
+#define STOP 0
+#define SLOW 1
+#define MEDIUM 2
+#define FAST 3
+#define FULL 4
+#define R_MEDIUM 5
 
 
 /**
@@ -156,6 +162,74 @@
 
 /**
 *
+*Method to send DCC commands to train and switches.
+*
+*@address - (HEX)Address where the commands will be sent
+*@inst - (HEX)Number of instruction that will be commanded
+*@repeat_count - Number of times the command will be sent
+*
+**/
+void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){
+    
+    unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type
+    unsigned __int64 temp_command = 0x0000000000000000;
+    unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start
+    unsigned int error = 0x00; //error byte
+    
+    //calculate error detection byte with xor
+    error = address ^ inst;
+    
+    //combine packet bits in basic DCC format
+    command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01;
+    //printf("\n\r %llx \n\r",command);
+    
+    int i=0;
+    //repeat DCC command lots of times
+    while(i < repeat_count) {
+        
+        temp_command = command;
+        //loops through packet bits encoding and sending out digital pulses for a DCC command
+        for (int j=0; j<64; j++) {
+            
+            if((temp_command&0x8000000000000000)==0) { 
+            //test packet bit
+                //send data for a "0" bit
+                Track=0;
+                wait_us(100);
+                Track=1;
+                wait_us(100);
+                //printf("0011");
+            }else{
+                
+                //send data for a "1"bit
+                Track=0;
+                wait_us(58);
+                Track=1;
+                wait_us(58);
+                //printf("01");
+            }
+            // next bit in packet
+            temp_command = temp_command<<1;
+        }
+        i++;
+    }
+}
+
+/**
+*Defining areas for train detection and collision logic.
+*area_A_arr/area_B_arr - Arrays that hold the Dsensors for each area, used to initialize the vectors.
+*area_A/area_B - Vectors that hold the different sensors of the corresponding areas of the track.
+**/
+int area_A_arr[] = {D21,D2,D22,D1,D0,D13,D12};
+int area_B_arr[] = {D6,D7,D8};
+
+const vector<int> area_A(area_A_arr,area_A_arr + sizeof(area_A_arr) / sizeof(int));
+const vector<int> area_B(area_B_arr,area_B_arr + sizeof(area_B_arr) / sizeof(int));
+
+
+
+/**
+*
 *Train class.
 *
 *@position - 
@@ -174,10 +248,12 @@
 **/
 class Train{
     
-    private:
-        int mode;
+    private:       
+        
+        unsigned int train_address;    //stop the train        
         Position *position;
         bool going_cw;
+        int speed;
         
     public:
         Train(int pos, bool cw){
@@ -186,8 +262,16 @@
             going_cw = cw;
         }
         
+        /**
+        * Contructor that takes the address of the train and the speed with default value MEDIUM.
+        */
+        Train(unsigned int address, int s=MEDIUM){
+            train_address = address;
+            speed = s;
+        }
+        
         Train(bool cw){ going_cw = cw; }
-        
+                        
         vector<int> get_next_sensors(){
             
             //Checking direction
@@ -200,6 +284,45 @@
             }            
         }
         
+        void set_speed(int s){
+            speed = s;
+        }        
+                
+        /**
+        *   Sends a DCC command to the train with the speed indicaed by the attribute speed
+        *   The number of times the command is sent can be indicated as an optional parameter. Default value is 1.
+        */        
+        void run(int times=1){
+            
+            const unsigned int DCCinst_forward_slow = 0x66; //forward slow speed (step 9)
+            const unsigned int DCCinst_forward_medium = 0x68; //forward half speed
+            const unsigned int DCCinst_forward_fast = 0x6C; //Forward fast speed (step 22)
+            const unsigned int DCCinst_forward_full = 0x6F; //Forward full speed 
+            const unsigned int DCCinst_reverse_medium = 0x48; //reverse half speed
+            const unsigned int DCCinst_stop = 0x50;    //stop the train
+            
+            switch(speed){
+                case STOP:
+                    DCC_send_command(train_address, DCCinst_stop,times);
+                    break;
+                case SLOW:
+                    DCC_send_command(train_address, DCCinst_forward_slow,times);
+                    break;
+                case MEDIUM:
+                    DCC_send_command(train_address, DCCinst_forward_medium,times);
+                    break;
+                case FAST:
+                    DCC_send_command(train_address, DCCinst_forward_fast,times);
+                    break;
+                case FULL:
+                    DCC_send_command(train_address, DCCinst_forward_full,times);
+                    break;
+                case R_MEDIUM:
+                    DCC_send_command(train_address, DCCinst_reverse_medium,times);
+                    break;
+            }
+        }
+        
         void set_position(int pos){
             
             position = &positions[pos]; //Taking the new position from the positions vector
@@ -224,6 +347,39 @@
             
             return going_cw;
         }
+        
+        
+        /**
+        *
+        *Checks if the element exists within the vector.
+        *
+        *@v - The vector (of ints) the method will go through.
+        *@element - The element the method will look for.
+        *
+        **/
+        bool in_vector(vector<int>v,int element){
+            
+            bool exist = false;
+            
+            for(int i=0; i< v.size(); i++){
+                
+                if(v[i] == element){
+                    
+                    exist = true;
+                }
+            }   
+            return exist;
+        }
+        
+        bool is_in_A(){
+            return in_vector(area_A,get_position_number());
+            
+        }
+        
+        bool is_in_B(){
+            
+            return in_vector(area_B,get_position_number());
+        }
 };
 
 
@@ -245,25 +401,11 @@
 Position d21(D21);
 Position d22(D22);
 
-/**
-*Defining areas for train detection and collision logic.
-*area_A_arr/area_B_arr - Arrays that hold the Dsensors for each area, used to initialize the vectors.
-*area_A/area_B - Vectors that hold the different sensors of the corresponding areas of the track.
-**/
-int area_A_arr[] = {D21,D2,D22,D1,D0,D13,D12};
-int area_B_arr[] = {D6,D7,D8};
-
-const vector<int> area_A(area_A_arr,area_A_arr + sizeof(area_A_arr) / sizeof(int));
-const vector<int> area_B(area_B_arr,area_B_arr + sizeof(area_B_arr) / sizeof(int));
 
 
 
-//.....DCC TRAIN COMMAND VARS
 
-//typical out of box default engine DCC address is 3 (at least for Bachmann trains)
-//Note: A DCC controller can reprogram the address whenever needed
-const unsigned int DCCaddressDR = 0x01; //Address for train 1 DARK-RED
-const unsigned int DCCaddressLR = 0x03; //Address for train 3 LIGHT-RED
+
 
 //01DCSSSS for speed, D is direction (fwd=1 and rev=0), C is speed(SSSSC) LSB
 const unsigned int DCCinst_forward = 0x68; //forward half speed
@@ -293,13 +435,20 @@
 const unsigned int SWBflip_4 = 0x88; //Flip SW4
 
 
+//.....DCC TRAIN COMMAND VARS
+
+//typical out of box default engine DCC address is 3 (at least for Bachmann trains)
+//Note: A DCC controller can reprogram the address whenever needed
+const unsigned int DCCaddressDR = 0x01; //Address for train 1 DARK-RED
+const unsigned int DCCaddressLR = 0x03; //Address for train 3 LIGHT-RED
+
 /**
 *Creation of 2 Train objects. 
 *Using boolean constructor because position initialization will be done after initializing all position vectors.
 *DR_train = Dark Red train - LR_train = Light Red Train
 **/
-Train DR_train(true); //Position and going_cw
-Train LR_train(true);
+Train DR_train(DCCaddressDR,MEDIUM);
+Train LR_train(DCCaddressLR,MEDIUM);
 
 //possibility of an array having {dr_train, lr_train}? for reuse and modularity of functions
 
@@ -464,42 +613,22 @@
 }
 
 
-/**
-*
-*Checks if the element exists within the vector.
-*
-*@v - The vector (of ints) the method will go through.
-*@element - The element the method will look for.
-*
-**/
-bool in_vector(vector<int>v,int element){
-    
-    bool exist = false;
-    
-    for(int i=0; i< v.size(); i++){
-        
-        if(v[i] == element){
-            
-            exist = true;
-        }
-    }   
-    return exist;
-}
+
 
 
 /**
-*This method will checks if there is a non-avoidable frontal collision(NAFC).
+*This method will check if there is a non-avoidable frontal collision(NAFC).
 *A NAFC will happen if:
 *
 *Both trains in area A or B with different direction
 *Trains in (D11 and D5) or (D9 and D3) with same direction 
 *
 */
-bool check_NAC(bool DR_in_A, bool DR_in_B,bool LR_in_A,bool LR_in_B){
+bool check_NAC(){
     
     bool NAC = false;
     
-    if((DR_in_A && LR_in_A) || (DR_in_B && LR_in_B) ){ //Check if both are in same area
+    if((DR_train.is_in_A() && LR_train.is_in_A()) || (DR_train.is_in_B() && LR_train.is_in_B()) ){ //Check if both are in same area
     
         if(DR_train.goes_cw() ^ LR_train.goes_cw()){ //XOR: They must have different values to be true (Different direction)
         
@@ -598,16 +727,9 @@
 *It will go through all the area vectors (A,B) and call the function in_vector to check inside the vectors.
 *
 **/
-void check_position(){
-    
-    bool DR_in_A, DR_in_B, LR_in_A, LR_in_B;
-    
-    DR_in_A = in_vector(area_A,DR_train.get_position_number()); //Check if DR train is in area A
-    DR_in_B = in_vector(area_B,DR_train.get_position_number());
-    LR_in_A = in_vector(area_A,LR_train.get_position_number());
-    LR_in_B = in_vector(area_B,LR_train.get_position_number());
-    
-    if(check_NAC(DR_in_A,DR_in_B,LR_in_A,LR_in_B)){
+void check_position(){    
+        
+    if(check_NAC()){
         lcd.cls();
         lcd.printf("NAC!!!");
     }      
@@ -791,60 +913,7 @@
   }
 
 
-/**
-*
-*Method to send DCC commands to train and switches.
-*
-*@address - (HEX)Address where the commands will be sent
-*@inst - (HEX)Number of instruction that will be commanded
-*@repeat_count - Number of times the command will be sent
-*
-**/
-void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){
-    
-    unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type
-    unsigned __int64 temp_command = 0x0000000000000000;
-    unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start
-    unsigned int error = 0x00; //error byte
-    
-    //calculate error detection byte with xor
-    error = address ^ inst;
-    
-    //combine packet bits in basic DCC format
-    command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01;
-    //printf("\n\r %llx \n\r",command);
-    
-    int i=0;
-    //repeat DCC command lots of times
-    while(i < repeat_count) {
-        
-        temp_command = command;
-        //loops through packet bits encoding and sending out digital pulses for a DCC command
-        for (int j=0; j<64; j++) {
-            
-            if((temp_command&0x8000000000000000)==0) { 
-            //test packet bit
-                //send data for a "0" bit
-                Track=0;
-                wait_us(100);
-                Track=1;
-                wait_us(100);
-                //printf("0011");
-            }else{
-                
-                //send data for a "1"bit
-                Track=0;
-                wait_us(58);
-                Track=1;
-                wait_us(58);
-                //printf("01");
-            }
-            // next bit in packet
-            temp_command = temp_command<<1;
-        }
-        i++;
-    }
-}
+
 
 
 /**
@@ -926,29 +995,6 @@
     }
 
 
-/**
-*
-*
-*
-**/
-void send_command(){
-    
-    if(DR_run){
-        
-        DCC_send_command(DCCaddressDR,DCCinst_forward,1); // Forward half speed train addres DARK-RED 
-    }else{
-        
-        DCC_send_command(DCCaddressDR,DCCinst_stop,400);
-    }
-    
-    if(LR_run){
-        
-        DCC_send_command(DCCaddressLR,DCCinst_forward_fast,1); // Forward half speed train addres DARK-RED 
-    }else{
-        
-        DCC_send_command(DCCaddressLR,DCCinst_stop,400);
-    }
-}
 
 
 /**
@@ -960,7 +1006,7 @@
 int select_sensor(int init_sensor, string train){
     
     lcd.cls();
-    lcd.printf("%s SENSOR",train);
+    lcd.printf("%s SENSOR D%d",train,init_sensor);
     
     int sensor = init_sensor;
     bool changed = false;
@@ -998,8 +1044,17 @@
 */
 bool select_direction(bool init_going_cw,string train){
     
+    string dir_string;
+    
+    if(init_going_cw){
+        dir_string = "cw";
+    }else{
+        dir_string = "ccw";
+    }
+    
     lcd.cls();
-    lcd.printf("%s DIRECTION",train);
+    lcd.printf("%s DIRECTION %s ",train,dir_string);
+    
     bool exit = false;
     bool going_cw = init_going_cw;
     bool changed = false;
@@ -1061,8 +1116,7 @@
     
     initialize_mcp();   //mcp initialization for interrupts before train running
     init();
-    
-    
+       
     
     int DR_init_sensor = select_sensor(D9,"DR");
     bool DR_init_dir = select_direction(false,"DR");
@@ -1105,7 +1159,9 @@
     DCC_send_command(DCCaddressDR,DCC_func_dimlight,400); // dim light
     DCC_send_command(DCCaddressDR,DCC_func_lighton,200);  // light full again
     */
-
+    
+    
+    
     //LED3 Shows start of route + LCD notif
     led3 = 1; // Entering the while
     lcd.cls();
@@ -1129,7 +1185,8 @@
             lcd.cls();
             
         }else{
-            send_command();
+            DR_train.run();
+            LR_train.run();
             
         } 
     }