Implementation of the Pomodoro technique on the ESP-32 microcontroller.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
4.4 KiB
Raw

#include "Pomodoro.h"
#include "Timer.h"
#include "SegmentDisplay.h"
#include "SegmentCharacter.h"
#include "NTPSynchronisation.h"
#include <Arduino.h>
#define serialSpeed 115200
uint32_t isrCount=0;
uint32_t isrTime=0;
enum PomodoroStatus{status_work,status_shortBreak,status_longBreak,status_workAfterLongBreak};
PomodoroStatus pStatus=status_work;
uint32_t timeBeforeTransition=0;
uint32_t timeBeforeTransitionMinutes=0;
uint32_t timeBeforeTransitionSeconds=0;
enum DisplayMode{dMode_clockHourMinute,dMode_clockDayMonth,dMode_pomodoro};
DisplayMode dMode=dMode_pomodoro;
const int pinDisplayMode=4;
uint32_t debounceTime=0;
const uint32_t debounceWait=10;
bool wifiIssue=false;
bool ntpIssue=false;
TaskHandle_t taskHandleAnnouncer;
void taskAnnouncer(void * param){
switch(pStatus){
case status_work:
displayWork(false);
break;
case status_workAfterLongBreak:
displayWork(true);
break;
case status_shortBreak:
displayShortRest();
break;
case status_longBreak:
displayLongRest();
break;
default:
break;
}
if(taskHandleAnnouncer!=NULL){
vTaskDelete(taskHandleAnnouncer);
}
}
void startTaskAnnouncer(){
xTaskCreatePinnedToCore(taskAnnouncer,"taskAnnouncer",1024,NULL,1,&taskHandleAnnouncer,0);
}
void IRAM_ATTR displayModeInterrupt(){
if(xTaskGetTickCount()-debounceTime>debounceWait){
switch(dMode){
case dMode_clockHourMinute:
if(wifiIssue||ntpIssue){
dMode=dMode_pomodoro;
}else{
dMode=dMode_clockDayMonth;
}
break;
case dMode_clockDayMonth:
dMode=dMode_pomodoro;
break;
default:
dMode=dMode_clockHourMinute;
break;
}
debounceTime=xTaskGetTickCount();
}
}
void setup(){
Serial.begin(115200);
setupTimer();
setupPomodoro();
setupSegmentDisplay();
sDisplayDigitValue[0]=SC_H;
sDisplayDigitValue[1]=SC_E;
sDisplayDigitValue[2]=SC_L;
sDisplayDigitValue[3]=SC_O;
wifiIssue=!connectWifi(500,10);
if(!wifiIssue){
ntpIssue=!synchroniseTimeNTP(false,true,500,10);
}
pinMode(pinDisplayMode,INPUT_PULLUP);
attachInterrupt(pinDisplayMode, displayModeInterrupt, RISING);
startTaskAnnouncer();
}
void loop() {
powerSegmentDisplay();
delay(20);
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
isrCount=0;
isrTime=0;
// Read the interrupt count and time
portENTER_CRITICAL(&timerMux);
isrCount = isrCounter;
isrTime = lastIsrAt;
portEXIT_CRITICAL(&timerMux);
//Avoid garbage display when isrTime is bigger than the
//waiting time resulting in timeBeforeTransition overflow
if(isrTime>(timerLastValue+currentWait)){
timeBeforeTransition=0;
}else{
timeBeforeTransition=((timerLastValue+currentWait)-isrTime)/1000;
}
switch(dMode){
case dMode_clockHourMinute:
case dMode_clockDayMonth:
if(wifiIssue){
sDisplayDigitValue[0]=SC_W;
sDisplayDigitValue[1]=SC_I;
sDisplayDigitValue[2]=SC_F;
sDisplayDigitValue[3]=SC_I;
break;
}
if(ntpIssue){
sDisplayDigitValue[0]=SC_N;
sDisplayDigitValue[1]=SC_T;
sDisplayDigitValue[2]=SC_P;
sDisplayDigitValue[3]=SC_BLANK;
break;
}
getLocalTime(&timeinfo);
if(dMode==dMode_clockHourMinute){
setNumberToDisplay(timeinfo.tm_hour*100+timeinfo.tm_min);
}else{
setNumberToDisplay(timeinfo.tm_mday*100+timeinfo.tm_mon+1);
}
sDisplayDigitValue[1]=sDisplayDigitValue[1]+SC_DOT;
sDisplayDigitValue[3]=sDisplayDigitValue[3]+SC_DOT;
break;
default:
timeBeforeTransitionMinutes=timeBeforeTransition/60;
timeBeforeTransitionSeconds=timeBeforeTransition%60;
sDisplayDigitValue[0]=SC_NUMBER[timeBeforeTransitionMinutes/10];
sDisplayDigitValue[1]=SC_NUMBER[timeBeforeTransitionMinutes%10]+SC_DOT;
sDisplayDigitValue[2]=SC_NUMBER[timeBeforeTransitionSeconds/10];
sDisplayDigitValue[3]=SC_NUMBER[timeBeforeTransitionSeconds%10];
break;
}
// Pomodoro calculation
if(isrTime>=(timerLastValue+currentWait)){
timerLastValue=isrTime;
if(work){
work=false;
workDone++;
if(workDone>=workBetweenLongBreak){
currentWait=timeLongRest;
workDone=0;
//displayLongRest();
pStatus=status_longBreak;
}else{
currentWait=timeShortRest;
//displayShortRest();
pStatus=status_shortBreak;
}
}else{
currentWait=timeWork;
work=true;
if(workDone==0){
//displayWork(true);
pStatus=status_workAfterLongBreak;
}else{
//displayWork(false);
pStatus=status_work;
}
}
startTaskAnnouncer();
}
}
}