Skip to content

Commit

Permalink
implemented button/touch assertions as callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
tobozo committed Dec 20, 2020
1 parent 0659622 commit 91af010
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 77 deletions.
9 changes: 5 additions & 4 deletions src/M5StackUpdater.h
Expand Up @@ -70,7 +70,8 @@
* checkSDUpdater( SD, MENU_BIN, 2000 );
*
* Headless setups can overload SDUpdater::assertStartUpdate
* with their own button/sensor/whatever detection routine
* (see setAssertTrigger() in M5StachUpdateUI.h) and have
* their own button/sensor/whatever detection routine
* or even issue the "update" command via serial
*
* if(digitalRead(BUTTON_A_PIN) == 0) {
Expand Down Expand Up @@ -210,7 +211,7 @@ class SDUpdater_Base {
bool SPIFFSisEmpty();
#endif

int (*assertStartUpdate)( char* labelLoad, char* labelSkip );
//int (*assertStartUpdate)( char* labelLoad, char* labelSkip, unsigned long waitdelay );
void (*displayUpdateUI)( const String& label );
void (*SDMenuProgress)( int state, int size );

Expand All @@ -227,7 +228,7 @@ class SDUpdater_Headless : public SDUpdater_Base {
SDUpdater_Headless( const int TFCardCsPin_ = TFCARD_CS_PIN ) : SDUpdater_Base( TFCardCsPin_ ) {
SDMenuProgress = SDMenuProgressHeadless;
displayUpdateUI = DisplayUpdateHeadless;
assertStartUpdate = assertStartUpdateFromSerial;
//assertStartUpdate = assertStartUpdateFromSerial;
};

};
Expand All @@ -239,7 +240,7 @@ class SDUpdater_Headless : public SDUpdater_Base {
SDUpdater_Display( const int TFCardCsPin_ = TFCARD_CS_PIN ) : SDUpdater_Base( TFCardCsPin_ ) {
SDMenuProgress = SDMenuProgressUI;
displayUpdateUI = DisplayUpdateUI;
assertStartUpdate = assertStartUpdateFromButton;
//assertStartUpdate = assertStartUpdateFromPushButton;
};

};
Expand Down
30 changes: 16 additions & 14 deletions src/M5StackUpdaterHeadless.h
Expand Up @@ -7,13 +7,16 @@
#define SDU_ROLLBACK_MSG "Will Roll back"

__attribute__((unused))
static int assertStartUpdateFromSerial( char* labelLoad, char* labelSkip )
static int assertStartUpdateFromSerial( char* labelLoad, char* labelSkip, unsigned long waitdelay )
{
if( Serial.available() ) {
String out = Serial.readStringUntil('\n');
if( out == "update" ) return 1;
if( out == "rollback") return 0;
}
auto msec = millis();
do {
if( Serial.available() ) {
String out = Serial.readStringUntil('\n');
if( out == "update" ) return 1;
if( out == "rollback") return 0;
}
} while( msec > millis()-waitdelay );
return -1;
}

Expand All @@ -24,14 +27,13 @@ static void checkSDUpdaterHeadless( fs::FS &fs, String fileName, unsigned long w
if( waitdelay == 0 ) {
waitdelay = 100; // at lease give some time for the serial buffer to fill
}
auto msec = millis();
do {
if ( assertStartUpdateFromSerial( nullptr, nullptr ) == 1 ) {
Serial.printf( SDU_LOAD_TPL, fileName.c_str() );
updateFromFS( fs, fileName, TfCardCsPin_ );
ESP.restart();
}
} while (millis() - msec < waitdelay);

if ( assertStartUpdateFromSerial( nullptr, nullptr, waitdelay ) == 1 ) {
Serial.printf( SDU_LOAD_TPL, fileName.c_str() );
updateFromFS( fs, fileName, TfCardCsPin_ );
ESP.restart();
}

Serial.print("Delay expired, no SD-Update will occur");
}

Expand Down
142 changes: 83 additions & 59 deletions src/M5StackUpdaterUI.h
Expand Up @@ -13,43 +13,48 @@
#define BTN_HINT_MSG "SD-Updater Options"


#if defined _CHIMERA_CORE_ || defined _M5STICKC_H_ || defined _M5STACK_H_ || defined _M5Core2_H_ //|| defined LGFX_ONLY
__attribute__((unused))
static int (*SDUpdaterAssertTrigger)( char* labelLoad, char* labelSkip, unsigned long waitdelay ) = nullptr;
typedef int (*assertTrigger)( char* labelLoad, char* labelSkip, unsigned long waitdelay );
// attach a button/touch event detection
__attribute__((unused))
static void setAssertTrigger( assertTrigger tg )
{
SDUpdaterAssertTrigger = tg;
}

#if defined _CHIMERA_CORE_ || defined _M5STICKC_H_ || defined _M5STACK_H_ || defined _M5Core2_H_ //|| defined LGFX_ONLY

#if defined LGFX_ONLY
static int assertStartUpdateFromButton( char* labelLoad, char* labelSkip )
{
// Dummy function, see checkSDUpdaterUI() or its caller to override
return -1;
}
// TODO: consexpr 'tft'
#else
#ifndef tft
#define undef_tft
#define tft M5.Lcd
#endif
static int assertStartUpdateFromButton( char* labelLoad, char* labelSkip )
{
M5.update();
if( M5.BtnA.isPressed() ) return 1;
if( M5.BtnB.isPressed() ) return 0;
return -1;
}
#endif


#ifdef ARDUINO_ODROID_ESP32 // odroid has 4 buttons under the TFT
#define BUTTON_WIDTH 60
#define BUTTON_HWIDTH BUTTON_WIDTH/2 // 30
#define BUTTON_HEIGHT 28
static uint16_t SDUButtonsXOffset[4] = {
static int16_t SDUButtonsXOffset[4] = {
1, 72, 188, 260
};
static int16_t SDUButtonsYOffset[4] = {
0, 0, 0, 0
};
#else
#define BUTTON_WIDTH 60
#define BUTTON_HWIDTH BUTTON_WIDTH/2 // 30
#define BUTTON_HEIGHT 28
static uint16_t SDUButtonsXOffset[3] = {
static int16_t SDUButtonsXOffset[3] = {
31, 126, 221
};
static int16_t SDUButtonsYOffset[3] = {
0, 0, 0
};
#endif

struct BtnStyle {
Expand All @@ -70,6 +75,9 @@
uint16_t MsgFontFolor[2] = {TFT_WHITE, TFT_BLACK}; // foreground, background
};

BtnStyles DefaultBtnStyle;
static BtnStyles *userBtnStyle = nullptr;

static void SDMenuProgressUI( int state, int size );
//static void checkSDUpdaterUI( fs::FS &fs, String fileName, unsigned long waitdelay = 2000 );
static void DisplayUpdateUI( const String& label );
Expand Down Expand Up @@ -129,28 +137,55 @@
__attribute__((unused))
static void drawSDUMessage()
{
BtnStyles bs;
tft.setTextColor( bs.MsgFontFolor[0], bs.MsgFontFolor[1] );
tft.setTextSize( bs.MsgFontSize );
BtnStyles *bs = ( userBtnStyle == nullptr ) ? &DefaultBtnStyle : userBtnStyle;
tft.setTextColor( bs->MsgFontFolor[0], bs->MsgFontFolor[1] );
tft.setTextSize( bs->MsgFontSize );
tft.setCursor( tft.width()/2, 0 );
tft.setTextDatum( TC_DATUM );
tft.setTextFont( 0 );
tft.drawString( BTN_HINT_MSG, tft.width()/2, 0 );
}
__attribute__((unused))
static void drawSDUPushButton( const char* label, uint8_t position, uint16_t outlinecolor, uint16_t fillcolor, uint16_t textcolor ) {
BtnStyles bs;
BtnStyles *bs = ( userBtnStyle == nullptr ) ? &DefaultBtnStyle : userBtnStyle;
tft.setTextColor( textcolor, fillcolor );
tft.setTextSize( bs.FontSize );
tft.fillRoundRect( SDUButtonsXOffset[position], tft.height() - bs.height - 2, bs.width, bs.height, 3, fillcolor );
tft.drawRoundRect( SDUButtonsXOffset[position], tft.height() - bs.height - 2, bs.width, bs.height, 3, outlinecolor );
tft.drawCentreString( label, SDUButtonsXOffset[position] + bs.hwidth, tft.height() - bs.height + 4, 2 );
tft.setTextSize( bs->FontSize );
tft.fillRoundRect( SDUButtonsXOffset[position], tft.height() - bs->height - 2 - SDUButtonsYOffset[position], bs->width, bs->height, 3, fillcolor );
tft.drawRoundRect( SDUButtonsXOffset[position], tft.height() - bs->height - 2 - SDUButtonsYOffset[position], bs->width, bs->height, 3, outlinecolor );
tft.drawCentreString( label, SDUButtonsXOffset[position] + bs->hwidth, tft.height() - bs->height + 4 - SDUButtonsYOffset[position], 2 );
}


#if defined HAS_TOUCH || defined _M5Core2_H_ // ESP32-Chimera-Core (TODO: add LGFX_ONLY) touch support
#if defined LGFX_ONLY
__attribute__((unused))
static int assertStartUpdateFromPushButton( char* labelLoad, char* labelSkip, unsigned long waitdelay )
{
// Dummy function, see checkSDUpdaterUI() or its caller to override
return -1;
}
#else
__attribute__((unused))
static int assertStartUpdateFromPushButton( char* labelLoad, char* labelSkip, unsigned long waitdelay )
{
if( waitdelay > 100 ) {
freezeTextStyle();
drawSDUMessage();
BtnStyles btns;
drawSDUPushButton( labelLoad, 0, btns.Load.BorderColor, btns.Load.FillColor, btns.Load.TextColor );
drawSDUPushButton( labelSkip, 1, btns.Skip.BorderColor, btns.Skip.FillColor, btns.Skip.TextColor );
}
auto msec = millis();
do {
M5.update();
if( M5.BtnA.isPressed() ) return 1;
if( M5.BtnB.isPressed() ) return 0;
} while (millis() - msec < waitdelay);
return -1;
}
#endif

#define SDUpdaterAssertTrigger AnyTouchedButtonOf

#if defined HAS_TOUCH || defined _M5Core2_H_ // ESP32-Chimera-Core (TODO: add LGFX_ONLY) touch support

#if defined _M5Core2_H_
// use TFT_eSPI_Touch emulation from M5Core2.h
Expand Down Expand Up @@ -183,7 +218,6 @@

struct TouchButtonWrapper
{

bool iconRendered = false;

void handlePressed( SDU_TouchButton *btn, bool pressed, uint16_t x, uint16_t y)
Expand Down Expand Up @@ -237,10 +271,9 @@
IconSprite.deleteSprite();
}
}
}; // end struct TouchButtonWrapper

};

static int AnyTouchedButtonOf( char* labelLoad, char* labelSkip, unsigned long waitdelay=5000 )
static int assertStartUpdateFromTouchButton( char* labelLoad, char* labelSkip, unsigned long waitdelay=5000 )
{
/* auto &tft = M5.Lcd; */
if( waitdelay == 0 ) return -1;
Expand Down Expand Up @@ -324,10 +357,6 @@
return retval;
}

#else

#define SDUpdaterAssertTrigger assertStartUpdateFromButton

#endif // HAS_TOUCH

static void checkSDUpdaterUI( fs::FS &fs, String fileName, unsigned long waitdelay, const int TFCardCsPin )
Expand All @@ -341,13 +370,14 @@
}

#if defined HAS_TOUCH || defined _M5Core2_H_
if( SDUpdaterAssertTrigger==nullptr ) setAssertTrigger( &assertStartUpdateFromTouchButton );
// TODO: see if "touch/press" detect on boot is possible (spoil : NO)
// TODO: read signal from other (external?) buttons
if( waitdelay == 0 ) return; // don't check for touch signal if waitDelay = 0
if( waitdelay == 0 ) return; // don't check for any touch/button signal if waitDelay = 0
freezeTextStyle();
drawSDUMessage();
// bring up Touch UI as there are no buttons to click with
if( SDUpdaterAssertTrigger( isRollBack ? (char*)ROLLBACK_LABEL : (char*)LAUNCHER_LABEL, (char*)SKIP_LABEL ) == 1 ) {
if( SDUpdaterAssertTrigger( isRollBack ? (char*)ROLLBACK_LABEL : (char*)LAUNCHER_LABEL, (char*)SKIP_LABEL, waitdelay ) == 1 ) {
if( isRollBack == false ) {
Serial.printf( SDU_LOAD_TPL, fileName.c_str() );
updateFromFS( fs, fileName, TFCardCsPin );
Expand All @@ -357,44 +387,38 @@
rollBackUI();
}
}
// reset text styles to avoid messing with the overlayed application
thawTextStyle();
#else
if( !SDUpdaterAssertTrigger ) setAssertTrigger( &assertStartUpdateFromPushButton );
bool draw = false;
if( waitdelay == 0 ) {
if( waitdelay <= 100 ) {
// no UI draw, but attempt to detect "button is pressed on boot"
// also force some minimal delay
waitdelay = 100;
} else {
// only draw if waitdelay > 0
draw = true;
}

if( draw ) {
// show a hint
freezeTextStyle();
drawSDUMessage();
BtnStyles btns;
if( isRollBack ) {
drawSDUPushButton( ROLLBACK_LABEL, 0, btns.Load.BorderColor, btns.Load.FillColor, btns.Load.TextColor );
if( draw ) { // bring up the UI

}

if ( SDUpdaterAssertTrigger( isRollBack ? (char*)ROLLBACK_LABEL : (char*)LAUNCHER_LABEL, (char*)SKIP_LABEL, waitdelay ) == 1 ) {
if( isRollBack == false ) {
Serial.printf( SDU_LOAD_TPL, fileName.c_str() );
updateFromFS( fs, fileName, TFCardCsPin );
ESP.restart();
} else {
drawSDUPushButton( LAUNCHER_LABEL, 0, btns.Load.BorderColor, btns.Load.FillColor, btns.Load.TextColor );
Serial.println( SDU_ROLLBACK_MSG );
rollBackUI();
}
drawSDUPushButton( SKIP_LABEL, 1, btns.Skip.BorderColor, btns.Skip.FillColor, btns.Skip.TextColor );
}

auto msec = millis();
do {
if ( assertStartUpdateFromButton( isRollBack ? (char*)ROLLBACK_LABEL : (char*)LAUNCHER_LABEL, (char*)SKIP_LABEL ) == 1 ) {
if( isRollBack == false ) {
Serial.printf( SDU_LOAD_TPL, fileName.c_str() );
updateFromFS( fs, fileName, TFCardCsPin );
ESP.restart();
} else {
Serial.println( SDU_ROLLBACK_MSG );
rollBackUI();
}

}
} while (millis() - msec < waitdelay);

if( draw ) {
// reset text styles to avoid messing with the overlayed application
thawTextStyle();
}
#endif
Expand Down

0 comments on commit 91af010

Please sign in to comment.