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-03
Revision:
24:8868101d01d0
Parent:
23:f9e7e64784be
Child:
25:7f5d764d8e34

File content as of revision 24:8868101d01d0:

#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);
    }
}

/*  
 *  
 */ 
void dispenseOrder(int r, int g, int b)
{
//TODO: Check if there are enough chips of each colour to dispense the order.
    //operationMode = false;
    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);
    }
    //operationMode = true;
}

void waitForSortComplete()
{
    while(!sortComplete) {}
}

void lift()
{
    select = 0; //Setting to operation mode just in case it has not been set.
    setSortSelect(true,true,true);
    setSortSelect(true,false,true);
    startSort = true; //set the startDispense line high.
    waitForSortComplete();
    startSort = false;
    setSortSelect(true,true,true);    
}



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);
    setSortSelect(false,false,true);
    if(operationMode)recycleAmount++;
    startSort = true; //set the startDispense line high.
    waitForSortComplete();
    startSort = false;
    setSortSelect(true,true,true);
    if(recycleAmount >= 5) {
        Thread::wait(1000);
        lift();
        Thread::wait(1000);
        recycleAmount = 0;
    }
}



void sort(Colour colour)
{
    if(colour == NONE) {
        return;
    } else {
        startSort = false;
        select = 0; //Setting to operation mode just in case it has not been set.
        setSortSelect(true,true,true);
        switch(colour) {
            case RED:                
                if(redAmount >= tubeSize && operationMode) {
                    recycle();
                    return;
                }
                setSortSelect(false,false,false);
                if(operationMode) redAmount++;
                break;
            case GREEN:
                if(greenAmount >= tubeSize && operationMode) {
                    recycle();
                    return;
                }
                setSortSelect(true,false,false);
                if(operationMode) greenAmount++;
                break;
            case BLUE:
                if(blueAmount >= tubeSize && operationMode) {
                    recycle();
                    return;
                }
                setSortSelect(false,true,false);
                if(operationMode) blueAmount++;
                break;
            case BIN:
                setSortSelect(true,true,false);
                break;
        }
        startSort = true;
        waitForSortComplete();
        startSort = false;
        setSortSelect(true,true,true);
        if(operationMode) writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
       
    }
}



void dispenseAll()
{
    dispenseOrder(redAmount,greenAmount,blueAmount);
    redAmount = 0; greenAmount = 0; blueAmount = 0;
    writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
}