Fast 7-segment number display for TFT

Here are the full conversions for all the Adafruit library users. Thanks Common_Ground.

I picked up one of these just to test and be sure they all worked. Also attached is a diagram that shows the pixel spacing for the numbers. The diagram should help because with really large leading zero blanked numbers, the actual displayed number often needs to be centered. One example is when displaying something like the day of the month in the center of the screen. The 31st, the 11th and the 1st should all be centered.

For those who don't know already, the way to do this is to first use the width function nD(11cS+2)-2cS to find what the width of the two digits will be for the size. Then use half of this as the xoffset from the center of the screen. So a 2 digit number at size 8 would be width 2(11x8+2)-16 or 164 pixels. Half of that would be 82 pixels so this is the amount to offset the width to start. So using xLoc as the center of the screen (120 for a 240 pixel width screen)...

draw7number(N, xLoc-82, yloc, 8, fC, bC, 2)

Now if you wanted even the # 1 to be centered as well as the number 11 or the number 31, you have to take a look at the number itself. Looking at the diagram, it works out that for half the pixel change for those numbersis 4 x cS pixels for numbers less than 20 and less than 2, plus an additional 2 x cS pixels for numbers less than 10.

draw7number(N, xLoc-82-((N<20)+(n<2))*20-(N<10)*10, yLoc, 8, fC, bC, -2)

This also exposes that the 5x and 7x scalers S2 and S4 could easily be changed on the 1st line of the function if someone wanted taller, shorter, fatter or skinnier numbers. All three scalers S2, S3 and S4 could also be adjusted down in fact if someone wanted really tiny numbers.

Hope this helps someone. :slight_smile:

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {
 
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
}


void loop(void) {
    draw7Number(millis() / 1000 ,10,10,4, ILI9341_WHITE , ILI9341_BLACK,2);        //LEFT2RIGHT
    draw7Number90(millis() / 1000 ,10,310,4, ILI9341_WHITE , ILI9341_BLACK,2);     //DOWN2UP
    draw7Number180(millis() / 1000 ,230,310,4, ILI9341_WHITE , ILI9341_BLACK,2);  //RIGHT2LEFT
    draw7Number270(millis() / 1000 ,230,10,4, ILI9341_WHITE , ILI9341_BLACK,2);    //UP2DOWN
}

/* Routine to Draw Large 7-Segment formated number with Arduino TFT Library
   Contributed by William Zaggle  (Uses TFT Library DrawLine and Fill Rectangle functions).

   int n - The number to be displayed
   int xLoc = The x location of the upper left corner of the number
   int yLoc = The y location of the upper left corner of the number
   int cS = The size of the number. 
   fC is the foreground color of the number
   bC is the background color of the number (prevents having to clear previous space)
   nD is the number of digit spaces to occupy (must include space for minus sign for numbers < 0).


    // Example to draw the number 37 in four directions in four corners of the display
    draw7Number(37,10,10,4, ILI9341_WHITE , ILI9341_BLACK,2);          //LEFT2RIGHT
    draw7Number90(37,10,310,4, ILI9341_WHITE , ILI9341_BLACK,2);     //DOWN2UP
    draw7Number180(37,230,310,4, ILI9341_WHITE , ILI9341_BLACK,2);  //RIGHT2LEFT
    draw7Number270(37,230,10,4, ILI9341_WHITE , ILI9341_BLACK,2);    //UP2DOWN
*/
void draw7Number(int n, unsigned int xLoc, unsigned int yLoc, char cS, unsigned int fC, unsigned int bC, char nD) {
  unsigned int num=abs(n),i,s,t,w,col,h,a,b,si=0,j=1,d=0,S2=5*cS,S3=2*cS,S4=7*cS,x1=cS+1,x2=S3+S2+1,y1=yLoc+x1,y3=yLoc+S3+S4+1;
  unsigned int seg[7][3]={{x1,yLoc,1},{x2,y1,0},{x2,y3+x1,0},{x1,(2*y3)-yLoc,1},{0,y3+x1,0},{0,y1,0},{x1,y3,1}};
  unsigned char nums[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67,0x00,0x40},c=(c=abs(cS))>10?10:(c<1)?1:c,cnt=(cnt=abs(nD))>10?10:(cnt<1)?1:cnt;
  for (xLoc+=cnt*(d=S2+(3*S3)+2);cnt>0;cnt--){
    for (i=(num>9)?num%10:((!cnt)&&(n<0))?11:((nD<0)&&(!num))?10:num,xLoc-=d,num/=10,j=0;j<7;++j){
      col=(nums[i]&(1<<j))?fC:bC;
      if (seg[j][2])for(w=S2,t=seg[j][1]+S3,h=seg[j][1]+cS,a=xLoc+seg[j][0]+cS,b=seg[j][1];b<h;b++,a--,w+=2)tft.drawFastHLine(a,b,w,col);
      else for(w=S4,t=xLoc+seg[j][0]+S3,h=xLoc+seg[j][0]+cS,b=xLoc+seg[j][0],a=seg[j][1]+cS;b<h;b++,a--,w+=2)tft.drawFastVLine(b,a,w,col);
      for (;b<t;b++,a++,w-=2)seg[j][2]?tft.drawFastHLine(a,b,w,col):tft.drawFastVLine(b,a,w,col);
    }
  }
}
  
void draw7Number90(int n, unsigned int xLoc, unsigned int yLoc, char cS, unsigned int fC, unsigned int bC, char nD) {
  unsigned int num=abs(n),i,s,t,w,col,h,a,b,si=0,j=1,d=0,S2=5*cS,S3=2*cS,S4=7*cS;
  unsigned int x1=cS+1,x2=S3+S2+1,y1=xLoc+x1,y3=xLoc+S3+S4+1;
  unsigned int seg[7][3]={{x1,xLoc,1},{x2,y1,0},{x2,y3+x1,0},{x1,(2*y3)-xLoc,1},{0,y3+x1,0},{0,y1,0},{x1,y3,1}};
  unsigned char nums[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67,0x00,0x40},c=(c=abs(cS))>10?10:(c<1)?1:c,cnt=(cnt=abs(nD))>10?10:(cnt<1)?1:cnt;
  for (yLoc-=cnt*(d=S2+(3*S3)+2);cnt>0;cnt--){
    for (  i=(num>9)?num%10:((!cnt)&&(n<0))?11:((nD<0)&&(!num))?10:num,yLoc+=d,num/=10,j=0;j<7;++j){
      col=(nums[i]&(1<<j))?fC:bC;
      if (seg[j][2])for(w=S2,t=seg[j][1]+S3,h=seg[j][1]+cS,a=yLoc-(seg[j][0]+cS+S2-1),b=seg[j][1];b<h;b++,a--,w+=2)tft.drawFastVLine(b,a,w,col);
      else for(w=S4,t=yLoc-seg[j][0]-S3,h=yLoc-seg[j][0]-cS,b=yLoc-seg[j][0],a=seg[j][1]+cS;b>h;b--,a--,w+=2)tft.drawFastHLine(a,b,w,col);
      for (;seg[j][2]?b<t:b>t;seg[j][2]?b++:b--,a++,w-=2)seg[j][2]?tft.drawFastVLine(b,a,w,col):tft.drawFastHLine(a,b,w,col);
    }
  }
}


void draw7Number180(int n, unsigned int xLoc, unsigned int yLoc, char cS, unsigned int fC, unsigned int bC, char nD) {
  unsigned int num=abs(n),i,s,t,w,col,h,a,b,si=0,j=1,d=0,S2=5*cS,S3=2*cS,S4=7*cS;
  unsigned int x1=cS,x2=S3+S2+1,y1=yLoc-x1,y3=yLoc-S3-S4-1;
  unsigned int seg[7][3]={{x1,yLoc,1},{x2,y1,0},{x2,y3-x1,0},{x1,(2*y3)-yLoc,1},{0,y3-x1,0},{0,y1,0},{x1,y3,1}};
  unsigned char nums[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67,0x00,0x40},c=(c=abs(cS))>10?10:(c<1)?1:c,cnt=(cnt=abs(nD))>10?10:(cnt<1)?1:cnt;
  for (xLoc-=cnt*(d=S2+(3*S3)+2);cnt>0;cnt--){
    for (i=(num>9)?num%10:((!cnt)&&(n<0))?11:((nD<0)&&(!num))?10:num,xLoc+=d,num/=10,j=0;j<7;++j){
      col=(nums[i]&(1<<j))?fC:bC;
      if (seg[j][2])for(w=S2,t=seg[j][1]-S3,h=seg[j][1]-cS,a=xLoc-(seg[j][0]+cS+S2),b=seg[j][1];b>h;b--,a--,w+=2)tft.drawFastHLine(a,b,w,col);
      else for(w=S4,t=xLoc-seg[j][0]-S3,h=xLoc-seg[j][0]-cS,b=xLoc-seg[j][0],a=seg[j][1]-cS-S4;b>h;b--,a--,w+=2)tft.drawFastVLine(b,a,w,col);
      for (;b>t;b--,a++,w-=2)seg[j][2]?tft.drawFastHLine(a,b,w,col):tft.drawFastVLine(b,a,w,col);
    }
  }
}

void draw7Number270(int n, unsigned int xLoc, unsigned int yLoc, char cS, unsigned int fC, unsigned int bC, char nD) {
  unsigned int num=abs(n),i,s,t,w,col,h,a,b,si=0,j=1,d=0,S2=5*cS,S3=2*cS,S4=7*cS;
  unsigned int x1=cS+1,x2=S3+S2+1,y1=xLoc-x1,y3=xLoc-S3-S4-1;
  unsigned int seg[7][3]={{x1,xLoc,1},{x2,y1,0},{x2,y3-x1,0},{x1,(2*y3)-xLoc,1},{0,y3-x1,0},{0,y1,0},{x1,y3,1}};
  unsigned char nums[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67,0x00,0x40},c=(c=abs(cS))>10?10:(c<1)?1:c,cnt=(cnt=abs(nD))>10?10:(cnt<1)?1:cnt;
  for (yLoc+=cnt*(d=S2+(3*S3)+2);cnt>0;cnt--){
    for (i=(num>9)?num%10:((!cnt)&&(n<0))?11:((nD<0)&&(!num))?10:num,yLoc-=d,num/=10,j=0;j<7;++j){
      col=(nums[i]&(1<<j))?fC:bC;
      if (seg[j][2])for(w=S2,t=seg[j][1]-S3,h=seg[j][1]-cS,a=yLoc+(seg[j][0]+cS),b=seg[j][1];b>h;b--,a--,w+=2)tft.drawFastVLine(b,a,w,col);
      else for(w=S4,t=yLoc+seg[j][0]+S3,h=yLoc+seg[j][0]+cS,b=yLoc+seg[j][0],a=seg[j][1]-cS-S4+1;b<h;b++,a--,w+=2)tft.drawFastHLine(a,b,w,col);
      for (;seg[j][2]?b>t:b<t;seg[j][2]?b--:b++,a++,w-=2)seg[j][2]?tft.drawFastVLine(b,a,w,col):tft.drawFastHLine(a,b,w,col);
    }
  }
}