The MBED firmware used on the Chipin sorter, developed over 12 weeks for a 3rd year university systems project. Chipin is a token sorter, it sorts tokens by colours and dispenses them to order through an online booking system and card reader. This program interfaces with an FPGA, PC and LCD screen to control the sorter. The sorter has an operation mode where it can process orders when a card is entered into the machine. There is also a maintenance mode where the device responds to maintenance instructions such as 'dispense all'. More information at http://www.ionsystems.uk/

Dependencies:   MCP23017 TCS3472_I2C WattBob_TextLCD mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FPGAcomms.h Source File

FPGAcomms.h

00001 #include "mbed.h"
00002 #include "colourProcessing.h"
00003 ////////////////////////////
00004 //  START OF I/O DEFINITIONS
00005 ////////////////////////////
00006 //Setup pins to FPGA
00007 DigitalOut startSort(p5);       //A positive edge tells the FPGA to start sorting.
00008 DigitalIn sortComplete(p16);    //FPGA sets to 1 once complete until another signal is recieved.
00009 /*
00010   The command codes for the three sort select bits(ColourBit1,ColourBit2,ColourBit3)
00011   See datasheet for furter information.
00012     000     Sort red chip
00013     001     Sort green chip
00014     010     Sort blue chip
00015     011     Bin the chip
00016     100     Recycle the chip
00017     101     Nothing
00018     110     Nothing
00019     111     Nothing
00020 */
00021 
00022 DigitalOut colourBit1(p6);      //The 3 bits below are select bits for the sorter.
00023 DigitalOut colourBit2(p7);
00024 DigitalOut colourBit3(p8);
00025 DigitalOut startDispense(p18);   //A positive edge tells the FPGA to start dispensing.
00026 /*
00027     00      Dispense red chip
00028     01      Dispense green chip
00029     10      Dispense blue chip
00030     11      Nothing
00031 */
00032 
00033 DigitalOut dispenseBit1(p19);  //The 2 bits below are select bits for the dispenser.
00034 DigitalOut dispenseBit2(p20); 
00035 
00036 DigitalIn dispenseComplete(p11);    //FPGA sets to 1 once complete until another signal is recieved.
00037 DigitalOut select(p15); //0 for control, 1 for maintenance.
00038 
00039 ////////////////////////////
00040 //  END OF I/O DEFINITIONS
00041 ////////////////////////////
00042 
00043 /*  Set the select lines for when the FPGA is in maintenance mode.
00044  *  The same pins have different functions in operation mode and maintenance mode on the FPGA.
00045 */
00046 void setMaintenanceSelect(bool bit6, bool bit5, bool bit4, bool bit3, bool bit2, bool bit1)
00047 {
00048     startSort = bit1;
00049     colourBit1 = bit2;
00050     colourBit2 = bit3;
00051     colourBit3 = bit4;
00052     startDispense = bit5;
00053     dispenseBit1 = bit6;
00054 }
00055 
00056 //Set the maintenance start bit.
00057 void setMaintenanceStart(bool value)
00058 {
00059     dispenseBit2 = value;
00060 }
00061 
00062 //Wait for the FPGA to complete a maintenance operation and return a complete signal.
00063 void waitForMaintenanceComplete()
00064 {
00065     while(!sortComplete) {
00066        
00067     }
00068    
00069 }
00070 
00071 //Set the select lines for a dispense operation for when the FPGA is in operation mode.
00072 void setDispenseSelect(bool dBit1, bool dBit2)
00073 {
00074     dispenseBit1 = dBit1;
00075     dispenseBit2 = dBit2;
00076 }
00077 
00078 //Set the select lines for a sorting operation for when the FPGA is in operation mode.
00079 void setSortSelect(bool sBit1, bool sBit2, bool sBit3)
00080 {
00081     colourBit1 = sBit1;
00082     colourBit2 = sBit2;
00083     colourBit3 = sBit3;
00084 }
00085 
00086 /*  maintain(StateMachine statemachine)
00087  *  Carries out a maintenance operation depending on the value of the StateMachine input parameter.
00088  */
00089 void maintain(StateMachine maintainState)
00090 {
00091     select = 1; //setting FPGA to maintenance mode.
00092     
00093     /*  Reset select pins to ensure FPGA carries out one operation.
00094      *  The FPGA triggers whenever the select lines change.
00095      *  Setting all bits high ensure a 'do nothing' state on the FPGA,
00096      *  so it won't do anything.
00097      */ 
00098     setMaintenanceSelect(true,true,true,true,true,true);
00099     switch(maintainState) { //Set the maintenanc select values depending on value of maintainState. 
00100         case RB_LEFT:
00101             setMaintenanceSelect(false,false,false,true,false,true);
00102             break;
00103         case RB_CENTRE:
00104             setMaintenanceSelect(false,false,false,true,true,false);
00105             break;
00106         case RB_RIGHT:
00107             setMaintenanceSelect(false,false,false,true,true,true);
00108             break;
00109         case GO_UP:
00110             setMaintenanceSelect(false,false,true,false,false,false);
00111             break;
00112         case GO_CENTRE:
00113             setMaintenanceSelect(false,false,true,false,false,true);
00114             break;
00115         case GO_DOWN:
00116             setMaintenanceSelect(false,false,true,false,true,false);
00117             break;
00118         case BR_LEFT:
00119             setMaintenanceSelect(false,false,true,false,true,true);
00120             break;
00121         case BR_RIGHT:
00122             setMaintenanceSelect(false,false,true,true,false,false);
00123             break;
00124         case R_PUSH:
00125             setMaintenanceSelect(false,false,true,true,false,true);
00126             break;
00127         case R_HOME:
00128             setMaintenanceSelect(false,false,true,true,true,false);
00129             break;
00130         case GB_LEFT:
00131             setMaintenanceSelect(false,false,true,true,true,true);
00132             break;
00133         case GB_CENTRE:
00134             setMaintenanceSelect(false,true,false,false,false,false);
00135             break;
00136         case GB_RIGHT:
00137             setMaintenanceSelect(false,true,false,false,false,true);
00138             break;
00139         case maintenanceEND:
00140             setMaintenanceSelect(false,true,false,false,true,false);
00141             break;
00142         default:
00143             break;
00144     }
00145     setMaintenanceStart(true);      //Tell the FPGA to start the maintenance operation
00146     waitForMaintenanceComplete();   //Wait for the FPGA to complete the maintenance operation.
00147     setMaintenanceStart(false);     //Set the start bit low.
00148     setMaintenanceSelect(true,false,true,true,true,false); //Set select bits back to 'do nothing' state.
00149 }
00150 
00151 //Wait for the FPGA to complete a dispense operation and send a complete signal.
00152 void waitForDispenseComplete()
00153 {
00154     while(!dispenseComplete) {
00155     }  
00156 }
00157 
00158 /*  dispense(Colour colour)
00159  *  Carries out a dispense operation for the colour defined by 'colour' which is a Colour.
00160  */
00161 void dispense(Colour colour)
00162 {
00163     startDispense = false;      //Set start dispense to false, it should be false already.
00164     bool validDispense = false; //Set up a boolean to record whether the dispense is valid or not.
00165     select = 0;                    //Set the FPGA to operation mode.
00166     setDispenseSelect(true,true);   //Set the dispense selcect bits to 'no nothing' state.
00167     // A dispense operation can only take place if there are chips
00168    
00169     switch(colour) {    //Carry out a dispense operation for the colour defined by 'colour'.
00170         case RED:
00171             
00172             if(redAmount > 0 || operationMode == false) {           //Ensure dispense is valid
00173                 setDispenseSelect(false,false);                     //Set select lines for RED dispense
00174                 if(operationMode)redAmount--;                       //Decrement tube amount if in operation mode
00175                 validDispense = true;                               
00176             }
00177             break;
00178         case GREEN:
00179             if(greenAmount > 0 || operationMode == false) {         //Ensure dispense is valid
00180                 setDispenseSelect(true,false);                      //Set select lines for GREEN dispense
00181                 if(operationMode)greenAmount--;                     //Decrement tube amount if in operation mode
00182                 validDispense = true;
00183             }
00184             break;
00185         case BLUE:
00186             if(blueAmount > 0 || operationMode == false) {          //Ensure dispense is valid
00187                 setDispenseSelect(false,true);                      //Set select lines for BLUE dispense
00188                 if(operationMode)blueAmount--;                      //Decrement tube amount if in operation mode
00189                 validDispense = true;
00190             }
00191             break;
00192     }
00193     
00194     if(operationMode)writeFile(redAmount,greenAmount,blueAmount,recycleAmount); //Store new tube values if in operation mode.
00195     /*  If this is a valid dispense (enough chips in storage tubes) then
00196      *  set the start bit, wait for complete signal, then reset start bit,
00197      *  and select lines.
00198      */
00199     if(validDispense || operationMode == false) {   
00200         startDispense = true; //set the startDispense line high.
00201         waitForDispenseComplete();       
00202         startDispense = false;
00203         setDispenseSelect(true,true);
00204     }
00205 }
00206 
00207 /*  dispenseOrder(int r, int g, int b)
00208  *  Dispenses a certain amount of each coloured chip,
00209  *  depending on the three input values (one input for each colour).
00210  */ 
00211 void dispenseOrder(int r, int g, int b)
00212 {
00213     for(int i = r; i > 0; i--) {        
00214         dispense(RED);
00215         wait(0.2);
00216         Thread::wait(200);
00217     }
00218     for(int i = g; i > 0; i--) {
00219         dispense(GREEN);
00220     }
00221     for(int i = b; i > 0; i--) {
00222         dispense(BLUE);
00223     }
00224 }
00225 //Wait for the FPGA to complete a sort operation and send a complete signal.
00226 void waitForSortComplete()
00227 {
00228     while(!sortComplete) {}
00229 }
00230 /*  lift()
00231  *  Communicate with the FPGA to carry out a lift operation.
00232  */
00233 void lift()
00234 {
00235     select = 0; //Setting to operation mode just in case it has not been set.
00236     setSortSelect(true,true,true);  //Setting sort select to 'no nothing' state.
00237     setSortSelect(true,false,true); //Setting sort select to 'lift' state.
00238     startSort = true;               //Tell the FPGA to start the lift operation
00239     waitForSortComplete();          //Wait for the FPGA to complete the lift operation
00240     startSort = false;              //Turn off startSort
00241     setSortSelect(true,true,true);  //Return sort select to 'no nothing' state.  
00242 }
00243 
00244 
00245 /*  recycle()
00246  *  Communicate with the FPGA to carry out a recycle operation.
00247  */
00248 void recycle()
00249 {
00250     if(redAmount >= tubeSize && greenAmount >= tubeSize && blueAmount >= tubeSize && operationMode){
00251         return;
00252         }
00253     select = 0; //Setting to operation mode just in case it has not been set.
00254     setSortSelect(true,true,true);      //Setting sort select to 'no nothing' state.
00255     setSortSelect(false,false,true);    //Setting sort select to 'recycle' state.
00256     if(operationMode)recycleAmount++;   //Increment the amount of chips in the lift, if we are in operation mode.
00257     startSort = true;                   //Tell the FPGA to start the recycle operation.
00258     waitForSortComplete();              //Wait for the FPGA to complete the recycle operation
00259     startSort = false;                  //Turn off startSort.
00260     setSortSelect(true,true,true);      //Return sort select to 'no nothing' state.  
00261     if(recycleAmount >= 5) {            //Check whether the lift is full.
00262         Thread::wait(1000);             //Carry out a lift operation if the recycle tube is full.
00263         lift();
00264         Thread::wait(1000);
00265         recycleAmount = 0;
00266     }
00267 }
00268 
00269 
00270 /*  sort(Colour colour)
00271  *  Sort a token into a storage tube. The storage tube is selected using the Colour input 'colour'.
00272  */
00273 void sort(Colour colour)
00274 {
00275     if(colour == NONE) {    //Return if no colour is given.
00276         return;
00277     } else {                
00278         startSort = false;                              //just in case it is high for some reason.
00279         select = 0;                                     //Setting to operation mode just in case it has not been set.
00280         setSortSelect(true,true,true);                  //Set sort select to 'no nothing' state.
00281         switch(colour) {
00282             case RED:                
00283                 if(redAmount >= tubeSize && operationMode) {    //Recycle if red tube full
00284                     recycle();
00285                     return;
00286                 }
00287                 setSortSelect(false,false,false);               //Set sort select for red sort
00288                 if(operationMode) redAmount++;
00289                 break;
00290             case GREEN:
00291                 if(greenAmount >= tubeSize && operationMode) {  //Recycle if green tube full
00292                     recycle();
00293                     return;
00294                 }
00295                 setSortSelect(true,false,false);               //Set sort select for green sort
00296                 if(operationMode) greenAmount++;
00297                 break;
00298             case BLUE:
00299                 if(blueAmount >= tubeSize && operationMode) {   //Recycle if blue tube full
00300                     recycle();
00301                     return;
00302                 }
00303                 setSortSelect(false,true,false);               //Set sort select for blue sort
00304                 if(operationMode) blueAmount++;
00305                 break;
00306             case BIN:
00307                 setSortSelect(true,true,false);                //Set sort select for bin
00308                 break;
00309         }
00310         startSort = true;                                      //Tell the FPGA to start the sort
00311         waitForSortComplete();                                 //Wait for the FPGA to complete sort operation and send complete signal
00312         startSort = false;                      
00313         setSortSelect(true,true,true);                         //Return sort select to 'do nothing' state.
00314         //Save tube values to file if in operation mode.
00315         if(operationMode) writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
00316     }
00317 }
00318 
00319 
00320 /*  dispenseAll()
00321  *  Dispense all the tokens in the three tubes, according to the stored values.
00322  */
00323 void dispenseAll()
00324 {
00325     dispenseOrder(redAmount,greenAmount,blueAmount);
00326     redAmount = 0; greenAmount = 0; blueAmount = 0;
00327     writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
00328 }