3333
3434 */
3535
36+ /* maybe useful:
37+ * Optional SD Card connections:
38+ * MISO => GPIO 16 (2 for PICO-D4)
39+ * MOSI => GPIO 17 (12 for PICO-D4)
40+ * CLK => GPIO 14
41+ * CS => GPIO 13
42+ *
43+ * To change above assignment fill other paramaters of FileBrowser::mountSDCard().
44+ */
45+
3646#include " inputbox.h"
3747
3848
@@ -56,6 +66,14 @@ extern "C" {
5666#include " mconf.h"
5767#include " machine.h"
5868
69+ #include < iostream>
70+ #include < string>
71+
72+ FileBrowser fb (SD_MOUNT_PATH);
73+
74+ #define SPIFFS_MOUNT_PATH " /flash"
75+ #define FORMAT_ON_FAIL true
76+
5977using std::unique_ptr;
6078using fabgl::StringList;
6179using fabgl::imin;
@@ -88,9 +106,17 @@ IPAddress apIP(192, 168, 1, 1);
88106DNSServer dnsServer;
89107WebServer server (80 );
90108
91- const char * filename = " /posts.txt" ;
109+ const char * filename2 = " /posts.txt" ;
92110
93111
112+ // for the app JPGView():
113+ #include < TJpg_Decoder.h>
114+ #include < FS.h>
115+ #include " SPIFFS.h" // ESP32 only
116+ fabgl::VGA16Controller VGAController;
117+ // fabgl::VGAController VGAController; // dont show the complete image .jpg
118+ fabgl::Canvas cv (&VGAController);
119+
94120
95121
96122
@@ -296,7 +322,7 @@ bool downloadURL(char const * URL, FILE * file)
296322// return filename if successfully downloaded or already exist
297323char const * getDisk (char const * url)
298324{
299- FileBrowser fb (SD_MOUNT_PATH);
325+ // FileBrowser fb(SD_MOUNT_PATH);
300326
301327 char const * filename = nullptr ;
302328 if (url) {
@@ -378,7 +404,7 @@ void sendPage(){
378404
379405void sendMessages (){
380406 Serial.println (" GET /posts" );
381- File file = SPIFFS.open (filename , FILE_READ);
407+ File file = SPIFFS.open (filename2 , FILE_READ);
382408 if (!file){
383409 Serial.println (" - failed to open file for reading" );
384410 }
@@ -395,7 +421,7 @@ void receiveMessage(){
395421 Serial.println (" zero args?" );
396422 }
397423
398- File file = SPIFFS.open (filename , FILE_APPEND);
424+ File file = SPIFFS.open (filename2 , FILE_APPEND);
399425 if (!file){
400426 Serial.println (" - failed to open file for writing" );
401427 }
@@ -414,6 +440,147 @@ void receiveMessage(){
414440
415441
416442
443+ // for the app JPGView():
444+ void writePixel (int16_t x, int16_t y, uint16_t rgb565)
445+ {
446+ uint8_t r = ((rgb565 >> 11 ) & 0x1F ) * 255 / 31 ; // red 0 .. 255
447+ uint8_t g = ((rgb565 >> 5 ) & 0x3F ) * 255 / 63.0 ; // green 0 .. 255
448+ uint8_t b = (rgb565 & 0x1F ) * 255 / 31.0 ; // blue 0 .. 255
449+ cv.setPixel (x, y, RGB888 (r, g, b));
450+ }
451+
452+ // This next function will be called during decoding of the jpeg file to
453+ // render each block to the Canvas.
454+ bool vga_output (int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t * bitmap) {
455+ // Stop further decoding as image is running off bottom of screen
456+ if ( y >= cv.getHeight () ) return 0 ;
457+
458+ for (int16_t j = 0 ; j < h; j++, y++) {
459+ for (int16_t i = 0 ; i < w; i++) {
460+ writePixel (x + i, y, bitmap[j * w + i]);
461+ }
462+ }
463+
464+ // Return 1 to decode next block
465+ return 1 ;
466+ }
467+
468+ // show image jpg
469+ // code by https://github.com/fdivitto/FabGL/discussions/160#discussioncomment-1423074
470+ void ShowJPG (char * filename)
471+ {
472+ Serial.print (" filename: " );
473+ Serial.println (filename);
474+ fabgl::BitmappedDisplayController::queueSize = 1024 ; // deixou mais rápido, com mais 10 = extremamente lento (e não resolveu d mostrar tudo)
475+ // cv.waitCompletion(false);
476+ // cv.endUpdate();
477+ // cv.reset(); // pane com o de baixo
478+ // cv.resetPaintOptions(); // pane
479+ ibox.end ();
480+ VGAController.begin ();
481+ // VGAController.setResolution(VGA_640x480_60Hz, 512, 300);
482+ // VGAController.setResolution(VGA_512x300_60Hz);
483+ // VGAController.setResolution(VGA_400x300_60Hz);
484+ // VGAController.setResolution(VGA_512x384_60Hz, 512, 300);
485+ VGAController.setResolution (VGA_512x384_60Hz); // my monitor resolution is 1024 x 600
486+ VGAController.setProcessPrimitivesOnBlank (true );
487+ cv.setBrushColor (RGB888 (0 , 0 , 0 ));
488+ cv.clear ();
489+ // Serial.print("ho");
490+ // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
491+ TJpgDec.setJpgScale (1 );
492+ // Serial.print("directory: ");
493+ // Serial.println(directory); //'directory' was not declared in this scope
494+ // The decoder must be given the exact name of the rendering function above
495+ TJpgDec.setCallback (vga_output);
496+ // Time recorded for test purposes
497+ uint32_t t = millis ();
498+ // Serial.print("hiy3");
499+ // Get the width and height in pixels of the jpeg if you wish
500+ uint16_t w = 0 , h = 0 ;
501+ // strcpy(filename, filename2);
502+ // auto file = fb.openFile(filename, "wb");
503+ // strcpy(file, filename);
504+ // filename = std::to_string(file); //'to_string' is not a member of 'std'
505+ // filename = to_string(file); 'to_string' was not declared in this scope
506+ // TJpgDec.drawSdJpg(0, 0, filename);
507+ // fclose(file);
508+ // TJpgDec.getSdJpgSize(&w, &h, filename2); // Note name preceded with "/"
509+
510+ // Resize if possible: (down scale...)
511+ TJpgDec.getFsJpgSize (&w, &h, String (" /" )+filename);
512+ Serial.print (" Width = " ); Serial.print (w); Serial.print (" , height = " ); Serial.println (h);
513+ /* if (w < 320 and h < 240)
514+ {
515+ TJpgDec.setJpgScale(2);
516+ }
517+ else
518+ TJpgDec.setJpgScale(1); */
519+
520+ /* Resize if possible: (640x480)
521+ if (w > 5120 or h > 3840)
522+ TJpgDec.setJpgScale(8);
523+ else if (w > 2560 or h > 1920)
524+ TJpgDec.setJpgScale(4);
525+ else if (w > 640 or h > 480)
526+ TJpgDec.setJpgScale(2);
527+ else
528+ TJpgDec.setJpgScale(1); */
529+
530+ // Resize if possible: (512x300) // (for my monitor...)
531+ // if (w > 4096 or h > 2400)
532+ if (w > 4301 or h > 2520 ) // crop 5%
533+ TJpgDec.setJpgScale (8 );
534+ // if (w > 2048 or h > 1200)
535+ if (w > 2150 or h > 1260 ) // crop 5%
536+ // TJpgDec.setJpgScale(8);
537+ TJpgDec.setJpgScale (4 );
538+ // else if (w > 2048 or h > 1200)
539+ // else if (w > 1024 or h > 600)
540+ else if (w > 1075 or h > 630 ) // crop 5%
541+ // TJpgDec.setJpgScale(4);
542+ TJpgDec.setJpgScale (2 );
543+ // else if (w > 1024 or h > 600)
544+ // else if (w > 512 or h > 300)
545+ // else if (w > 538 or h > 315) //crop 5%
546+ // TJpgDec.setJpgScale(2);
547+ else
548+ TJpgDec.setJpgScale (1 );
549+
550+
551+ // Draw the image, top left at 0,0
552+ // TJpgDec.drawFsJpg(0, 0, filename); //file not found
553+ // TJpgDec.drawFsJpg(0, 0, "/panda.jpg"); // Ok
554+ // filename = "/" + filename; invalid operands of types 'const char [2]' and 'char*' to binary 'operator+'
555+ // filename = "/" += filename; invalid operands of types 'const char [2]' and 'char*' to binary 'operator+'
556+ // filename = '/' + filename; dont work
557+ Serial.print (" filename: " );
558+ Serial.println (filename);
559+ TJpgDec.drawFsJpg (0 , 0 , String (" /" )+filename);
560+ // TJpgDec.drawSdJpg(0, 0, filename); //file not found
561+ // TJpgDec.drawSdJpg(0, 0, "/moto.jpg"); //file not found
562+ // TJpgDec.drawSdJpg(0, 0, "SD/moto.jpg"); //file not found
563+ // TJpgDec.drawSdJpg(0, 0, "/SD/moto.jpg"); //file not found
564+ // TJpgDec.drawSdJpg(0, 0, "moto.jpg"); //file not found
565+ // TJpgDec.drawSdJpg(0, 0, "/panda.jpg".c_str()); // Jpeg file not found request for member 'c_str' in '"/panda.jpg"', which is of non-class type 'const char [11]'
566+ // TJpgDec.drawSdJpg(0, 0, "/moto.jpg"); //Jpeg file not found
567+ // TJpgDec.drawSdJpg(0, 0, "/moto.jpg"); // Jpeg file not found
568+
569+ // How much time did rendering take
570+ t = millis () - t;
571+ Serial.print (t); Serial.println (" ms" );
572+
573+ // take a keypress
574+ int scode = PS2Controller::keyboard ()->getNextScancode ();
575+
576+ // now user can choice another app:
577+ esp_restart ();
578+ /* while (1){
579+ t = millis();
580+ } */
581+ }
582+
583+
417584
418585
419586// App PCEmulator code
@@ -568,10 +735,10 @@ while (1)
568735void ChatterBox ()
569736{
570737 // initialize file (not totally sure this is necessary but YOLO)
571- File file = SPIFFS.open (filename , FILE_READ);
738+ File file = SPIFFS.open (filename2 , FILE_READ);
572739 if (!file){
573740 file.close ();
574- File file_write = SPIFFS.open (filename , FILE_WRITE);
741+ File file_write = SPIFFS.open (filename2 , FILE_WRITE);
575742 if (!file_write){
576743 Serial.println (" - failed to create file?!?" );
577744 }
@@ -610,7 +777,14 @@ void ChatterBox()
610777 // ib.setBackgroundColor(RGB888(0, 0, 0));
611778 // ib.onPaint = [&](Canvas * canvas) { drawInfo(canvas); };
612779 // ib.setAutoOK(0);
613- ibox.message (" Status" ," ChatterBox Started!" );
780+ // dnsServer.processNextRequest();
781+ // server.handleClient();
782+ // IPAddress IP = WiFi.softAPIP();
783+ // char capIP[16] = "";
784+ // strcpy(capIP, String(apIP));
785+ // char IP2[16] = "";
786+ // strcpy(IP2, String(IP));
787+ ibox.message (" Status" ," ChatterBox Started! Click 'Enter'." ,WiFi.softAPIP ().toString ().c_str (),WiFi.localIP ().toString ().c_str ());
614788 // ib.messageFmt("", nullptr," ", "ChatterBox Started!");
615789
616790
@@ -626,9 +800,48 @@ void ChatterBox()
626800
627801
628802
803+
804+ // App JPG View
805+ void JPGView ()
806+ {
807+
808+ // Browse Files
809+ // ibox.folderBrowser("Browse Files", SD_MOUNT_PATH);
810+ // break;
811+ // //////////////////////////////////////////////////
812+ // File Select
813+ if (SPIFFS_MOUNT_PATH) {
814+ char filename[16 ] = " /" ;
815+ // String filename;
816+ char directory[32 ];
817+ strcpy (directory, SPIFFS_MOUNT_PATH);
818+ if (ibox.fileSelector (" File Select" , " Filename: " , directory, sizeof (directory) - 1 , filename, sizeof (filename) - 1 ) == InputResult::Enter) {
819+ // if (ibox.fileSelector("File Select", "Filename: ", directory, sizeof(directory) - 1, filename, sizeof(filename)) == InputResult::Enter) {
820+ // directory += filename; - invalid use of non-lvalue array
821+ Serial.print (" directory: " );
822+ Serial.println (directory);
823+ // filename = "/" + filename; //invalid use of non-lvalue array
824+ // '/' += filename; invalid use of non-lvalue array
825+ // filename[16] = "/" + filename; invalid operands of types 'const char [2]' and 'char [16]' to binary 'operator+'
826+ // filename[16] = "/" += filename; invalid use of non-lvalue array
827+ Serial.print (" filename: " );
828+ Serial.println (filename);
829+ ShowJPG (filename);
830+ // delay(2000);
831+ }
832+
833+ // Serial.print("hi");
834+ }
835+ }
836+
837+
838+
839+
840+
841+
629842void setup ()
630843{
631- Serial.begin (115200 ); delay (500 ); printf (" \n\n\n Reset \n\n " );// DEBUG ONLY
844+ Serial.begin (115200 ); delay (500 ); printf (" \n\n\n Start \n\n " );// DEBUG ONLY
632845
633846 disableCore0WDT ();
634847 delay (100 ); // experienced crashes without this delay!
@@ -655,14 +868,15 @@ void setup()
655868
656869 esp_register_shutdown_handler (shutdownHandler);
657870
658- updateDateTime ();
871+ // updateDateTime();
659872
660873
661- // For App chatterbox :
662- if (!SPIFFS.begin (FORMAT_SPIFFS_IF_FAILED)){
874+ // Initialise SPIFFS :
875+ if (!SPIFFS.begin (FORMAT_SPIFFS_IF_FAILED,SPIFFS_MOUNT_PATH )){
663876 Serial.println (" SPIFFS Mount Failed" );
664877 return ;
665- }
878+ }
879+ FileBrowser::mountSPIFFS (FORMAT_ON_FAIL, SPIFFS_MOUNT_PATH);
666880
667881}
668882
@@ -691,11 +905,13 @@ void loop()
691905 // for (auto conf = mconf.getFirstItem(); conf; conf = conf->next)
692906 // dconfs.append(conf->desc);
693907 // dconfs.select(idx, true);
694-
908+ ibox. setAutoOK ( 0 );
695909 ibox.setupButton (0 , " PCEmulator" );
696910 ibox.setupButton (1 , " ChatterBox" );
697- auto r = ibox.select (" Applications list" , " Please select a application" , &dconfs, nullptr , " " );
698-
911+ ibox.setupButton (2 , " JPG View" );
912+ ibox.setupButton (3 , " Update time" );
913+ // auto r = ibox.select("Applications list", "Please select a application", &dconfs, nullptr, " ");
914+ auto r = ibox.select (" Applications list" , " Please select a application" , &dconfs, nullptr , nullptr );
699915 idx = dconfs.getFirstSelected ();
700916
701917 switch (r) {
@@ -707,6 +923,14 @@ void loop()
707923 // App ChatterBox
708924 ChatterBox ();
709925 break ;
926+ case InputResult::ButtonExt2:
927+ // App JPG View
928+ JPGView ();
929+ break ;
930+ case InputResult::ButtonExt3:
931+ // conect to internet and update date/time
932+ updateDateTime ();
933+ break ;
710934 case InputResult::Enter:
711935 showDialog = false ;
712936 break ;
0 commit comments