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

FPGAcomms.h

Committer:
IonSystems
Date:
2014-12-05
Revision:
28:bdf2bf56f97b
Parent:
26:23ee3ea4ac7c

File content as of revision 28:bdf2bf56f97b:

#include "mbed.h"
#include "colourProcessing.h"
////////////////////////////
//  START OF I/O DEFINITIONS
////////////////////////////
//Setup pins to FPGA
DigitalOut startSort(p5);       //A positive edge tells the FPGA to start sorting.
DigitalIn sortComplete(p16);    //FPGA sets to 1 once complete until another signal is recieved.
/*
  The command codes for the three sort select bits(ColourBit1,ColourBit2,ColourBit3)
  See datasheet for furter information.
    000     Sort red chip
    001     Sort green chip
    010     Sort blue chip
    011     Bin the chip
    100     Recycle the chip
    101     Nothing
    110     Nothing
    111     Nothing
*/

DigitalOut colourBit1(p6);      //The 3 bits below are select bits for the sorter.
DigitalOut colourBit2(p7);
DigitalOut colourBit3(p8);
DigitalOut startDispense(p18);   //A positive edge tells the FPGA to start dispensing.
/*
    00      Dispense red chip
    01      Dispense green chip
    10      Dispense blue chip
    11      Nothing
*/

DigitalOut dispenseBit1(p19);  //The 2 bits below are select bits for the dispenser.
DigitalOut dispenseBit2(p20); 

DigitalIn dispenseComplete(p11);    //FPGA sets to 1 once complete until another signal is recieved.
DigitalOut select(p15); //0 for control, 1 for maintenance.

////////////////////////////
//  END OF I/O DEFINITIONS
////////////////////////////

/*  Set the select lines for when the FPGA is in maintenance mode.
 *  The same pins have different functions in operation mode and maintenance mode on the FPGA.
*/
void setMaintenanceSelect(bool bit6, bool bit5, bool bit4, bool bit3, bool bit2, bool bit1)
{
    startSort = bit1;
    colourBit1 = bit2;
    colourBit2 = bit3;
    colourBit3 = bit4;
    startDispense = bit5;
    dispenseBit1 = bit6;
}

//Set the maintenance start bit.
void setMaintenanceStart(bool value)
{
    dispenseBit2 = value;
}

//Wait for the FPGA to complete a maintenance operation and return a complete signal.
void waitForMaintenanceComplete()
{
    while(!sortComplete) {
       
    }
   
}

//Set the select lines for a dispense operation for when the FPGA is in operation mode.
void setDispenseSelect(bool dBit1, bool dBit2)
{
    dispenseBit1 = dBit1;
    dispenseBit2 = dBit2;
}

//Set the select lines for a sorting operation for when the FPGA is in operation mode.
void setSortSelect(bool sBit1, bool sBit2, bool sBit3)
{
    colourBit1 = sBit1;
    colourBit2 = sBit2;
    colourBit3 = sBit3;
}

/*  maintain(StateMachine statemachine)
 *  Carries out a maintenance operation depending on the value of the StateMachine input parameter.
 */
void maintain(StateMachine maintainState)
{
    select = 1; //setting FPGA to maintenance mode.
    
    /*  Reset select pins to ensure FPGA carries out one operation.
     *  The FPGA triggers whenever the select lines change.
     *  Setting all bits high ensure a 'do nothing' state on the FPGA,
     *  so it won't do anything.
     */ 
    setMaintenanceSelect(true,true,true,true,true,true);
    switch(maintainState) { //Set the maintenanc select values depending on value of maintainState. 
        case RB_LEFT:
            setMaintenanceSelect(false,false,false,true,false,true);
            break;
        case RB_CENTRE:
            setMaintenanceSelect(false,false,false,true,true,false);
            break;
        case RB_RIGHT:
            setMaintenanceSelect(false,false,false,true,true,true);
            break;
        case GO_UP:
            setMaintenanceSelect(false,false,true,false,false,false);
            break;
        case GO_CENTRE:
            setMaintenanceSelect(false,false,true,false,false,true);
            break;
        case GO_DOWN:
            setMaintenanceSelect(false,false,true,false,true,false);
            break;
        case BR_LEFT:
            setMaintenanceSelect(false,false,true,false,true,true);
            break;
        case BR_RIGHT:
            setMaintenanceSelect(false,false,true,true,false,false);
            break;
        case R_PUSH:
            setMaintenanceSelect(false,false,true,true,false,true);
            break;
        case R_HOME:
            setMaintenanceSelect(false,false,true,true,true,false);
            break;
        case GB_LEFT:
            setMaintenanceSelect(false,false,true,true,true,true);
            break;
        case GB_CENTRE:
            setMaintenanceSelect(false,true,false,false,false,false);
            break;
        case GB_RIGHT:
            setMaintenanceSelect(false,true,false,false,false,true);
            break;
        case maintenanceEND:
            setMaintenanceSelect(false,true,false,false,true,false);
            break;
        default:
            break;
    }
    setMaintenanceStart(true);      //Tell the FPGA to start the maintenance operation
    waitForMaintenanceComplete();   //Wait for the FPGA to complete the maintenance operation.
    setMaintenanceStart(false);     //Set the start bit low.
    setMaintenanceSelect(true,false,true,true,true,false); //Set select bits back to 'do nothing' state.
}

//Wait for the FPGA to complete a dispense operation and send a complete signal.
void waitForDispenseComplete()
{
    while(!dispenseComplete) {
    }  
}

/*  dispense(Colour colour)
 *  Carries out a dispense operation for the colour defined by 'colour' which is a Colour.
 */
void dispense(Colour colour)
{
    startDispense = false;      //Set start dispense to false, it should be false already.
    bool validDispense = false; //Set up a boolean to record whether the dispense is valid or not.
    select = 0;                    //Set the FPGA to operation mode.
    setDispenseSelect(true,true);   //Set the dispense selcect bits to 'no nothing' state.
    // A dispense operation can only take place if there are chips
   
    switch(colour) {    //Carry out a dispense operation for the colour defined by 'colour'.
        case RED:
            
            if(redAmount > 0 || operationMode == false) {           //Ensure dispense is valid
                setDispenseSelect(false,false);                     //Set select lines for RED dispense
                if(operationMode)redAmount--;                       //Decrement tube amount if in operation mode
                validDispense = true;                               
            }
            break;
        case GREEN:
            if(greenAmount > 0 || operationMode == false) {         //Ensure dispense is valid
                setDispenseSelect(true,false);                      //Set select lines for GREEN dispense
                if(operationMode)greenAmount--;                     //Decrement tube amount if in operation mode
                validDispense = true;
            }
            break;
        case BLUE:
            if(blueAmount > 0 || operationMode == false) {          //Ensure dispense is valid
                setDispenseSelect(false,true);                      //Set select lines for BLUE dispense
                if(operationMode)blueAmount--;                      //Decrement tube amount if in operation mode
                validDispense = true;
            }
            break;
    }
    
    if(operationMode)writeFile(redAmount,greenAmount,blueAmount,recycleAmount); //Store new tube values if in operation mode.
    /*  If this is a valid dispense (enough chips in storage tubes) then
     *  set the start bit, wait for complete signal, then reset start bit,
     *  and select lines.
     */
    if(validDispense || operationMode == false) {   
        startDispense = true; //set the startDispense line high.
        waitForDispenseComplete();       
        startDispense = false;
        setDispenseSelect(true,true);
    }
}

/*  dispenseOrder(int r, int g, int b)
 *  Dispenses a certain amount of each coloured chip,
 *  depending on the three input values (one input for each colour).
 */ 
void dispenseOrder(int r, int g, int b)
{
    for(int i = r; i > 0; i--) {        
        dispense(RED);
        wait(0.2);
        Thread::wait(200);
    }
    for(int i = g; i > 0; i--) {
        dispense(GREEN);
    }
    for(int i = b; i > 0; i--) {
        dispense(BLUE);
    }
}
//Wait for the FPGA to complete a sort operation and send a complete signal.
void waitForSortComplete()
{
    while(!sortComplete) {}
}
/*  lift()
 *  Communicate with the FPGA to carry out a lift operation.
 */
void lift()
{
    select = 0; //Setting to operation mode just in case it has not been set.
    setSortSelect(true,true,true);  //Setting sort select to 'no nothing' state.
    setSortSelect(true,false,true); //Setting sort select to 'lift' state.
    startSort = true;               //Tell the FPGA to start the lift operation
    waitForSortComplete();          //Wait for the FPGA to complete the lift operation
    startSort = false;              //Turn off startSort
    setSortSelect(true,true,true);  //Return sort select to 'no nothing' state.  
}


/*  recycle()
 *  Communicate with the FPGA to carry out a recycle operation.
 */
void recycle()
{
    if(redAmount >= tubeSize && greenAmount >= tubeSize && blueAmount >= tubeSize && operationMode){
        return;
        }
    select = 0; //Setting to operation mode just in case it has not been set.
    setSortSelect(true,true,true);      //Setting sort select to 'no nothing' state.
    setSortSelect(false,false,true);    //Setting sort select to 'recycle' state.
    if(operationMode)recycleAmount++;   //Increment the amount of chips in the lift, if we are in operation mode.
    startSort = true;                   //Tell the FPGA to start the recycle operation.
    waitForSortComplete();              //Wait for the FPGA to complete the recycle operation
    startSort = false;                  //Turn off startSort.
    setSortSelect(true,true,true);      //Return sort select to 'no nothing' state.  
    if(recycleAmount >= 5) {            //Check whether the lift is full.
        Thread::wait(1000);             //Carry out a lift operation if the recycle tube is full.
        lift();
        Thread::wait(1000);
        recycleAmount = 0;
    }
}


/*  sort(Colour colour)
 *  Sort a token into a storage tube. The storage tube is selected using the Colour input 'colour'.
 */
void sort(Colour colour)
{
    if(colour == NONE) {    //Return if no colour is given.
        return;
    } else {                
        startSort = false;                              //just in case it is high for some reason.
        select = 0;                                     //Setting to operation mode just in case it has not been set.
        setSortSelect(true,true,true);                  //Set sort select to 'no nothing' state.
        switch(colour) {
            case RED:                
                if(redAmount >= tubeSize && operationMode) {    //Recycle if red tube full
                    recycle();
                    return;
                }
                setSortSelect(false,false,false);               //Set sort select for red sort
                if(operationMode) redAmount++;
                break;
            case GREEN:
                if(greenAmount >= tubeSize && operationMode) {  //Recycle if green tube full
                    recycle();
                    return;
                }
                setSortSelect(true,false,false);               //Set sort select for green sort
                if(operationMode) greenAmount++;
                break;
            case BLUE:
                if(blueAmount >= tubeSize && operationMode) {   //Recycle if blue tube full
                    recycle();
                    return;
                }
                setSortSelect(false,true,false);               //Set sort select for blue sort
                if(operationMode) blueAmount++;
                break;
            case BIN:
                setSortSelect(true,true,false);                //Set sort select for bin
                break;
        }
        startSort = true;                                      //Tell the FPGA to start the sort
        waitForSortComplete();                                 //Wait for the FPGA to complete sort operation and send complete signal
        startSort = false;                      
        setSortSelect(true,true,true);                         //Return sort select to 'do nothing' state.
        //Save tube values to file if in operation mode.
        if(operationMode) writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
    }
}


/*  dispenseAll()
 *  Dispense all the tokens in the three tubes, according to the stored values.
 */
void dispenseAll()
{
    dispenseOrder(redAmount,greenAmount,blueAmount);
    redAmount = 0; greenAmount = 0; blueAmount = 0;
    writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
}