Etch a Sketch on the uLCD screen with wheel encoders as the knobs.

Dependencies:   4DGL-uLCD-SE mbed

main.cpp

Committer:
simplyellow
Date:
2017-03-14
Revision:
2:8752f5af08a4
Parent:
1:876e9cc9088b

File content as of revision 2:8752f5af08a4:

#include "mbed.h"
#include "uLCD_4DGL.h"

//left wheel parameters
InterruptIn leftchA(p26);
InterruptIn leftchB(p25);
int leftChanA;
int leftChanB;
int leftCurrState;
int leftPrevState;
int leftChange;
volatile int count1 = 0;

//right wheel parameters
InterruptIn rightchA(p13);
InterruptIn rightchB(p14);
int rightChanA;
int rightChanB;
int rightCurrState;
int rightPrevState;
int rightChange;
volatile int count2 = 0;

//etch a sketch cursor positions
int x;
int y;
int oldx;
int oldy;

uLCD_4DGL uLCD(p9,p10,p11);

//clearing screen control
InterruptIn cls(p21);
DigitalOut led1(LED1);      //flashes to indicate clear

//drawing control
InterruptIn pen(p22);
bool capOn = true;
DigitalOut led2(LED2);      //on when drawing is turned off

//bluetooth color control
Serial bluemod(p28, p27);
int color = 0xFF0000;       // default red
volatile char bred = 0;
volatile char bgreen = 0;
volatile char bblue = 0;
Ticker t;

//toothbrush motor vibrates during usage
DigitalOut haptic(p20);

/*
*   example 01 <- 11
*   change = (11&01 = 01) ^ (01&10 = 00>>1) = 1
*   example 10 -> 00
*   change = (10&01 = 00) ^ (00&10 = 00>>1) = 0
*   Implemented barebones version of "QEI.h" by Aaron Berk for the sake of
*   understanding the concept of X4 encoding
*   00 01 11 10 00
*   4 different states
*/

/*
*   Calculate the number of pulses recorded by the left wheel
*/
void encode1() {
    leftChange = 0;
    leftChanA  = leftchA.read();
    leftChanB  = leftchB.read();
    leftCurrState = (leftChanA << 1) | (leftChanB);
    if (((leftCurrState ^ leftPrevState) != 0x3) && (leftCurrState != leftPrevState)) {
        leftChange = (leftPrevState & 0x1) ^ ((leftCurrState & 0x2) >> 1);
        if (leftChange == 0) {
            leftChange = -1;
        }
        count1 += leftChange;
    }
    leftPrevState = leftCurrState;
}

/*
*   Calculate the number of pulses recorded by the right wheel
*/
void encode2() {
    rightChange = 0;
    rightChanA  = rightchA.read();
    rightChanB  = rightchB.read();
    rightCurrState = (rightChanA << 1) | (rightChanB);
    if (((rightCurrState ^ rightPrevState) != 0x3) && (rightCurrState != rightPrevState)) {
        rightChange = (rightPrevState & 0x1) ^ ((rightCurrState & 0x2) >> 1);
        if (rightChange == 0) {
            rightChange = -1;
        }
        count2 += rightChange;
    }
    rightPrevState = rightCurrState;
}

/*
*   Clear the LCD screen with a pushbutton
*/
void clear() {
    uLCD.cls();
    led1 = 1;
    wait(0.1);
    led1 = 0;
    wait(0.1);
}

/*
*   Toggle the drawing on the LCD screen
*/
void cap() {
    capOn = !capOn;
    if(!capOn) {
        led2 = 1;
    } else {
        led2 = 0;
    }
}

/*
*   Change the color of the Etch A Sketch 'ink' using bluetooth input
*/
void colorChange() {
    while(bluemod.readable()) {
        if(bluemod.getc()=='!') {
            if(bluemod.getc()=='C') {
                bred = bluemod.getc();
                bgreen = bluemod.getc();
                bblue = bluemod.getc();
                if (bluemod.getc()==char(~('!' + 'C' + bred + bgreen + bblue))) {
                    color = (bred << 16 | bgreen << 8 | bblue);
                }
            }
        }
    }
}

/*
*   Set up pull-ups, initial states, and interrupts on the two wheels and
*   hall sensors
*/
void setupEncoder() {
    leftchA.mode(PullUp);
    leftchB.mode(PullUp);
    rightchA.mode(PullUp);
    rightchB.mode(PullUp);

    leftChanA = leftchA.read();
    leftChanB = leftchB.read();
    rightChanA = rightchA.read();
    rightChanB = rightchB.read();

    leftCurrState = (leftChanA << 1) | (leftChanB);
    leftPrevState = leftCurrState;
    rightCurrState = (rightChanA << 1) | (rightChanB);
    rightPrevState = rightCurrState;

    leftchA.rise(&encode1);
    leftchA.fall(&encode1);
    leftchB.rise(&encode1);
    leftchB.fall(&encode1);

    rightchA.rise(&encode2);
    rightchA.fall(&encode2);
    rightchB.rise(&encode2);
    rightchB.fall(&encode2);
}

int main() {
    //set up features
    setupEncoder();
    cls.mode(PullUp);
    cls.fall(&clear);
    pen.mode(PullUp);
    pen.fall(&cap);
    t.attach(&colorChange, 0.0625);

    //set up LCD
    uLCD.baudrate(300000);
    uLCD.background_color(BLACK);
    uLCD.cls();

    //set up cursor positions
    //for the wheels, +/- counts of 1280 will get you to the edge of screen
    x = 64;
    y = 64;
    oldx = x;
    oldy = y;
    uLCD.pixel(x, y, color);

    while(1) {
        //converting counts to LCD coordinates
        oldx = x;
        oldy = y;
        x = 64+count1/20;
        y = 64+count2/20;
        //if cursor moves, motor vibrates
        if(x!=oldx || y!=oldy) {
            haptic = 1;
            wait(0.05);
        } else {
            haptic = 0;
        }
        //if pen is activated, draw is
        if(capOn) {
            uLCD.pixel(x, y, color);
        }
    }
}