@@ -667,103 +667,102 @@ void APPLOADER_INIT() {
667667void processKB_APPLOADER () {
668668 int currentMillis = millis ();
669669 String outPath = " " ;
670+ char inchar = 0 ;
670671
671672 switch (CurrentAppLoaderState) {
672673 case MENU :
674+ // 1. Drain the hardware buffer continuously at loop speed
675+ inchar = KB ().updateKeypress ();
676+
677+ // 2. Only process the actual input if the cooldown has expired
673678 if (currentMillis - KBBounceMillis >= KB_COOLDOWN ) {
674- char inchar = KB ().updateKeypress ();
675-
676679 if (inchar != 0 ) {
677- KBBounceMillis = currentMillis;
678- }
680+ KBBounceMillis = currentMillis;
679681
680- // HANDLE INPUTS
681- if (inchar == 0 ) {
682- // Do nothing
683- }
684- else if (inchar == 12 || inchar == 23 ) { // Home or App Switcher Kill Signal
682+ // HANDLE INPUTS
683+ if (inchar == 12 || inchar == 23 ) { // Home or App Switcher Kill Signal
685684 HOME_INIT ();
686- }
687- else if (inchar == ' a' || inchar == ' A' || inchar == ' 1' ) {
685+ }
686+ else if (inchar == ' a' || inchar == ' A' || inchar == ' 1' ) {
688687 selectedSlot = 1 ;
689688 CurrentAppLoaderState = SWAP_OR_EDIT ;
690689 KB ().setKeyboardState (NORMAL );
691- }
692- else if (inchar == ' b' || inchar == ' B' || inchar == ' 2' ) {
690+ }
691+ else if (inchar == ' b' || inchar == ' B' || inchar == ' 2' ) {
693692 selectedSlot = 2 ;
694693 CurrentAppLoaderState = SWAP_OR_EDIT ;
695694 KB ().setKeyboardState (NORMAL );
696- }
697- else if (inchar == ' c' || inchar == ' C' || inchar == ' 3' ) {
695+ }
696+ else if (inchar == ' c' || inchar == ' C' || inchar == ' 3' ) {
698697 selectedSlot = 3 ;
699698 CurrentAppLoaderState = SWAP_OR_EDIT ;
700699 KB ().setKeyboardState (NORMAL );
701- }
702- else if (inchar == ' d' || inchar == ' D' || inchar == ' 4' ) {
700+ }
701+ else if (inchar == ' d' || inchar == ' D' || inchar == ' 4' ) {
703702 selectedSlot = 4 ;
704703 CurrentAppLoaderState = SWAP_OR_EDIT ;
705704 KB ().setKeyboardState (NORMAL );
705+ }
706+ // All other keys are ignored in the MENU state
706707 }
707- // All other keys are ignored in the MENU state
708+ }
708709
709- currentMillis = millis ();
710- // Make sure oled only updates at OLED_MAX_FPS
711- if (currentMillis - OLEDFPSMillis >= (1000 /OLED_MAX_FPS )) {
712- OLEDFPSMillis = currentMillis;
713- OLED ().oledWord (" Choose slot: (A)(B)(C)(D)" );
714- }
710+ // 3. Update OLED at true OLED_MAX_FPS, completely independent of keyboard bounce
711+ currentMillis = millis ();
712+ if (currentMillis - OLEDFPSMillis >= (1000 /OLED_MAX_FPS )) {
713+ OLEDFPSMillis = currentMillis;
714+ OLED ().oledWord (" Choose slot: (A)(B)(C)(D)" );
715715 }
716716 break ;
717717
718718 case SWAP_OR_EDIT :
719- if (currentMillis - KBBounceMillis >= KB_COOLDOWN ) {
720- char inchar = KB ().updateKeypress ();
719+ // 1. Drain the hardware buffer continuously at loop speed
720+ inchar = KB ().updateKeypress ();
721721
722+ // 2. Only process the actual input if the cooldown has expired
723+ if (currentMillis - KBBounceMillis >= KB_COOLDOWN ) {
722724 if (inchar != 0 ) {
723- KBBounceMillis = currentMillis;
724- }
725+ KBBounceMillis = currentMillis;
725726
726- if (inchar == 0 ) {
727- // Do nothing
728- }
729- else if (inchar == 12 || inchar == 23 ) { // Home or App Switcher Kill Signal
730- selectedSlot = 0 ;
731- CurrentAppLoaderState = MENU ;
732- newState = true ; // Trigger e-ink redraw of the menu
733- }
734- else if (inchar == ' S' || inchar == ' s' || inchar == ' !' ) {
735- CurrentAppLoaderState = SWAP ;
736- }
737- else if (inchar == ' D' || inchar == ' d' || inchar == ' $' ) {
738- // Clear the slot
739- prefs.begin (" PocketMage" , false );
740- prefs.remove ((" OTA" + String (selectedSlot)).c_str ());
741- prefs.end ();
742-
743- const esp_partition_t *partition =
744- esp_partition_find_first (ESP_PARTITION_TYPE_APP ,
745- (esp_partition_subtype_t )(ESP_PARTITION_SUBTYPE_APP_OTA_MIN + selectedSlot),
746- nullptr );
747-
748- if (partition) {
749- esp_err_t err = esp_partition_erase_range (partition, 0 , partition->size );
750- if (err == ESP_OK ) {
751- Serial.printf (" OTA_%d erased\n " , selectedSlot);
752- }
727+ if (inchar == 12 || inchar == 23 ) { // Home or App Switcher Kill Signal
728+ selectedSlot = 0 ;
729+ CurrentAppLoaderState = MENU ;
730+ newState = true ; // Trigger e-ink redraw of the menu
731+ }
732+ else if (inchar == ' S' || inchar == ' s' || inchar == ' !' ) {
733+ CurrentAppLoaderState = SWAP ;
753734 }
735+ else if (inchar == ' D' || inchar == ' d' || inchar == ' $' ) {
736+ // Clear the slot
737+ prefs.begin (" PocketMage" , false );
738+ prefs.remove ((" OTA" + String (selectedSlot)).c_str ());
739+ prefs.end ();
740+
741+ const esp_partition_t *partition =
742+ esp_partition_find_first (ESP_PARTITION_TYPE_APP ,
743+ (esp_partition_subtype_t )(ESP_PARTITION_SUBTYPE_APP_OTA_MIN + selectedSlot),
744+ nullptr );
745+
746+ if (partition) {
747+ esp_err_t err = esp_partition_erase_range (partition, 0 , partition->size );
748+ if (err == ESP_OK ) {
749+ Serial.printf (" OTA_%d erased\n " , selectedSlot);
750+ }
751+ }
754752
755- OLED ().sysMessage (" App removed" , 2000 );
753+ OLED ().sysMessage (" App removed" , 2000 );
756754
757- newState = true ;
758- CurrentAppLoaderState = MENU ;
755+ newState = true ;
756+ CurrentAppLoaderState = MENU ;
757+ }
759758 }
759+ }
760760
761- currentMillis = millis ();
762- // Make sure oled only updates at OLED_MAX_FPS
763- if (currentMillis - OLEDFPSMillis >= (1000 /OLED_MAX_FPS )) {
764- OLEDFPSMillis = currentMillis;
765- OLED ().oledWord (" (S)wap app or (D)elete app" );
766- }
761+ // 3. Update OLED at true OLED_MAX_FPS, completely independent of keyboard bounce
762+ currentMillis = millis ();
763+ if (currentMillis - OLEDFPSMillis >= (1000 /OLED_MAX_FPS )) {
764+ OLEDFPSMillis = currentMillis;
765+ OLED ().oledWord (" (S)wap app or (D)elete app" );
767766 }
768767 break ;
769768
0 commit comments