Johnl52 / Arduino-Date-Entry

Data entry sketch
0 stars 0 forks source link

Multitasking #2

Open pataelmo opened 4 years ago

pataelmo commented 4 years ago

I think a core crux of your issue is about multitasking and making your code non-blocking.

As soon as you need to handle different events from different places and do the right thing with either or both of those inputs it's valuable to switch you code logic from block to non-blocking (or minimally blocking) code.

You need to:

I typically write my main loop something like this:

#define TOUCH_SELECTION_NONE 0
#define TOUCH_SELECTION_DATE 1

int selectedItem = TOUCH_SELECTION_NONE;
char currentDate[9] = "10/09/19";
bool screenUpdated = true;

loop() {
     handleScreenTouch();
     handleKeyboardPress();
     drawScreen();
}

void handleScreenTouch() {
    TSPoint p = ts.getPoint();
    // Detect Date pressed
    if ((p.x>=387) && (p.x<=475) && (p.y>=158) && (p.y<=318)) {
        selectedItem = TOUCH_SELECTION_DATE;
    } else {
        selectedItem = TOUCH_SELECTION_NONE;
    }
}

void handleKeyboadPress() {
    char keyPress = 0;
    if(Serial1.available()) {
         keyPress = Serial1.read();
         if (selectedItem == TOUCH_SELECTION_DATE) {
             updateDateItem(keyPress);
         }
        // If nothing is selected we'll read the character but drop it.
    }
}

void updateDateItem(char key) {
    static char newDate[10] = "";
    static byte newDateIndex = 0;
    if (key == '\r') {
        if (newDateIndex > 0) {
            for (int x=0;x<newDateIndex;x++) {
                 currentDate[x] = newDate[x];
            }
            newDateIndex = 0;
            screenUpdated = true;
       }
    } else if (newDateIndex < 10) {
       newDate[newDateIndex++] = key;
    }
}

void drawScreen () {
    if (screenUpdated) {
        // Redraw the screen
        screenUpdated = false;
    }
}
Johnl52 commented 4 years ago

By Block and non-blocking do you mean instead of having most of the code in the main loop (a block of code) break it up into smaller sub routines (handleScreenTouch(), handleKeyboardPress(), drawScreen())? That is the way I prefer to do my programs, makes it more manageable to understand what is doing what. Also why I try to get each part working individually before bringing it into the main program. The changes below you have for reading the keyboard and such, will those work the way they are or mainly just an outline for me to follow? I see you changed the While to an If for reading the keyboard. Thanks so much for your time with this, greatly appreciatedJohn On Wednesday, October 9, 2019, 10:05:00 AM EDT, Patrick notifications@github.com wrote:

I think a core crux of your issue is about multitasking and making your code non-blocking.

As soon as you need to handle different events from different places and do the right thing with either or both of those inputs it's valuable to switch you code logic from block to non-blocking (or minimally blocking) code.

You need to:

I typically write my main loop something like this:

define TOUCH_SELECTION_NONE 0

define TOUCH_SELECTION_DATE 1

int selectedItem = TOUCH_SELECTION_NONE; char currentDate[9] = "10/09/19"; bool screenUpdated = true;

loop() { handleScreenTouch(); handleKeyboardPress(); drawScreen(); }

void handleScreenTouch() { TSPoint p = ts.getPoint(); // Detect Date pressed if ((p.x>=387) && (p.x<=475) && (p.y>=158) && (p.y<=318)) { selectedItem = TOUCH_SELECTION_DATE; } else { selectedItem = TOUCH_SELECTION_NONE; } }

void handleKeyboadPress() { char keyPress = 0; if(Serial1.available()) { keyPress = Serial1.read(); if (selectedItem == TOUCH_SELECTION_DATE) { updateDateItem(keyPress); } // If nothing is selected we'll read the character but drop it. } }

void updateDateItem(char key) { static char newDate[10] = ""; static byte newDateIndex = 0; if (key == '\r') { if (newDateIndex > 0) { for (int x=0;x<newDateIndex;x++) { currentDate[x] = newDate[x]; } newDateIndex = 0; screenUpdated = true; } } else if (newDateIndex < 10) { newDate[newDateIndex++] = key; } }

void drawScreen () { if (screenUpdated) { // Redraw the screen screenUpdated = false; } }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

pataelmo commented 4 years ago

The breaking things into smaller chunks of code by using functions like I did here is good for readability. But blocking versus not blocking means that the code doesn't stop other things from happening.

Technically all code on a micro is blocking because there is no OS to switch tasks, but the idea of avoid while loops or calling function that take a long (especially undetermined) amount of time to return. So instead of having a while loop that waits until all the data from the keyboard can be read, you just check to see if there's a byte and if so grab it an throw it into a buffer. Then you can check to see if there is enough data in the buffer to do something (in this case check for \r).

Blocking code is code that will block other code from being able to run. By writing code that's non-blocking you can make your main loop just call a bunch of things that need to happen and none of them will stop the others from being able to work.

Other than replacing the // redraw screen comment with actual code that'll redraw the entire screen I believe the code I wrote above will work as you intend, but haven't even checked to see if it'll compile, so no promises 😃

Johnl52 commented 4 years ago

Thanks for the explanation. That's the same reason I don't use "delay" in my programs, makes everything stop for that amount of time. For timing I use the millisec clock grab a start time and compare it to a stop time. I should be able to get it to compile, after all you had to leave something for me to do :) 

On Wednesday, October 9, 2019, 03:56:16 PM EDT, Patrick <notifications@github.com> wrote:  

The breaking things into smaller chunks of code by using functions like I did here is good for readability. But blocking versus not blocking means that the code doesn't stop other things from happening.

Technically all code on a micro is blocking because there is no OS to switch tasks, but the idea of avoid while loops or calling function that take a long (especially undetermined) amount of time to return. So instead of having a while loop that waits until all the data from the keyboard can be read, you just check to see if there's a byte and if so grab it an throw it into a buffer. Then you can check to see if there is enough data in the buffer to do something (in this case check for \r).

Blocking code is code that will block other code from being able to run. By writing code that's non-blocking you can make your main loop just call a bunch of things that need to happen and none of them will stop the others from being able to work.

Other than replacing the // redraw screen comment with actual code that'll redraw the entire screen I believe the code I wrote above will work as you intend, but haven't even checked to see if it'll compile, so no promises 😃

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub, or unsubscribe.