Got quadrature decoders and mode switch working

Dependencies:   mbed

main.cpp

Committer:
wac
Date:
2010-10-25
Revision:
1:fb60f76e33ee
Parent:
0:7ae28d2c1e3e

File content as of revision 1:fb60f76e33ee:

// 9430 User Interface Mockup
// 
// Read quadrature encoder and drive LEDs
// Version 0.1
// Created by Wayne Chin
// October 22, 2010
// Version 0.2
// Added amps/gas mode selections; confirmed quad decoder operation.
// October 25, 2010

#include "mbed.h"

#define TRUE 1
#define FALSE 0
#define ON 0 // LED drives are inverted
#define OFF 1 // LED drives are inverted
#define MAXAMPS200 200 // Max amps display
#define MINAMPSET 25 // Min amps display
#define MAXGASPRESS 99 // Max gas display
#define STARTGASPRESS 75
#define MINGASPRESS 0
#define AMPSMODE 0
#define GASMODE 1
#define BUTTONTIMEOUT 1000 // Mode change timeout in milliseconds

// Global variables
int quadnew, quadold; // Quadrature decoding
int quadcount; // Integer counter for quadrature encoder output
int gascount, ampscount; // Separately keep track of gas and amps
int select, gasselect; // Keep track of mode/gas selection LEDs
int quadswitchnew, quadswitchold; // Debounce pushbutton states
int mode; // Keep track of AMPS or GAS pressure display modes
int modechanged; // Keep track of entry into mode change

Serial pc(USBTX, USBRX); // tx, rx

// mbed LEDs
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

// Quadrature encoder inputs
DigitalIn quada(p21);
DigitalIn quadb(p22);
DigitalIn quadsw(p30);

// 7-segment display LEDs
DigitalOut LED1a(p23); // Hundreds digit
DigitalOut LED1b(p24);
DigitalOut LED1c(p25);
DigitalOut LED1d(p26);
DigitalOut LED1e(p27);
DigitalOut LED1f(p28);
DigitalOut LED1g(p29);
DigitalOut LED2a(p13); // Tens digit
DigitalOut LED2b(p14);
DigitalOut LED2c(p15);
DigitalOut LED2d(p16);
DigitalOut LED2e(p17);
DigitalOut LED2f(p18);
DigitalOut LED2g(p19);
DigitalOut LED3a(p5); // Ones digit
DigitalOut LED3b(p6);
DigitalOut LED3c(p7);
DigitalOut LED3d(p8);
DigitalOut LED3e(p9);
DigitalOut LED3f(p10);
DigitalOut LED3g(p11);

// Gas selection LEDs
//DigitalOut LEDg1(p20); // Not wired up
DigitalOut LEDg2(p20);
DigitalOut LEDg3(p12);
//DigitalOut LEDg4(p20); // Not wired up

// Interrupt
Ticker getswitches; // Periodic function call used to sample switches
Timer modetimer; // Used for press-and-hold function

// Take integer input and drive 3 digit 7-segment display and toggle among gas select LEDs
void LEDout(int number)
{
    int hundreds, tens, ones;
    if (mode == AMPSMODE && number > 999) // Throw out numbers greater than 999
        return;
    else if (mode == GASMODE && number > 99) // Throw out numbers greater than 99
        return;
    else if (number < 0) // Throw out numbers less than 0
        return;
    else // Display number
    {
        // Extract hundreds digit
        hundreds = number - (number / 100);
        // Extract tens digit
        tens = number - hundreds;
        tens = tens - (tens / 10);
        // Extract ones digit
        ones = number - hundreds - tens;

        if (mode == AMPSMODE)
        {
            switch (hundreds)
            {
                case 0: {
                    LED1a = ON; LED1b = ON; LED1c = ON; LED1d = ON; LED1e = ON; LED1f = ON; LED1g = OFF; }
                    break;
                case 1: {
                    LED1a = OFF; LED1b = ON; LED1c = ON; LED1d = OFF; LED1e = OFF; LED1f = OFF; LED1g = OFF; }
                    break;
                case 2: {
                    LED1a = ON; LED1b = ON; LED1c = OFF; LED1d = ON; LED1e = ON; LED1f = OFF; LED1g = ON; }
                    break;
                case 3: {
                    LED1a = ON; LED1b = ON; LED1c = ON; LED1d = ON; LED1e = OFF; LED1f = OFF; LED1g = ON; }
                    break;
                case 4: {
                    LED1a = OFF; LED1b = ON; LED1c = ON; LED1d = OFF; LED1e = OFF; LED1f = ON; LED1g = ON; }
                    break;
                case 5: {
                    LED1a = ON; LED1b = OFF; LED1c = ON; LED1d = ON; LED1e = OFF; LED1f = ON; LED1g = ON; }
                    break;
                case 6: {
                    LED1a = ON; LED1b = OFF; LED1c = ON; LED1d = ON; LED1e = ON; LED1f = ON; LED1g = ON; }
                    break;
                case 7: {
                    LED1a = ON; LED1b = ON; LED1c = ON; LED1d = OFF; LED1e = OFF; LED1f = OFF; LED1g = OFF; }
                    break;
                case 8: {
                    LED1a = ON; LED1b = ON; LED1c = ON; LED1d = ON; LED1e = ON; LED1f = ON; LED1g = ON; }
                    break;
                case 9: {
                    LED1a = ON; LED1b = ON; LED1c = ON; LED1d = ON; LED1e = OFF; LED1f = ON; LED1g = ON; }
                    break;
                default:
                    break; // Do nothing
            } // switch (hundreds)
        }
        else // (mode == GASMODE)
        {
            // Turn off hundreds digit in gas mode
            LED1a = OFF; LED1b = OFF; LED1c = OFF; LED1d = OFF; LED1e = OFF; LED1f = OFF; LED1g = OFF;
        }
        
        switch (tens)
        {
            case 0: {
                LED2a = ON; LED2b = ON; LED2c = ON; LED2d = ON; LED2e = ON; LED2f = ON; LED2g = OFF; }
                break;
            case 1: {
                LED2a = OFF; LED2b = ON; LED2c = ON; LED2d = OFF; LED2e = OFF; LED2f = OFF; LED2g = OFF; }
                break;
            case 2: {
                LED2a = ON; LED2b = ON; LED2c = OFF; LED2d = ON; LED2e = ON; LED2f = OFF; LED2g = ON; }
                break;
            case 3: {
                LED2a = ON; LED2b = ON; LED2c = ON; LED2d = ON; LED2e = OFF; LED2f = OFF; LED2g = ON; }
                break;
            case 4: {
                LED2a = OFF; LED2b = ON; LED2c = ON; LED2d = OFF; LED2e = OFF; LED2f = ON; LED2g = ON; }
                break;
            case 5: {
                LED2a = ON; LED2b = OFF; LED2c = ON; LED2d = ON; LED2e = OFF; LED2f = ON; LED2g = ON; }
                break;
            case 6: {
                LED2a = ON; LED2b = OFF; LED2c = ON; LED2d = ON; LED2e = ON; LED2f = ON; LED2g = ON; }
                break;
            case 7: {
                LED2a = ON; LED2b = ON; LED2c = ON; LED2d = OFF; LED2e = OFF; LED2f = OFF; LED2g = OFF; }
                break;
            case 8: {
                LED2a = ON; LED2b = ON; LED2c = ON; LED2d = ON; LED2e = ON; LED2f = ON; LED2g = ON; }
                break;
            case 9: {
                LED2a = ON; LED2b = ON; LED2c = ON; LED2d = ON; LED2e = OFF; LED2f = ON; LED2g = ON; }
                break;
            default:
                break; // Do nothing
        } // switch (tens)
        
        switch (ones)
        {
            case 0: {
                LED3a = ON; LED3b = ON; LED3c = ON; LED3d = ON; LED3e = ON; LED3f = ON; LED3g = OFF; }
                break;
            case 1: {
                LED3a = OFF; LED3b = ON; LED3c = ON; LED3d = OFF; LED3e = OFF; LED3f = OFF; LED3g = OFF; }
                break;
            case 2: {
                LED3a = ON; LED3b = ON; LED3c = OFF; LED3d = ON; LED3e = ON; LED3f = OFF; LED3g = ON; }
                break;
            case 3: {
                LED3a = ON; LED3b = ON; LED3c = ON; LED3d = ON; LED3e = OFF; LED3f = OFF; LED3g = ON; }
                break;
            case 4: {
                LED3a = OFF; LED3b = ON; LED3c = ON; LED3d = OFF; LED3e = OFF; LED3f = ON; LED3g = ON; }
                break;
            case 5: {
                LED3a = ON; LED3b = OFF; LED3c = ON; LED3d = ON; LED3e = OFF; LED3f = ON; LED3g = ON; }
                break;
            case 6: {
                LED3a = ON; LED3b = OFF; LED3c = ON; LED3d = ON; LED3e = ON; LED3f = ON; LED3g = ON; }
                break;
            case 7: {
                LED3a = ON; LED3b = ON; LED3c = ON; LED3d = OFF; LED3e = OFF; LED3f = OFF; LED3g = OFF; }
                break;
            case 8: {
                LED3a = ON; LED3b = ON; LED3c = ON; LED3d = ON; LED3e = ON; LED3f = ON; LED3g = ON; }
                break;
            case 9: {
                LED3a = ON; LED3b = ON; LED3c = ON; LED3d = ON; LED3e = OFF; LED3f = ON; LED3g = ON; }
                break;
            default:
                break; // Do nothing
        } // switch (ones)
    } // if Display number
} // LEDout()

// Read quadrature encoder switch inputs from I/O port.
// Return 2-bit value with (quada,quadb).
int getquad()
{
    if (quada == 0 && quadb == 0) // (0,0)
        return(0);
    else if (quada == 1 && quadb == 0) // Clockwise from (0,0)
        return(2);
    else if (quada == 1 && quadb == 1) // Clockwise from (1,0)
        return(3);
    else // Clockwise from (1,1)
        return(1);
} // getquad()

// Read quadrature encoder, update counter variable, and update LEDs
// Quadrature clockwise states: 00 -> 10 -> 11 -> 01
// Quadrature counter-clockwise states: 00 -> 01 -> 11 -> 10
void sampleswitches()
{
    int quadcountold = quadcount;
    // Change gas select state only when button is depressed
    quadswitchnew = quadsw;
    if (quadswitchnew == OFF && quadswitchold == ON) // Button pushed down, then released
    {
        if (modetimer.read_ms() <= BUTTONTIMEOUT)
        {
            if (mode == AMPSMODE)
            {
                select++;
                if (select > 3) // Cycle through 2 UIMockup LEDs
                    select = 2;
            }
            else // (mode == GASMODE)
            {
                gasselect++;
                if (gasselect > 4) // Cycle through 4 mbed LEDs
                    gasselect = 1;
            }
        }
        modetimer.stop();
        modetimer.reset();
        quadswitchold = quadswitchnew;
        modechanged = FALSE;
    }
    else if (quadswitchnew == ON && quadswitchold == ON) // Button held down
    {
        if (modetimer.read_ms() == 0)
            modetimer.start();
        else if (modetimer.read_ms() > BUTTONTIMEOUT) // Look for mode change
        {
            if (modechanged == FALSE)
            {
                if (mode == AMPSMODE)
                {
                    mode = GASMODE;
                    pc.printf("Gas mode\n\r");
                }
                else
                {
                    mode = AMPSMODE;
                    pc.printf("Amps mode\n\r");
                }
                modetimer.stop();
                modechanged = TRUE;
            }
        }
        quadswitchold = quadswitchnew;
    }
    else if (quadswitchnew == ON) // Button depressed for the first time
        quadswitchold = quadswitchnew; // Do nothing
    else if (quadswitchnew == OFF) // Button released
        quadswitchold = quadswitchnew; // Do nothing

    // Update 7-segment display
    quadnew = getquad(); // Get new quad state
    switch (quadold)
    {
        case 0:
            switch (quadnew)
            {
                case 0:
                    break;
                case 2:
                    quadcount++;
                    break;
                case 1:
                    quadcount--;
                    break;
                case 3:
                    ; // Missed a count, so do nothing
                    break;
            } // switch
            break;
        case 1:
            switch (quadnew)
            {
                case 1:
                    break;
                case 0:
                    quadcount++;
                    break;
                case 3:
                    quadcount--;
                    break;
                case 2:
                    ; // Missed a count, so do nothing
                    break;
            } //switch
            break;
        case 2:
            switch (quadnew)
            {
                case 2:
                    break;
                case 3:
                    quadcount++;
                    break;
                case 0:
                    quadcount--;
                    break;
                case 1:
                    ; // Missed a count, so do nothing
                    break;
             } // switch
             break;
        case 3:
            switch (quadnew)
            {
                case 3:
                    break;
                case 1:
                    quadcount++;
                    break;
                case 2:
                    quadcount--;
                    break;
                case 0:
                    ; // Missed a count, so do nothing
                    break;
             } // switch
             break;
    } // switch (quadold)
    quadold = quadnew; // Store current quad state
    
    if (mode == AMPSMODE)
    {
        ampscount += (quadcountold - quadcount);
        if (ampscount > MAXAMPS200)
            ampscount = MAXAMPS200; // Clip at high end
        else if (ampscount < MINAMPSET)
            ampscount = MINAMPSET; // Clip at low end
        if (select == 2)
        {
            LEDg2 = ON; LEDg3 = OFF;
        }
        else // select == 3
        {
            LEDg2 = OFF; LEDg3 = ON;
        }
        switch (ampscount % 4) // Get 2 LSBs and display on mbed LEDs
        {
            case 0:
                led1 = 1; led2 = 0; led3 = 0; led4 = 0;
                break;
            case 1:
                led1 = 0; led2 = 1; led3 = 0; led4 = 0;
                break;
            case 2:
                led1 = 0; led2 = 0; led3 = 1; led4 = 0;
                break;
            default:
                led1 = 0; led2 = 0; led3 = 0; led4 = 1;
                break;
        } // switch
        LEDout(ampscount);
        //if (quadcount != quadcountold) pc.printf("%d amps\n\r", ampscount);
    }
    else // (mode == GASMODE)
    {
        gascount += (quadcountold - quadcount);
        if (gascount > MAXGASPRESS)
            gascount = MAXGASPRESS; // Clip at high end
        else if (gascount < MINGASPRESS)
            gascount = MINGASPRESS; // Clip at low end    
        // Update mbed LEDs to simulate gas selection
        switch (gasselect)
        {
            case 1: {
                led1 = 1; led2 = 0; led3 = 0; led4 = 0; }
                break;
            case 2: {
                led1 = 0; led2 = 1; led3 = 0; led4 = 0;
                LEDg2 = ON; LEDg3 = OFF; }
                break;
            case 3: {
                led1 = 0; led2 = 0; led3 = 1; led4 = 0;
                LEDg2 = OFF; LEDg3 = ON; }
                break;
            default: { // gasselect == 4
                led1 = 0; led2 = 0; led3 = 0; led4 = 1; }
                break;
        }
        LEDout(gascount);
        //if (quadcount != quadcountold) pc.printf("%d psi\n\r", gascount);        
    } // if (mode == GASMODE)
} //  sampleswitches()

int main() 
{
    pc.baud(19200);
    pc.printf("\n\rConnected to mBed...\r\n");

    /****** Program Starts Here *******/
    // Initialize variables
    quadnew = getquad(); // Get initial quadrature state
    quadold = quadnew; // Initialize state variables
    quadswitchold = OFF; // Initialize state variables
    mode = AMPSMODE; // Power up in AMPS selection mode
    modetimer.stop();
    modetimer.reset();
    modechanged = FALSE; // Initialize state variables
    select = 1; // Default discrete LED selection
    gasselect = 1;
    quada.mode(PullUp); // Enable pullup resistors on switch inputs
    quadb.mode(PullUp);
    quadsw.mode(PullUp);

    ampscount = MAXAMPS200;
    gascount = STARTGASPRESS;

    // Turn off all LEDs first, and let sampleswitches update everything
    LED1a = OFF; LED1b = OFF; LED1c = OFF; LED1d = OFF; LED1e = OFF; LED1f = OFF; LED1g = OFF;
    LED2a = OFF; LED2b = OFF; LED2c = OFF; LED2d = OFF; LED2e = OFF; LED2f = OFF; LED2g = OFF;
    LED3a = OFF; LED3b = OFF; LED3c = OFF; LED3d = OFF; LED3e = OFF; LED3f = OFF; LED3g = OFF;
    LEDg2 = OFF; LEDg3 = OFF;

    // Set up interrupt call
    getswitches.attach_us(&sampleswitches, 10000); // setup getswitches to call sampleswitches every 10 ms
    
    while (1)
    {
    }// while (1)
    
} // main()