Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Fonts

  1. #1

    Fonts

    I have a sketch that has a scoreboard with count-down clock to display on an Adafruit 240x320 GLCD (It's a TFT but I don't use as such) I'm using Adafruit GFX and the ILI9341 library ( #include <Adafruit_ILI9341.h>) and a Teensy 3.2.

    I want to replace the blocky size 7 regular installed font with something "crispier" and found the Teensy ILI9341_t3 library has what I want: #include <font_ArialBlack.h>.

    My sketch which includes static text, a MP3 sound player, SD card bitmap display for graphics and scores that can be incremented, WORKS FINE with the <Adafruit_ILI9341.h> but I get a ton of errors when I try the Teensy ILI9341_t3 library.

    I've run the Teensy (3.2) example program in the Teensy ILI9341_t3 library on this same display and it works fine. So there's a disconnect between the two libraries. I've tried to use both libraries, using two different object names, among other things. Should I just try using the font_ArialBlack.h with the Adafruit ILI9341 library? (I've tried to use it "raw" but it doesn't work, so I may have to run it though the Adafruit font converter.

    Before I post the sketch (360 lines) or the myriad of errors I get, I thought I would ASK FIRST to see if there is a quick solution since someone must know how both these libraries work better than me and perhaps come across these same issues.

    Any comments?

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,219
    Yes - At one point both libraries started with pretty compatible stuff. But then both continued to evolve independent of each other.
    Likewise I have the ili9341_t3n library, which is a supper set of the ili9341_t3 library.

    For example the Adafruit added something later I think was called a canvas, which is not implemented in either of our libraries.
    Mine has the concept of a frame buffer...

    So none of them are complete replacements for the other. But in some cases they have the same capabilities done different ways. So without knowing what errors you are receiving hard to say.

    Now as far as Fonts are concerned:

    Adafruit library with GFX also has library of fonts. Not sure if any of them meet your needs or not. Note: the ILI9341_t3 library only is setup to use the ILI.. fonts. My ILI9341_t3n is setup to allow either ILI or GFX fonts

    But again without additional information hard to know what you are running into.

  3. #3
    This is good information since I thought any improvements to any library would be backward compatible. Otherwise there should be a totally different naming scheme.
    It sounds like the ILI9341_T3N library could work. I don't really need the Adafruit library except for the fact I started with it and feel stuck with it.
    One error I remembered when I compiled with the ILI9341_T3 library was "keyword set font() not a class member" or something similar to that. These libraries are not very well documented at the front end (before users download them)...maybe they are in the .h and .cpp files but that's getting too hairy!
    Here's my code that compiles for a Teensy 3.2 with the ILI9341 library from Adafruit. Errors when the ILI9341_T3 library is used. I want to pop in a new font in the function "UpdateTimeDisplay".

    Code:
        /***************************************************
            Name: RobDioramaTeensySDV25BETA   Use for testing/flogging, then copy to new version
            By:            
            Start Date:    29Apr21
            Last Rev:      18Jul21
            MCU:           Teensy3.2
            Hardware:      Teensy3.2, Adafruit GLCD (TFT), Aideepen MP3 player module
            Description:   Using GLCD/TFT for hockey scoreboard for hockey diorama
                           GLCD code and GFX library from Adafruit
                           Modified timer code from Odometer
                           Touch screen (TFT) only used as screen, not touch-enabled
            Vers History: V1.0   Start
                          V1.1   Added score rectangles, added credits
                          V1.2   Added pb for scores
                          V1.3   Added debounce library, used for pb switches and code to put scores in boxes
                          V2.0   Replaced Arduino UNO with Teensy 3.2. Using Adafruit, not Alan Senior library
                                 Uses tft.print(buf) instead of tft.drawString(buf, x, y, size) which has been deprecated
                          V2.2   Added FE logo function.
                                 (Added SD card to display bitmaps on screen, not working)
                          V2.3   Beta  SD card displaying bitmaps on key press.
                          V2.4   Sound module and amplifier added
                                 GLCD stopped working.  Replaced with Adafruit GLCD with integral SD card
                          V2.5   Added pushbuttons to select function
                                 Added interrupt service routine, using pin 5 ("score") to reset Teensy if in slideshow
                                 Added Aideepen Sound module to play MP3 SFX through amp module
                 
        */ 
    /*******************************************************************/
       
        #include <Adafruit_GFX.h>
        #include <Adafruit_ILI9341.h>
        GFXcanvas1 canvas(320,240);
        //#include <ILI9341_t3.h>
        //#include <font_ArialBlack.h>
        #include <SPI.h>
        #include <SD.h>
        #include <ezButton.h>//debounce library
        //#include <Fonts/Dialog_plain_16.h>//Custom font conversion at http://oleddisplay.squix.ch/
        //#include <Fonts/Open_24_Display_St20pt7b.h>
        #define TFT_DC  10
        #define TFT_CS  15
        #define TFT_RST 9
        #define SD_CS   20  //chip select for SD card standard SPI pins MOSI 11, SCK 13 in library
        /************Defines for Aideepen MP3 Sound Card***********************/
        #include <SoftwareSerial.h>
        #define Teensy_RX 0//connect to Tx of module
        #define Teensy_TX 1//connect to Rx of module
        SoftwareSerial mySerial(Teensy_RX, Teensy_TX);
        static int8_t Send_buf[8] = {0} ;
        #define CMD_SEL_DEV 0X09
        #define DEV_TF 0X02
        #define CMD_PLAY_W_VOL 0X22
        // SFX stolen from the web, voice using free Text to Speech converter
        #define charge 0x1702//SFX, next five
        #define horn 0x1704
        #define neverbehind 0x1701//not implemented
        #define oneminute 0x1703
        #define notallowed 0x1705//not implemented
        int x = 0; //variable to update interrupt for scoreboard reset
        ezButton canpb(2);//this is D2, not pin 2 - actually pin 4
        ezButton oilpb(3);//D3, pin 5
        ezButton slide(4);//D4, pin 6
        ezButton score(5);//D5, pin 7//interrupt is on this pin.  All digital pins on Teensy have interrupt capability
        
        Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
        //ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC,TFT_RST);
        //Countdown variables
        int countDirection = -1; // direction of count: 1 for up, -1 for down, 0 for stopped
        int nowMinutes=1; // "minutes" part of time
        int nowSeconds=30; // "seconds" part of time
        unsigned long millisNow = 0; // value of millis() at most recent 1/10 second
        int setmin = nowMinutes;//needed for reset
        int setsec = nowSeconds;
        const unsigned long millisTick = 1000; // number of milliseconds per 1/10 second
        int countCan = 0; //reset to zero every power cycle
        int countOil = 0;
        /***********************Setup***********************************/
        void setup(void) {
          Serial.begin(9600);//for troubleshooting
          mySerial.begin(9600);//for MP3 play
          delay(500);//Wait chip initialization is complete
          sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
          delay(200);//wait for 200ms
          attachInterrupt(5, Reset, FALLING);//this is used to reset Teensy using pin 5
          canpb.setDebounceTime(50); // set debounce time to 50 milliseconds
          oilpb.setDebounceTime(50);
          canpb.setCountMode(COUNT_RISING);
          oilpb.setCountMode(COUNT_RISING);
          tft.begin();
          if (!SD.begin(SD_CS))//check of SD card is available
          { Serial.println("failed!"); }
          Serial.println("OK!");
          tft.setRotation(3);//can't use with slideshow
          Scoreboard();   //static text, run once, stay on.
          sendCommand(CMD_PLAY_W_VOL, charge);
          delay(4000);
          //credits();//credits for the design, start by switch?  Maybe existing PB, held down to activate
        }
        /*****************************Loop******************************/
        void loop() {
          canpb.loop(); // MUST call the loop() function first for debounce switches
          oilpb.loop();
          slide.loop();
          score.loop();
          //int canpbState = canpb.getState();
         // int oilpbState = oilpb.getState();
          int slideState = slide.getState();
          int scoreState = score.getState();
          if (slideState == LOW)//choose slideshow or scoreboard button
            Slideshow();
          else if (scoreState == LOW)
          { tft.setRotation(3);
            Scoreboard();
          }
          int countCan = canpb.getCount();
          int countOil = oilpb.getCount();
          //if (countOil >= countCan)
          //sendCommand(CMD_PLAY_W_VOL, notallowed);
          //delay (3000);
         // countOil=countOil--;
          tft.setTextSize(4);
          tft.setCursor(70, 105); //put score in Montreal box
          tft.println(countCan);
          tft.setCursor(240, 105); //put score in Oilers box
          tft.println(countOil); 
          
          //Start Countdown
          if ((millis() - millisNow) >= millisTick) {
            nowSeconds += countDirection;
            millisNow += millisTick;
            // trade 60 seconds for 1 minute
            if (nowSeconds >= 60) {
              nowSeconds -= 60;//remove 60 seconds
              nowMinutes++;//add one minute
            }
            // trade 1 minute for 60 seconds
            if (nowSeconds < 0) {
              nowMinutes--;//remove minute
              nowSeconds += 60;
            }//add 60 seconds
          }
          if ((nowMinutes == 1) && (nowSeconds == 0)) {
            sendCommand(CMD_PLAY_W_VOL, oneminute);//"1 minute to play" SFX
          }
        
          //countdown is over
          if ((nowMinutes == 0) && (nowSeconds == 0)) {
            delay(100);
            nowMinutes = setmin;
            nowSeconds = setsec;
            delay (500);
            sendCommand(CMD_PLAY_W_VOL, horn);//time up, sound horn
            delay(3000);
          }
          updateTimeDisplay();
        }
        /********************sendCommand function for MP3 sound card*****************/
        void sendCommand(int8_t command, int16_t dat)
        { delay(20);
          Send_buf[0] = 0x7e; //starting byte
          Send_buf[1] = 0xff; //version
          Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
          Send_buf[3] = command; //
          Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
          Send_buf[5] = (int8_t)(dat >> 8);//datah
          Send_buf[6] = (int8_t)(dat); //datal
          Send_buf[7] = 0xef; //ending byte
          for (uint8_t i = 0; i < 8; i++) //
          { mySerial.write(Send_buf[i]) ; }
        }
       /*********************ISR Reset**********************************/
        void Reset() {
          SCB_AIRCR = 0x05FA0004;//PB on pin D5 gets us here to reset MCU
        }
        /********************Function Scoreboard************************/
       void Scoreboard() {//all static, run once at startup Note: was unsigned long instead of void
          //tft.setFont(&Dialog_plain_16);//try different fonts
          //tft.setFont (&Roboto_Medium_11);
          tft.fillScreen(ILI9341_BLACK);
          tft.setTextColor(ILI9341_CYAN);
          tft.setTextSize(4);//def 4 for default font
          tft.setCursor(0, 0); //x,y
          tft.println(" FOUND FORUM");
          tft.setTextColor(ILI9341_GREEN);
          tft.setTextSize(3);//def 3 for default font
          tft.setCursor(0, 40); //x,y
          tft.println("Canadiens  Oilers");
          //tft.setFont();//reset font. Use when using non default fonts
          //Draw rectangles for scores
          tft.drawRect(50, 90, 70, 50, ILI9341_RED); //(x,y,w,h,color) Canadiens on left
          tft.drawRect(220, 90, 70, 50, ILI9341_RED); //Oilers right
          tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
          //tft.setTextSize(3);
          //return 0;
        }
        /************************Function UpdateTimeDisplay****************/
        void updateTimeDisplay () {
          char buf[8];
          //tft.setFont(&Open_24_Display_St20pt7b);
          //tft.setFont (&DSEG7_Classic_Mini_Regular_18);//seven segment font not updated
          //tft.setFont (&DSEG7_Modern_Regular_18);
          //tft.setFont(ArialBlack_60);
          tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); //need black background or letters pile up
          tft.setCursor(-20, 170); //x,y was -40,230 for open_24 font
          tft.setTextSize(7);//def 7 for large regular font
          sprintf(buf, "  %02d:%02d", nowMinutes, nowSeconds);
           tft.print(buf);
          //tft.setTextSize(3);//reset for score
          tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);//reset for score
        }
        /*****************************Function Slideshow************************/
        void Slideshow()
        { tft.fillScreen(ILI9341_BLACK);
          bmpDraw("Goalie.bmp", 0, 0); //okay
          delay (5000);
        
          tft.fillScreen(ILI9341_BLACK);
          bmpDraw("RobChris.bmp", 0, 0);//okay
          delay (5000);
        
          tft.fillScreen(ILI9341_BLACK);
          bmpDraw("RobBob.bmp", 0, 0);//okay
          delay (5000);
          tft.fillScreen(ILI9341_BLACK);
        
          tft.fillScreen(ILI9341_BLACK);
          bmpDraw("FElogo.bmp", 0, 0);//okay
          delay (5000);
          tft.fillScreen(ILI9341_BLACK);
        }
        #define BUFFPIXEL 40 //increased from 20   
        /*********************Function: draw bitmaps on GLCD*************************/
        void bmpDraw(char *filename, uint8_t x, uint16_t y) {
          File     bmpFile;
          int      bmpWidth, bmpHeight;   // W+H in pixels
          uint8_t  bmpDepth;              // Bit depth (currently must be 24)
          uint32_t bmpImageoffset;        // Start of image data in file
          uint32_t rowSize;               // Not always = bmpWidth; may have padding
          uint8_t  sdbuffer[3 * BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
          uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
          boolean  goodBmp = false;       // Set to true on valid header parse
          boolean  flip    = true;        // BMP is stored bottom-to-top
          int      w, h, row, col;
          uint8_t  r, g, b;
          uint32_t pos = 0, startTime = millis();
        
          if ((x >= tft.width()) || (y >= tft.height())) return;
        //All print commands display on monitor if connected.  Not needed here but good for troubleshooting
          Serial.println();
          Serial.print(F("Loading image '"));
          Serial.print(filename);
          Serial.println('\'');
        
          // Open requested file on SD card
          if ((bmpFile = SD.open(filename)) == NULL) {
            Serial.print(F("File not found"));
            return;
          }
          // Parse BMP header
          if (read16(bmpFile) == 0x4D42) { // BMP signature
            Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
            (void)read32(bmpFile); // Read & ignore creator bytes
            bmpImageoffset = read32(bmpFile); // Start of image data
            Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
            // Read DIB header
            Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
            bmpWidth  = read32(bmpFile);
            bmpHeight = read32(bmpFile);
            if (read16(bmpFile) == 1) { // # planes -- must be '1'
              bmpDepth = read16(bmpFile); // bits per pixel
              Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
              if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
        
                goodBmp = true; // Supported BMP format -- proceed!
                Serial.print(F("Image size: "));
                Serial.print(bmpWidth);
                Serial.print('x');
                Serial.println(bmpHeight);
        
                // BMP rows are padded (if needed) to 4-byte boundary
                rowSize = (bmpWidth * 3 + 3) & ~3;
                if (bmpHeight < 0) {
                  bmpHeight = -bmpHeight;
                  flip      = false;
                }
        
                // Crop area to be loaded
                w = bmpWidth;
                h = bmpHeight;
                if ((x + w - 1) >= tft.width())  w = tft.width()  - x;
                if ((y + h - 1) >= tft.height()) h = tft.height() - y;
        
                // Set TFT address window to clipped image bounds
                tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
        
                for (row = 0; row < h; row++) { // For each scanline...
                  if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
                    pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
                  else     // Bitmap is stored top-to-bottom
                    pos = bmpImageoffset + row * rowSize;
                  if (bmpFile.position() != pos) { // Need seek?
                    bmpFile.seek(pos);
                    buffidx = sizeof(sdbuffer); // Force buffer reload
                  }
        
                  for (col = 0; col < w; col++) { // For each pixel...
                    if (buffidx >= sizeof(sdbuffer)) { // Read more pixel data
                      bmpFile.read(sdbuffer, sizeof(sdbuffer));
                      buffidx = 0; // Set index to beginning
                    }
        
                    // Convert pixel from BMP to TFT format, push to display
                    b = sdbuffer[buffidx++];
                    g = sdbuffer[buffidx++];
                    r = sdbuffer[buffidx++];
                    tft.pushColor(tft.color565(r, g, b));
                  } // end pixel
                } // end scanline
                Serial.print(F("Loaded in "));
                Serial.print(millis() - startTime);
                Serial.println(" ms");
              } // end goodBmp
            }
          }
          bmpFile.close();
          if (!goodBmp) Serial.println(F("BMP format not recognized."));
        }
        uint16_t read16(File &f) {
          uint16_t result;
          ((uint8_t *)&result)[0] = f.read(); // LSB
          ((uint8_t *)&result)[1] = f.read(); // MSB
          return result;
        }
        uint32_t read32(File &f) {
          uint32_t result;
          ((uint8_t *)&result)[0] = f.read(); // LSB
          ((uint8_t *)&result)[1] = f.read();
          ((uint8_t *)&result)[2] = f.read();
          ((uint8_t *)&result)[3] = f.read(); // MSB
          return result;
        }

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,219
    Note this compiles with ILI9341_t3n...
    I did edit one of your functions that was giving compile warnings of converting strings to char *
    (Just added const to parameter...)

    Note: I did not look over it much but there may be problems with how it is drawing the bitmaps... You may want to look at the updated examples in the library that hopefully get around the issue.


    Code:
    /***************************************************
         Name: RobDioramaTeensySDV25BETA   Use for testing/flogging, then copy to new version
         By:
         Start Date:    29Apr21
         Last Rev:      18Jul21
         MCU:           Teensy3.2
         Hardware:      Teensy3.2, Adafruit GLCD (TFT), Aideepen MP3 player module
         Description:   Using GLCD/TFT for hockey scoreboard for hockey diorama
                        GLCD code and GFX library from Adafruit
                        Modified timer code from Odometer
                        Touch screen (TFT) only used as screen, not touch-enabled
         Vers History: V1.0   Start
                       V1.1   Added score rectangles, added credits
                       V1.2   Added pb for scores
                       V1.3   Added debounce library, used for pb switches and code to put scores in boxes
                       V2.0   Replaced Arduino UNO with Teensy 3.2. Using Adafruit, not Alan Senior library
                              Uses tft.print(buf) instead of tft.drawString(buf, x, y, size) which has been deprecated
                       V2.2   Added FE logo function.
                              (Added SD card to display bitmaps on screen, not working)
                       V2.3   Beta  SD card displaying bitmaps on key press.
                       V2.4   Sound module and amplifier added
                              GLCD stopped working.  Replaced with Adafruit GLCD with integral SD card
                       V2.5   Added pushbuttons to select function
                              Added interrupt service routine, using pin 5 ("score") to reset Teensy if in slideshow
                              Added Aideepen Sound module to play MP3 SFX through amp module
    
    */
    /*******************************************************************/
    
    //#include <Adafruit_GFX.h>
    //#include <Adafruit_ILI9341.h>
    //GFXcanvas1 canvas(320, 240);
    #include <ILI9341_t3n.h>
    //#include <font_ArialBlack.h>
    #include <SPI.h>
    #include <SD.h>
    #include <ezButton.h>//debounce library
    //#include <Fonts/Dialog_plain_16.h>//Custom font conversion at http://oleddisplay.squix.ch/
    //#include <Fonts/Open_24_Display_St20pt7b.h>
    #define TFT_DC  10
    #define TFT_CS  15
    #define TFT_RST 9
    #define SD_CS   20  //chip select for SD card standard SPI pins MOSI 11, SCK 13 in library
    /************Defines for Aideepen MP3 Sound Card***********************/
    #include <SoftwareSerial.h>
    #define Teensy_RX 0//connect to Tx of module
    #define Teensy_TX 1//connect to Rx of module
    SoftwareSerial mySerial(Teensy_RX, Teensy_TX);
    static int8_t Send_buf[8] = {0} ;
    #define CMD_SEL_DEV 0X09
    #define DEV_TF 0X02
    #define CMD_PLAY_W_VOL 0X22
    // SFX stolen from the web, voice using free Text to Speech converter
    #define charge 0x1702//SFX, next five
    #define horn 0x1704
    #define neverbehind 0x1701//not implemented
    #define oneminute 0x1703
    #define notallowed 0x1705//not implemented
    int x = 0; //variable to update interrupt for scoreboard reset
    ezButton canpb(2);//this is D2, not pin 2 - actually pin 4
    ezButton oilpb(3);//D3, pin 5
    ezButton slide(4);//D4, pin 6
    ezButton score(5);//D5, pin 7//interrupt is on this pin.  All digital pins on Teensy have interrupt capability
    
    //Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
    ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC,TFT_RST);
    //Countdown variables
    int countDirection = -1; // direction of count: 1 for up, -1 for down, 0 for stopped
    int nowMinutes = 1; // "minutes" part of time
    int nowSeconds = 30; // "seconds" part of time
    unsigned long millisNow = 0; // value of millis() at most recent 1/10 second
    int setmin = nowMinutes;//needed for reset
    int setsec = nowSeconds;
    const unsigned long millisTick = 1000; // number of milliseconds per 1/10 second
    int countCan = 0; //reset to zero every power cycle
    int countOil = 0;
    /***********************Setup***********************************/
    void setup(void) {
      Serial.begin(9600);//for troubleshooting
      mySerial.begin(9600);//for MP3 play
      delay(500);//Wait chip initialization is complete
      sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
      delay(200);//wait for 200ms
      attachInterrupt(5, Reset, FALLING);//this is used to reset Teensy using pin 5
      canpb.setDebounceTime(50); // set debounce time to 50 milliseconds
      oilpb.setDebounceTime(50);
      canpb.setCountMode(COUNT_RISING);
      oilpb.setCountMode(COUNT_RISING);
      tft.begin();
      if (!SD.begin(SD_CS))//check of SD card is available
      {
        Serial.println("failed!");
      }
      Serial.println("OK!");
      tft.setRotation(3);//can't use with slideshow
      Scoreboard();   //static text, run once, stay on.
      sendCommand(CMD_PLAY_W_VOL, charge);
      delay(4000);
      //credits();//credits for the design, start by switch?  Maybe existing PB, held down to activate
    }
    /*****************************Loop******************************/
    void loop() {
      canpb.loop(); // MUST call the loop() function first for debounce switches
      oilpb.loop();
      slide.loop();
      score.loop();
      //int canpbState = canpb.getState();
      // int oilpbState = oilpb.getState();
      int slideState = slide.getState();
      int scoreState = score.getState();
      if (slideState == LOW)//choose slideshow or scoreboard button
        Slideshow();
      else if (scoreState == LOW)
      { tft.setRotation(3);
        Scoreboard();
      }
      int countCan = canpb.getCount();
      int countOil = oilpb.getCount();
      //if (countOil >= countCan)
      //sendCommand(CMD_PLAY_W_VOL, notallowed);
      //delay (3000);
      // countOil=countOil--;
      tft.setTextSize(4);
      tft.setCursor(70, 105); //put score in Montreal box
      tft.println(countCan);
      tft.setCursor(240, 105); //put score in Oilers box
      tft.println(countOil);
    
      //Start Countdown
      if ((millis() - millisNow) >= millisTick) {
        nowSeconds += countDirection;
        millisNow += millisTick;
        // trade 60 seconds for 1 minute
        if (nowSeconds >= 60) {
          nowSeconds -= 60;//remove 60 seconds
          nowMinutes++;//add one minute
        }
        // trade 1 minute for 60 seconds
        if (nowSeconds < 0) {
          nowMinutes--;//remove minute
          nowSeconds += 60;
        }//add 60 seconds
      }
      if ((nowMinutes == 1) && (nowSeconds == 0)) {
        sendCommand(CMD_PLAY_W_VOL, oneminute);//"1 minute to play" SFX
      }
    
      //countdown is over
      if ((nowMinutes == 0) && (nowSeconds == 0)) {
        delay(100);
        nowMinutes = setmin;
        nowSeconds = setsec;
        delay (500);
        sendCommand(CMD_PLAY_W_VOL, horn);//time up, sound horn
        delay(3000);
      }
      updateTimeDisplay();
    }
    /********************sendCommand function for MP3 sound card*****************/
    void sendCommand(int8_t command, int16_t dat)
    { delay(20);
      Send_buf[0] = 0x7e; //starting byte
      Send_buf[1] = 0xff; //version
      Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
      Send_buf[3] = command; //
      Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
      Send_buf[5] = (int8_t)(dat >> 8);//datah
      Send_buf[6] = (int8_t)(dat); //datal
      Send_buf[7] = 0xef; //ending byte
      for (uint8_t i = 0; i < 8; i++) //
      {
        mySerial.write(Send_buf[i]) ;
      }
    }
    /*********************ISR Reset**********************************/
    void Reset() {
      SCB_AIRCR = 0x05FA0004;//PB on pin D5 gets us here to reset MCU
    }
    /********************Function Scoreboard************************/
    void Scoreboard() {//all static, run once at startup Note: was unsigned long instead of void
      //tft.setFont(&Dialog_plain_16);//try different fonts
      //tft.setFont (&Roboto_Medium_11);
      tft.fillScreen(ILI9341_BLACK);
      tft.setTextColor(ILI9341_CYAN);
      tft.setTextSize(4);//def 4 for default font
      tft.setCursor(0, 0); //x,y
      tft.println(" FOUND FORUM");
      tft.setTextColor(ILI9341_GREEN);
      tft.setTextSize(3);//def 3 for default font
      tft.setCursor(0, 40); //x,y
      tft.println("Canadiens  Oilers");
      //tft.setFont();//reset font. Use when using non default fonts
      //Draw rectangles for scores
      tft.drawRect(50, 90, 70, 50, ILI9341_RED); //(x,y,w,h,color) Canadiens on left
      tft.drawRect(220, 90, 70, 50, ILI9341_RED); //Oilers right
      tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
      //tft.setTextSize(3);
      //return 0;
    }
    /************************Function UpdateTimeDisplay****************/
    void updateTimeDisplay () {
      char buf[8];
      //tft.setFont(&Open_24_Display_St20pt7b);
      //tft.setFont (&DSEG7_Classic_Mini_Regular_18);//seven segment font not updated
      //tft.setFont (&DSEG7_Modern_Regular_18);
      //tft.setFont(ArialBlack_60);
      tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); //need black background or letters pile up
      tft.setCursor(-20, 170); //x,y was -40,230 for open_24 font
      tft.setTextSize(7);//def 7 for large regular font
      sprintf(buf, "  %02d:%02d", nowMinutes, nowSeconds);
      tft.print(buf);
      //tft.setTextSize(3);//reset for score
      tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);//reset for score
    }
    /*****************************Function Slideshow************************/
    void Slideshow()
    { tft.fillScreen(ILI9341_BLACK);
      bmpDraw("Goalie.bmp", 0, 0); //okay
      delay (5000);
    
      tft.fillScreen(ILI9341_BLACK);
      bmpDraw("RobChris.bmp", 0, 0);//okay
      delay (5000);
    
      tft.fillScreen(ILI9341_BLACK);
      bmpDraw("RobBob.bmp", 0, 0);//okay
      delay (5000);
      tft.fillScreen(ILI9341_BLACK);
    
      tft.fillScreen(ILI9341_BLACK);
      bmpDraw("FElogo.bmp", 0, 0);//okay
      delay (5000);
      tft.fillScreen(ILI9341_BLACK);
    }
    #define BUFFPIXEL 40 //increased from 20   
    /*********************Function: draw bitmaps on GLCD*************************/
    void bmpDraw(const char *filename, uint8_t x, uint16_t y) {
      File     bmpFile;
      int      bmpWidth, bmpHeight;   // W+H in pixels
      uint8_t  bmpDepth;              // Bit depth (currently must be 24)
      uint32_t bmpImageoffset;        // Start of image data in file
      uint32_t rowSize;               // Not always = bmpWidth; may have padding
      uint8_t  sdbuffer[3 * BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
      uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
      boolean  goodBmp = false;       // Set to true on valid header parse
      boolean  flip    = true;        // BMP is stored bottom-to-top
      int      w, h, row, col;
      uint8_t  r, g, b;
      uint32_t pos = 0, startTime = millis();
    
      if ((x >= tft.width()) || (y >= tft.height())) return;
      //All print commands display on monitor if connected.  Not needed here but good for troubleshooting
      Serial.println();
      Serial.print(F("Loading image '"));
      Serial.print(filename);
      Serial.println('\'');
    
      // Open requested file on SD card
      if ((bmpFile = SD.open(filename)) == NULL) {
        Serial.print(F("File not found"));
        return;
      }
      // Parse BMP header
      if (read16(bmpFile) == 0x4D42) { // BMP signature
        Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
        (void)read32(bmpFile); // Read & ignore creator bytes
        bmpImageoffset = read32(bmpFile); // Start of image data
        Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
        // Read DIB header
        Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
        bmpWidth  = read32(bmpFile);
        bmpHeight = read32(bmpFile);
        if (read16(bmpFile) == 1) { // # planes -- must be '1'
          bmpDepth = read16(bmpFile); // bits per pixel
          Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
          if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
    
            goodBmp = true; // Supported BMP format -- proceed!
            Serial.print(F("Image size: "));
            Serial.print(bmpWidth);
            Serial.print('x');
            Serial.println(bmpHeight);
    
            // BMP rows are padded (if needed) to 4-byte boundary
            rowSize = (bmpWidth * 3 + 3) & ~3;
            if (bmpHeight < 0) {
              bmpHeight = -bmpHeight;
              flip      = false;
            }
    
            // Crop area to be loaded
            w = bmpWidth;
            h = bmpHeight;
            if ((x + w - 1) >= tft.width())  w = tft.width()  - x;
            if ((y + h - 1) >= tft.height()) h = tft.height() - y;
    
            // Set TFT address window to clipped image bounds
            tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
    
            for (row = 0; row < h; row++) { // For each scanline...
              if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
                pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
              else     // Bitmap is stored top-to-bottom
                pos = bmpImageoffset + row * rowSize;
              if (bmpFile.position() != pos) { // Need seek?
                bmpFile.seek(pos);
                buffidx = sizeof(sdbuffer); // Force buffer reload
              }
    
              for (col = 0; col < w; col++) { // For each pixel...
                if (buffidx >= sizeof(sdbuffer)) { // Read more pixel data
                  bmpFile.read(sdbuffer, sizeof(sdbuffer));
                  buffidx = 0; // Set index to beginning
                }
    
                // Convert pixel from BMP to TFT format, push to display
                b = sdbuffer[buffidx++];
                g = sdbuffer[buffidx++];
                r = sdbuffer[buffidx++];
                tft.pushColor(tft.color565(r, g, b));
              } // end pixel
            } // end scanline
            Serial.print(F("Loaded in "));
            Serial.print(millis() - startTime);
            Serial.println(" ms");
          } // end goodBmp
        }
      }
      bmpFile.close();
      if (!goodBmp) Serial.println(F("BMP format not recognized."));
    }
    uint16_t read16(File &f) {
      uint16_t result;
      ((uint8_t *)&result)[0] = f.read(); // LSB
      ((uint8_t *)&result)[1] = f.read(); // MSB
      return result;
    }
    uint32_t read32(File &f) {
      uint32_t result;
      ((uint8_t *)&result)[0] = f.read(); // LSB
      ((uint8_t *)&result)[1] = f.read();
      ((uint8_t *)&result)[2] = f.read();
      ((uint8_t *)&result)[3] = f.read(); // MSB
      return result;
    }

  5. #5
    Loaded your library and, as you indicated, the sketch compiles. I fixed the warnings.
    I had some success loading two fonts created with Font Converter (http://oleddisplay.squix.ch/#/home) that created the style I wanted for GFX font library. The first one did a double strike to get "bold" but I didn't like it so tried another, created in the same fashion. This one was better but I cannot place it property on my display. It overwrites other text and my attempts to move it failed. At y value of 0, text is at top, at 100 it moves down, at 200 it's about middle, at 300 it stays where it was. negative values (as I use for x) do not work. Perhaps the rotation command has something to do with this. I'll try a couple more fonts. But I like your library because even though I put the font in the Adafruit_ILI9341 library, it was "discovered" by yours. So yeah, your's is definitely a super-set.

  6. #6
    Kurt, I was trying out the example programs in your library and getting numerous errors. Eg, in the program ILI_Ada_FontTest3 (or 4) I get these errors:
    I tired commenting out the offending font that wouldn't load but got errors on the next font. DemoSauce did not work. ILI_GFX Font test worked and so did the TFT_String_Align.

    Where does the library look for fonts? I've got them all over the place including in the Teensy hardware library (C:/programsx86...). When I was thrashing about, I was moving font files into the library I was currently TRYING to use. Should there be ONE, and ONLY ONE Font directory?


    Code:
    Arduino: 1.8.13 (Windows 10), TD: 1.53, Board: "Teensy 3.2 / 3.1, Serial, 96 MHz (overclock), Faster, US English"
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    C:\Users\bobfo\AppData\Local\Temp\arduino_modified_sketch_855607\ILI_Ada_FontTest3.ino:9:27: fatal error: font_OpenSans.h: No such file or directory
    
    Multiple libraries were found for "font_Arial.h"
    
    compilation terminated.
    
     Used: D:\ArduinoSketch\libraries\ILI9341_t3
    
     Not used: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\ILI9341_t3
    
    Multiple libraries were found for "SPI.h"
    
     Used: D:\ArduinoSketch\libraries\SPI
    
     Not used: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SPI
    
     Not used: D:\ArduinoSketch\libraries\SPITeensy
    
     Not used: D:\ArduinoSketch\libraries\SPI-master
    
    Error compiling for board Teensy 3.2 / 3.1.
    
    
    
    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,219
    You might want to check the Readme file for the library. There is a section on Font Support

    Some of the example sketches, such as the ILI_Ada_FontTest3 and ILI_Ada_FontTest4 may require an additional library of fonts to work.
    You can find this font library up at: https://github.com/mjs513/ILI9341_fonts
    This font library is setup, to create an archive file of all of the fonts, such that it won't pull in every font file in this directory,
    unlike some other libraries. Likewise it is setup to hopefully work with several of our libraries by conditionally including header files
    to try to match which display library you are using.

  8. #8
    Good news is that I found a font that works for me and displays properly on my 240x320 display.
    I wish ALL libraries were as well documented as yours. Adafruit documentation really sucks, sorry guys, but it does.
    Finally, now that I have the ILI9341-t3n loaded and in use, should I DELETE all the other ILI9341 libraries? My system has so many libraries the IDE takes a long time to load as it scans through the libraries for updates (which I may not need, since I don't use every library). I want to clean the whole mess up and get the fonts in one area.
    Thanks for your assistance thus far. It helped me out. Nice dog too.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •