Program that uses Adafruit FONA 800h and resistive touch uLCD display to track roommates and send and receive text messages.

Dependencies:   mbed-rtos mbed uLCD_4D_Picaso

main.cpp

Committer:
coleandbrandon
Date:
2016-05-01
Revision:
0:0b0487606b13

File content as of revision 0:0b0487606b13:

#include "mbed.h"
#include "uLCD_4D_Picaso.h"
#include "Adafruit_FONA.h"
#include "rtos.h"
#include <string>
#include <vector>
#include <ctype.h>

#define FONA_RST p12
#define FONA_TX p13
#define FONA_RX p14
#define FONA_RI p11

//using namespace std;
Serial pcSerial(USBTX, USBRX);
Adafruit_FONA fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);

Mutex mut;
uLCD_4D_Picaso lcd(p28, p27, p30);

// this is a large buffer for replies
char replybuffer[255];

// Turn on a LED when somebody calls the FONA (we need to somehow make this apply to texts instead of call
// Ok so this works!! just change where indicated
DigitalOut led1(LED1);
DigitalOut led2(LED2);
volatile bool newText = false; 
class FonaEventListener : public Adafruit_FONA::EventListener {
    virtual void onRing() { //<- Upon arrival of new text here is what happens
        //this is what should happen when a text comes in
        
        led1 = 1;
        wait_ms(500);
        led1 = 0;
        newText = true; //global 
    }
    
    virtual void onNoCarrier() {
        led1 = 0;
    }
};
FonaEventListener fonaEventListener;

// Functions defined after main()
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
void flushSerial();
char readBlocking();
uint16_t readnumber();
long map(long x, long in_min, long in_max, long out_min, long out_max);

// I don't think this global variable is defined correctly
volatile bool whoshome[4] = {0}; // Cole = whoshome[0], brandon = whoshome[1], George = whoshome[2], Jesse = whoshome[3]

// This member function needs to run when a text message has been received by the FONA module.
// textout() reads the phone number of the person who sent the text message from text message slot 1,
// deletes that text message, checks the boolean array that indicates who is home and then sends out a text
// message for each person that is home.

void textout();    
   
// The ___home() member functions below should be called when the ____home buttons on the LCD touchscreen are pressed.
// For example, when cole comes in the house he will push his button to indicate that he is home. This will update his
// status from away (0) to home (1) and text everyone that is HOME the text message "Cole is home." The functionality is 
// the same for brandonshome, georgeshome, jesseshome

void coleshome();
void brandonshome();
void georgeshome();
void jesseshome();

// These functions should be called when one of the roommates pushes the ____away button on the lcd touchscreen.
// For example, if Cole is leaving the house, then he would touch the COLE away box and it would change his value
// in the boolean array whoshome from home (1) to away (0). Then, the next time the LCD DISPLAY thread is run,
// Cole's name would disappear from the display because he is away.

void colesaway(void);
void brandonsaway(void);
void georgesaway(void);
void jessesaway(void);

// This is the display function that updates the names based on the boolean array whoshome. Let me know if you
// have questions about this.

void update_display(){
    mut.lock();
    
    //print names - if home, print name, if not, print blank spaces 
    
    lcd.txt_MoveCursor(4, 0);
    lcd.txt_Attributes(Picaso::UNDERLINED);
    
    if (whoshome[0]) { //cole
        lcd.putStr("Cole\r\n");
        }
    else lcd.putStr("       \r\n");
    if (whoshome[1]) {  //Brandon
        lcd.putStr("Brandon\r\n");
        }
    else lcd.putStr("       \r\n");
    if (whoshome[2]) { //george
        lcd.putStr("George\r\n");
        }
    else lcd.putStr("       \r\n");
    if (whoshome[3]) { //Jesse
        lcd.putStr("Jesse\r\n");
        }
    else lcd.putStr("       \r\n");
    
    mut.unlock();
}

void display_func(void const *args){ //this is what is going to be responsible for updating to the screen
 
    // this may need to be in a separate thread, i'm not sure. we also may need to use a mutex
    mut.lock();
    pcSerial.printf("i'm in the display function\r\n");
    mut.unlock();
    int status = 0;
    int x = 0;
    int y = 0;
    while (1) {
        status = lcd.touch_Get(0);
        if (status) {
            mut.lock();
            pcSerial.printf("i got touched\r\n");
            mut.unlock();
            x = lcd.touch_Get(1);
            y = lcd.touch_Get(2);
            
                if (status == 1 && y >= 180 && y <= 240 && x >= 0 && x <= 55) {
                    //update_display();
                    coleshome();
                } 
                if (status == 1 && y >= 180 && y <= 240 && x >= 65 && x <= 115) {
                    //update_display();
                    brandonshome();
                } 
                if (status == 1 && y >= 180 && y <= 240 && x >= 125 && x <= 175) {
                    //update_display();
                    georgeshome();
                } 
                if (status == 1 && y >= 180 && y <= 240 && x >= 185 && x <= 240) {
                    //update_display();
                    jesseshome();
                } 
            
            // AWAY
            
                if (status == 1 && y >= 250 && x >= 0 && x <= 55) {
                    //update_display();
                    colesaway();
                } 
                if (status == 1 && y >= 250 && x >= 65 && x <= 115) {
                    //update_display();
                    brandonsaway();
                } 
                if (status == 1 && y >= 250 && x >= 125 && x <= 175) {
                    //update_display();
                    georgesaway();
                } 
                if (status == 1 && y >= 250 && x >= 185 && x <= 240) {
                    jessesaway();
                    //update_display();
                } 
        }
    }  
} 

void textout(void const *args){ // this is responsible for texting a list of people who are home 
    
    while(true) {
        while (!newText) Thread::yield(); //GEORGE!!!
        mut.lock();
        pcSerial.printf("i received a text message\r\n");
        mut.unlock();
        newText = false; //update global variable
        //read in txt message
        fona.getSMSSender(1, replybuffer, 250); // store phone number in reply buffer
        
        fona.deleteSMS(1); // delete text message to free up sms #1
        mut.lock();
        pcSerial.printf("text message deleted\r\n");
        mut.unlock();
        //reply to number with texts of who is home
        if (whoshome[0]) { //cole
            fona.sendSMS(replybuffer, "Cole is home");
            //wait_ms(250);
        }
        if (whoshome[1]) { //brandon
            fona.sendSMS(replybuffer, "Brandon is home");
            //wait_ms(250);
        }
        if (whoshome[2]) { //george
            fona.sendSMS(replybuffer, "George is home");
            //wait_ms(250);
        }
        if (whoshome[3]) { //jesse
            fona.sendSMS(replybuffer, "Jesse is home");
            //wait_ms(250);
        }
        if (whoshome[0] == 0 && whoshome[1] == 0 && whoshome[2] == 0 && whoshome[3] == 0) {
            fona.sendSMS(replybuffer, "No one is home :(");
            //wait_ms(250);
        }
    }
}    

void coleshome(){
    // update bool array
    whoshome[0] = 1;
    update_display();
    if (whoshome[1]) {
        fona.sendSMS("6789936332", "Cole is home."); //text brandon
        //wait_ms(250);
    }
    if (whoshome[2]) {
        fona.sendSMS("4045189567", "Cole is home."); //text george
        //wait_ms(250);
    }
    if (whoshome[3]) {
        fona.sendSMS("7067664360", "Cole is home."); //text jesse
        //wait_ms(250);
    }
}

void brandonshome(){
    // update bool array
    whoshome[1] = 1;
    update_display();
    if (whoshome[0]) {
        fona.sendSMS("8476022588", "Brandon is home."); //text cole
        //wait_ms(250);
    }
    if (whoshome[2]) {
        fona.sendSMS("4045189567", "Brandon is home."); //text george
        //wait_ms(250);
    }
    if (whoshome[3]) {
        fona.sendSMS("7067664360", "Brandon is home."); //text jesse
        //wait_ms(250);
    }
}

void georgeshome(){
    // update bool array
    whoshome[2] = 1;
    update_display();
    if (whoshome[0]) {
        fona.sendSMS("8476022588", "George is home."); //text cole
        //wait_ms(250);
    }
    if (whoshome[1]) {
        fona.sendSMS("6789936332", "George is home."); //text brandon
        //wait_ms(250);
    }
    if (whoshome[3]) {
        fona.sendSMS("7067664360", "George is home."); //text jesse
        //wait_ms(250);
    }
}

void jesseshome(){
    // update bool array
    whoshome[3] = 1;
    update_display();
    if (whoshome[0]) {
        fona.sendSMS("8476022588", "Jesse is home."); //text cole
        //wait_ms(250);
    }
    if (whoshome[1]) {
        fona.sendSMS("6789936332", "Jesse is home."); //text brandon
        //wait_ms(250);
    }
    if (whoshome[2]) {
        fona.sendSMS("4045189567", "Jesse is home."); //text george
        //wait_ms(250);
    }
}

void colesaway(){
    whoshome[0] = 0;
    update_display();
}

void brandonsaway(){
    whoshome[1] = 0;
    update_display();
}

void georgesaway(){
    whoshome[2] = 0;
    update_display();
}

void jessesaway(){
    whoshome[3] = 0;
    update_display();
}


void flushSerial() {
    while (pcSerial.readable()) 
        pcSerial.getc();
}

char readBlocking() {
    while (!pcSerial.readable());
    return pcSerial.getc();
}

uint16_t readnumber() {
    uint16_t x = 0;
    char c;
    while (! isdigit(c = readBlocking())) {
        //pcSerial.putc(c);
    }
    pcSerial.putc(c);
    x = c - '0';
    while (isdigit(c = readBlocking())) {
        pcSerial.putc(c);
        x *= 10;
        x += c - '0';
    }
    return x;
}
  
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout) {
    uint16_t buffidx = 0;
    bool timeoutvalid = true;
    if (timeout == 0) timeoutvalid = false;
    
    while (true) {
        if (buffidx > maxbuff) {
            //pcSerial.printf("SPACE\r\n");
            break;
        }
        
        while(pcSerial.readable()) {
            char c =  pcSerial.getc();
            
            //pcSerial.printf("%02x#%c\r\n", c, c);
            
            if (c == '\r') continue;
            if (c == 0xA) {
                if (buffidx == 0)   // the first 0x0A is ignored
                    continue;
                
                timeout = 0;         // the second 0x0A is the end of the line
                timeoutvalid = true;
                break;
            }
            buff[buffidx] = c;
            buffidx++;
        }
        
        if (timeoutvalid && timeout == 0) {
            //pcSerial.printf("TIMEOUT\r\n");
            break;
        }
        wait_ms(1);
    }
    buff[buffidx] = 0;  // null term
    return buffidx;
}

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void initialize_everything(){
        //initiate whatever
   
    // LCD touchscreen
    lcd.setbaudWait(Picaso::BAUD_600000);
    lcd.touch_Set(0);
    lcd.txt_Opacity(Picaso::OPAQUE);
    
    //Set up header
    
    lcd.txt_MoveCursor(0, 6);
    lcd.txt_Attributes(Picaso::BOLD);
    lcd.txt_FGcolour(Picaso::RED);
    lcd.putStr("mbed Roomate Tracker");
    lcd.txt_MoveCursor(2, 0);
    lcd.txt_FGcolour(Picaso::CYAN);
    lcd.putStr("Who's home?");
    
    //Set up touch boxes
    lcd.gfx_Rectangle(0, 180, 55, 240, Picaso::RED);
    lcd.gfx_RectangleFilled(1, 181, 54, 239, Picaso::WHITE);
    lcd.gfx_Rectangle(65, 180, 115, 240, Picaso::RED);
    lcd.gfx_RectangleFilled(66, 181, 114, 239, Picaso::WHITE);
    lcd.gfx_Rectangle(125, 180, 175, 240, Picaso::RED);
    lcd.gfx_RectangleFilled(126, 181, 174, 239, Picaso::WHITE);
    lcd.gfx_Rectangle(185, 180, 240, 240, Picaso::RED);
    lcd.gfx_RectangleFilled(186, 181, 239, 239, Picaso::WHITE);
    lcd.txt_MoveCursor(17, 2);
    lcd.putStr("COLE\r\nhome");
    lcd.txt_MoveCursor(17, 8);
    lcd.putStr("BRANDON\r\nhome");
    lcd.txt_MoveCursor(17, 16);
    lcd.putStr("GEORGE\r\nhome");
    lcd.txt_MoveCursor(17, 24);
    lcd.putStr("JESSE\r\nhome");
    
    lcd.gfx_Rectangle(0, 250, 55, 310, Picaso::RED);
    lcd.gfx_RectangleFilled(1, 251, 54, 309, Picaso::WHITE);
    lcd.gfx_Rectangle(65, 250, 115, 310, Picaso::RED);
    lcd.gfx_RectangleFilled(66, 251, 114, 309, Picaso::WHITE);
    lcd.gfx_Rectangle(125, 250, 175, 310, Picaso::RED);
    lcd.gfx_RectangleFilled(126, 251, 174, 309, Picaso::WHITE);
    lcd.gfx_Rectangle(185, 250, 240, 310, Picaso::RED);
    lcd.gfx_RectangleFilled(186, 251, 239, 309, Picaso::WHITE);
    lcd.txt_FGcolour(Picaso::WHITE);
    lcd.txt_Attributes(Picaso::UNDERLINED);
    lcd.txt_MoveCursor(23, 2);
    lcd.putStr("COLE\r\naway");
    lcd.txt_MoveCursor(23, 8);
    lcd.putStr("BRANDON\r\naway");
    lcd.txt_MoveCursor(23, 16);
    lcd.putStr("GEORGE\r\naway");
    lcd.txt_MoveCursor(23, 24);
    lcd.putStr("JESSE\r\naway");
    
    
    flushSerial();
    //FONA initialization (copied from FONA code (may only need the fona.begin(9600) but all of this stuff won't hurt to have
    pcSerial.baud(9600);
    wait(1);
    mut.lock();
    pcSerial.printf("\r\n");
    
    pcSerial.printf("FONA basic test\r\n");
    pcSerial.printf("Initializing....(May take 3 seconds)\r\n");
    wait(2);
    // See if the FONA is responding
    if (! fona.begin(9600)) {
        pcSerial.printf("Couldn't find FONA\r\n");
        while (1);
    }
    pcSerial.printf("Can I get an Amen\r\n");
    fona.setEventListener(&fonaEventListener);
    pcSerial.printf("FONA is OK\r\n");
    for( int i = 1; i < 10; i++){
        fona.deleteSMS(i);
        wait_ms(10);
    }
    
    // Print SIM card IMEI number.
    char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
    uint8_t imeiLen = fona.getIMEI(imei);
    if (imeiLen > 0) {
        pcSerial.printf("SIM card IMEI: %s\r\n", imei);
    }
    mut.unlock();
}


int main() {
   
    initialize_everything(); //does all the setup stuff
 ///   //start threads
    pcSerial.printf("everything is initialized\r\n");
    Thread thread1(display_func); //this is what waits for something to touch it
    pcSerial.printf("display thread good\r\n");
    Thread thread2(textout);
    pcSerial.printf("textout thread good\r\n");
    //Thread thread3(texting);
    while (true){
    led2 = !led2;
    Thread::wait(500);
    }
   
    //wait
   
}