handle buttons and leds completely as user tasks

This commit is contained in:
andreas 2023-10-24 15:58:43 +02:00
parent 91c1e6f85c
commit 0e10fcfee2
8 changed files with 91 additions and 57 deletions

View File

@ -61,12 +61,6 @@ class GwApi{
}; };
class Status{ class Status{
public: public:
typedef enum{
OFF,
PRESSED,
PRESSED_5, //5...10s
PRESSED_10 //>10s...30s
} ButtonState;
bool wifiApOn=false; bool wifiApOn=false;
bool wifiClientOn=false; bool wifiClientOn=false;
bool wifiClientConnected=false; bool wifiClientConnected=false;
@ -89,8 +83,6 @@ class GwApi{
bool tcpClientConnected=false; bool tcpClientConnected=false;
unsigned long n2kRx=0; unsigned long n2kRx=0;
unsigned long n2kTx=0; unsigned long n2kTx=0;
ButtonState button=OFF;
unsigned long buttonPresses=0;
void empty(){ void empty(){
wifiApOn=false; wifiApOn=false;
wifiClientOn=false; wifiClientOn=false;
@ -114,8 +106,6 @@ class GwApi{
tcpClientConnected=false; tcpClientConnected=false;
n2kRx=0; n2kRx=0;
n2kTx=0; n2kTx=0;
button=OFF;
buttonPresses=0;
} }
}; };
/** /**

View File

@ -1,5 +0,0 @@
#ifndef _GWBUTTONS_H
#define _GWBUTTONS_H
//task function
void handleButtons(void *param);
#endif

View File

@ -1,4 +1,5 @@
#include "GwButtons.h" #include "GwButtonTask.h"
#include "GwIButtonTask.h"
#include "GwHardware.h" #include "GwHardware.h"
#include "GwApi.h" #include "GwApi.h"
#include "GwLedTask.h" #include "GwLedTask.h"
@ -22,9 +23,12 @@ class FactoryResetRequest: public GwMessage{
},"reset",1000,NULL,0,NULL); },"reset",1000,NULL,0,NULL);
}; };
}; };
void handleButtons(void *param){ void handleButtons(GwApi *api){
GwApi *api=(GwApi*)param;
GwLog *logger=api->getLogger(); GwLog *logger=api->getLogger();
IButtonTask state;
if (!apiSetIButtonTask(api,state)){
LOG_DEBUG(GwLog::ERROR,"unable to set button state");
}
#ifndef GWBUTTON_PIN #ifndef GWBUTTON_PIN
LOG_DEBUG(GwLog::LOG,"no button pin defined, do not watch"); LOG_DEBUG(GwLog::LOG,"no button pin defined, do not watch");
vTaskDelete(NULL); vTaskDelete(NULL);
@ -50,46 +54,51 @@ void handleButtons(void *param){
unsigned long lastReport=0; unsigned long lastReport=0;
const unsigned long OFF_TIME=20; const unsigned long OFF_TIME=20;
const unsigned long REPORT_TIME=1000; const unsigned long REPORT_TIME=1000;
const unsigned long HARD_REST_TIME=10000; const unsigned long PRESS_5_TIME=5000;
GwLedMode ledMode=LED_OFF; const unsigned long PRESS_10_TIME=10000;
const unsigned long PRESS_RESET_TIME=12000;
LOG_DEBUG(GwLog::LOG,"button task started");
while(true){ while(true){
delay(10); delay(10);
int current=digitalRead(GWBUTTON_PIN); int current=digitalRead(GWBUTTON_PIN);
unsigned long now=millis(); unsigned long now=millis();
IButtonTask::ButtonState lastState=state.state;
if (current != activeState){ if (current != activeState){
if (lastPressed != 0 && (lastPressed+OFF_TIME) < now){ if (lastPressed != 0 && (lastPressed+OFF_TIME) < now){
lastPressed=0; //finally off lastPressed=0; //finally off
firstPressed=0; firstPressed=0;
if (ledMode != LED_OFF){ state.state=IButtonTask::OFF;
setLedMode(LED_GREEN); //TODO: better "go back"
ledMode=LED_OFF;
}
LOG_DEBUG(GwLog::LOG,"Button press stopped"); LOG_DEBUG(GwLog::LOG,"Button press stopped");
} }
if (state.state != lastState){
apiSetIButtonTask(api,state);
}
continue; continue;
} }
lastPressed=now; lastPressed=now;
if (firstPressed == 0) { if (firstPressed == 0) {
firstPressed=now; firstPressed=now;
LOG_DEBUG(GwLog::LOG,"Button press started"); LOG_DEBUG(GwLog::LOG,"Button press started");
state.pressCount++;
state.state=IButtonTask::PRESSED;
apiSetIButtonTask(api,state);
lastReport=now; lastReport=now;
continue;
} }
if (lastReport != 0 && (lastReport + REPORT_TIME) < now ){ if (lastReport != 0 && (lastReport + REPORT_TIME) < now ){
LOG_DEBUG(GwLog::LOG,"Button active for %ld",(now-firstPressed)); LOG_DEBUG(GwLog::LOG,"Button active for %ld",(now-firstPressed));
lastReport=now; lastReport=now;
} }
GwLedMode nextMode=ledMode; if (now > (firstPressed+PRESS_5_TIME)){
if (now > (firstPressed+HARD_REST_TIME/2)){ state.state=IButtonTask::PRESSED_5;
nextMode=LED_BLUE;
} }
if (now > (firstPressed+HARD_REST_TIME*0.9)){ if (now > (firstPressed+PRESS_10_TIME)){
nextMode=LED_RED; state.state=IButtonTask::PRESSED_10;
} }
if (ledMode != nextMode){ if (lastState != state.state){
setLedMode(nextMode); apiSetIButtonTask(api,state);
ledMode=nextMode;
} }
if (now > (firstPressed+HARD_REST_TIME)){ if (now > (firstPressed+PRESS_RESET_TIME)){
LOG_DEBUG(GwLog::ERROR,"Factory reset by button"); LOG_DEBUG(GwLog::ERROR,"Factory reset by button");
GwMessage *r=new FactoryResetRequest(api); GwMessage *r=new FactoryResetRequest(api);
api->getQueue()->sendAndForget(r); api->getQueue()->sendAndForget(r);

View File

@ -0,0 +1,7 @@
#ifndef _GWBUTTONTASK_H
#define _GWBUTTONTASK_H
#include "GwApi.h"
//task function
void handleButtons(GwApi *param);
DECLARE_USERTASK(handleButtons);
#endif

View File

@ -0,0 +1,19 @@
#ifndef _GWIBUTTONTASK_H
#define _GWIBUTTONTASK_H
#include "GwApi.h"
class IButtonTask : public GwApi::TaskInterfaces::Base
{
public:
typedef enum
{
OFF,
PRESSED,
PRESSED_5, // 5...10s
PRESSED_10 //>10s
} ButtonState;
ButtonState state=OFF;
long pressCount=0;
};
DECLARE_TASKIF(handleButtons,IButtonTask);
#endif

View File

@ -2,12 +2,14 @@
#include "GwHardware.h" #include "GwHardware.h"
#include "GwApi.h" #include "GwApi.h"
#include "FastLED.h" #include "FastLED.h"
#include "GwIButtonTask.h"
static GwLedMode mode=LED_OFF; typedef enum {
void setLedMode(GwLedMode newMode){ LED_OFF,
//we consider the mode to an atomic item... LED_GREEN,
mode=newMode; LED_BLUE,
} LED_RED,
LED_WHITE
} GwLedMode;
static CRGB::HTMLColorCode colorFromMode(GwLedMode cmode){ static CRGB::HTMLColorCode colorFromMode(GwLedMode cmode){
switch(cmode){ switch(cmode){
@ -38,18 +40,41 @@ void handleLeds(GwApi *api){
FastLED.addLeds<GWLED_TYPE,GWLED_PIN>(leds,1); FastLED.addLeds<GWLED_TYPE,GWLED_PIN>(leds,1);
#endif #endif
uint8_t brightness=api->getConfig()->getInt(GwConfigDefinitions::ledBrightness,128); uint8_t brightness=api->getConfig()->getInt(GwConfigDefinitions::ledBrightness,128);
GwLedMode currentMode=mode; GwLedMode currentMode=LED_GREEN;
leds[0]=colorFromMode(currentMode); leds[0]=colorFromMode(currentMode);
FastLED.setBrightness(brightness); FastLED.setBrightness(brightness);
FastLED.show(); FastLED.show();
LOG_DEBUG(GwLog::LOG,"led task started with mode %d",(int)currentMode); LOG_DEBUG(GwLog::LOG,"led task started with mode %d",(int)currentMode);
while(true){ int apiResult=0;
while (true)
{
delay(50); delay(50);
GwLedMode newMode=mode; GwLedMode newMode = currentMode;
if (newMode != currentMode){ IButtonTask buttonState = apiGetIButtonTask(api, apiResult);
leds[0]=colorFromMode(newMode); if (apiResult >= 0)
{
switch (buttonState.state)
{
case IButtonTask::PRESSED_5:
newMode = LED_BLUE;
break;
case IButtonTask::PRESSED_10:
newMode = LED_RED;
break;
default:
newMode = LED_GREEN;
break;
}
}
else
{
newMode = LED_WHITE;
}
if (newMode != currentMode)
{
leds[0] = colorFromMode(newMode);
FastLED.show(); FastLED.show();
currentMode=newMode; currentMode = newMode;
} }
} }
vTaskDelete(NULL); vTaskDelete(NULL);

View File

@ -3,13 +3,6 @@
#include "GwApi.h" #include "GwApi.h"
//task function //task function
void handleLeds(GwApi *param); void handleLeds(GwApi *param);
typedef enum {
LED_OFF,
LED_GREEN,
LED_BLUE,
LED_RED,
LED_WHITE
} GwLedMode;
void setLedMode(GwLedMode mode);
DECLARE_USERTASK(handleLeds); DECLARE_USERTASK(handleLeds);
#endif #endif

View File

@ -53,8 +53,6 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
#include "GwSerial.h" #include "GwSerial.h"
#include "GwWebServer.h" #include "GwWebServer.h"
#include "NMEA0183DataToN2K.h" #include "NMEA0183DataToN2K.h"
#include "GwButtons.h"
#include "GwLedTask.h"
#include "GwCounter.h" #include "GwCounter.h"
#include "GwXDRMappings.h" #include "GwXDRMappings.h"
#include "GwSynchronized.h" #include "GwSynchronized.h"
@ -852,8 +850,6 @@ void setup() {
NMEA2000.Open(); NMEA2000.Open();
logger.logDebug(GwLog::LOG,"starting addon tasks"); logger.logDebug(GwLog::LOG,"starting addon tasks");
logger.flush(); logger.flush();
setLedMode(LED_GREEN);
userCodeHandler.startAddonTask(F("handleButtons"),handleButtons,100);
{ {
GWSYNCHRONIZED(&mainLock); GWSYNCHRONIZED(&mainLock);
userCodeHandler.startUserTasks(MIN_USER_TASK); userCodeHandler.startUserTasks(MIN_USER_TASK);