Demo of GP9002 VFD in grayscale mode

Dependencies:   Adafruit-GFX-Library-master Adafruit-GP9002-Grayscale-VFD-Library mbed

Fork of GP9002adafruit by Oliver Broad

Files at this revision

API Documentation at this revision

Comitter:
oliverb
Date:
Mon May 02 16:49:40 2016 +0000
Parent:
0:414a9e6fed37
Child:
2:efef4231b922
Commit message:
Adafruit_GFX appears to compile, looks as if it is a stream-ish object, but "print" is undefined and looks like it might be "puts"; ; I've given up on preserving Arduino headers;

Changed in this revision

Adafruit-GFX-Library-master/Adafruit_GFX.cpp Show annotated file Show diff for this revision Revisions of this file
Adafruit-GFX-Library-master/Adafruit_GFX.h Show annotated file Show diff for this revision Revisions of this file
Adafruit-GFX-Library-master/fontconvert/fontconvert.c Show diff for this revision Revisions of this file
Adafruit-GFX-Library-master/fontconvert/fontconvert.txt Show annotated file Show diff for this revision Revisions of this file
--- a/Adafruit-GFX-Library-master/Adafruit_GFX.cpp	Mon May 02 11:24:17 2016 +0000
+++ b/Adafruit-GFX-Library-master/Adafruit_GFX.cpp	Mon May 02 16:49:40 2016 +0000
@@ -31,11 +31,6 @@
 POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifdef __AVR__
- #include <avr/pgmspace.h>
-#elif defined(ESP8266)
- #include <pgmspace.h>
-#endif
 #include "Adafruit_GFX.h"
 #include "glcdfont.c"
 
@@ -466,12 +461,7 @@
   }
 }
 
-#if ARDUINO >= 100
-size_t Adafruit_GFX::write(uint8_t c) {
-#else
-void Adafruit_GFX::write(uint8_t c) {
-#endif
-
+int Adafruit_GFX::_putc(int c) {
   if(!gfxFont) { // 'Classic' built-in font
 
     if(c == '\n') {
@@ -516,10 +506,15 @@
     }
 
   }
-#if ARDUINO >= 100
   return 1;
-#endif
 }
+// get a single character (Stream implementation)
+int Adafruit_GFX::_getc() {
+    return -1;
+}
+
+
+
 
 // Draw a character
 void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
@@ -639,7 +634,7 @@
   textbgcolor = b;
 }
 
-void Adafruit_GFX::setTextWrap(boolean w) {
+void Adafruit_GFX::setTextWrap(bool w) {
   wrap = w;
 }
 
@@ -670,7 +665,7 @@
 // with the erroneous character indices.  By default, the library uses the
 // original 'wrong' behavior and old sketches will still work.  Pass 'true'
 // to this function to use correct CP437 character values in your code.
-void Adafruit_GFX::cp437(boolean x) {
+void Adafruit_GFX::cp437(bool x) {
   _cp437 = x;
 }
 
@@ -690,7 +685,7 @@
 }
 
 // Pass string and a cursor position, returns UL corner and W,H.
-void Adafruit_GFX::getTextBounds(char *str, int16_t x, int16_t y,
+void Adafruit_GFX::getTextBounds(const char *str, int16_t x, int16_t y,
  int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) {
   uint8_t c; // Current character
 
@@ -779,6 +774,7 @@
 }
 
 // Same as above, but for PROGMEM strings
+/*
 void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str,
  int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) {
   uint8_t *s = (uint8_t *)str, c;
@@ -866,7 +862,7 @@
 
   } // End classic vs custom font
 }
-
+*/
 // Return the size of the display (per current rotation)
 int16_t Adafruit_GFX::width(void) const {
   return _width;
@@ -876,7 +872,7 @@
   return _height;
 }
 
-void Adafruit_GFX::invertDisplay(boolean i) {
+void Adafruit_GFX::invertDisplay(bool i) {
   // Do nothing, must be subclassed if supported by hardware
 }
 
@@ -905,7 +901,7 @@
   _label[9] = 0;
 }
 
-void Adafruit_GFX_Button::drawButton(boolean inverted) {
+void Adafruit_GFX_Button::drawButton(bool inverted) {
   uint16_t fill, outline, text;
 
   if(!inverted) {
@@ -924,23 +920,23 @@
   _gfx->setCursor(_x - strlen(_label)*3*_textsize, _y-4*_textsize);
   _gfx->setTextColor(text);
   _gfx->setTextSize(_textsize);
-  _gfx->print(_label);
+  _gfx->puts(_label);
 }
 
-boolean Adafruit_GFX_Button::contains(int16_t x, int16_t y) {
+bool Adafruit_GFX_Button::contains(int16_t x, int16_t y) {
   if ((x < (_x - _w/2)) || (x > (_x + _w/2))) return false;
   if ((y < (_y - _h/2)) || (y > (_y + _h/2))) return false;
   return true;
 }
 
-void Adafruit_GFX_Button::press(boolean p) {
+void Adafruit_GFX_Button::press(bool p) {
   laststate = currstate;
   currstate = p;
 }
 
-boolean Adafruit_GFX_Button::isPressed() { return currstate; }
-boolean Adafruit_GFX_Button::justPressed() { return (currstate && !laststate); }
-boolean Adafruit_GFX_Button::justReleased() { return (!currstate && laststate); }
+bool Adafruit_GFX_Button::isPressed() { return currstate; }
+bool Adafruit_GFX_Button::justPressed() { return (currstate && !laststate); }
+bool Adafruit_GFX_Button::justReleased() { return (!currstate && laststate); }
 
 // -------------------------------------------------------------------------
 
--- a/Adafruit-GFX-Library-master/Adafruit_GFX.h	Mon May 02 11:24:17 2016 +0000
+++ b/Adafruit-GFX-Library-master/Adafruit_GFX.h	Mon May 02 16:49:40 2016 +0000
@@ -1,16 +1,11 @@
 #ifndef _ADAFRUIT_GFX_H
 #define _ADAFRUIT_GFX_H
 
-#if ARDUINO >= 100
- #include "Arduino.h"
- #include "Print.h"
-#else
- #include "WProgram.h"
-#endif
+#include "mbed.h"
 
 #include "gfxfont.h"
 
-class Adafruit_GFX : public Print {
+class Adafruit_GFX : public Stream {
 
  public:
 
@@ -28,7 +23,7 @@
     drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
     fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
     fillScreen(uint16_t color),
-    invertDisplay(boolean i);
+    invertDisplay(bool i);
 
   // These exist only with Adafruit_GFX (no subclass overrides)
   void
@@ -62,19 +57,27 @@
     setTextColor(uint16_t c),
     setTextColor(uint16_t c, uint16_t bg),
     setTextSize(uint8_t s),
-    setTextWrap(boolean w),
+    setTextWrap(bool w),
     setRotation(uint8_t r),
-    cp437(boolean x=true),
+    cp437(bool x=true),
     setFont(const GFXfont *f = NULL),
-    getTextBounds(char *string, int16_t x, int16_t y,
-      int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
-    getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y,
+    getTextBounds(const char *string, int16_t x, int16_t y,
       int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
-
-#if ARDUINO >= 100
-  virtual size_t write(uint8_t);
-#else
-  virtual void   write(uint8_t);
+/*    getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y,
+      int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); */
+#if DOXYGEN_ONLY
+    /** Write a character to the LCD
+     *
+     * @param c The character to write to the display
+     */
+    int putc(int c);
+ 
+    /** Write a formatted string to the LCD
+     *
+     * @param format A printf-style format string, followed by the
+     *               variables to use in formatting the string.
+     */
+    int printf(const char* format, ...);   
 #endif
 
   int16_t height(void) const;
@@ -97,11 +100,15 @@
   uint8_t
     textsize,
     rotation;
-  boolean
+  bool
     wrap,   // If set, 'wrap' text at right edge of display
     _cp437; // If set, use correct CP437 charset (default is off)
   GFXfont
     *gfxFont;
+// Stream implementation functions
+    virtual int _putc(int value);
+    virtual int _getc();
+
 };
 
 class Adafruit_GFX_Button {
@@ -111,13 +118,13 @@
   void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y,
    uint8_t w, uint8_t h, uint16_t outline, uint16_t fill,
    uint16_t textcolor, char *label, uint8_t textsize);
-  void drawButton(boolean inverted = false);
-  boolean contains(int16_t x, int16_t y);
+  void drawButton(bool inverted = false);
+  bool contains(int16_t x, int16_t y);
 
-  void press(boolean p);
-  boolean isPressed();
-  boolean justPressed();
-  boolean justReleased();
+  void press(bool p);
+  bool isPressed();
+  bool justPressed();
+  bool justReleased();
 
  private:
   Adafruit_GFX *_gfx;
@@ -127,16 +134,16 @@
   uint16_t _outlinecolor, _fillcolor, _textcolor;
   char _label[10];
 
-  boolean currstate, laststate;
+  bool currstate, laststate;
 };
 
 class GFXcanvas1 : public Adafruit_GFX {
 
  public:
   GFXcanvas1(uint16_t w, uint16_t h);
-  ~GFXcanvas1(void);
-  void     drawPixel(int16_t x, int16_t y, uint16_t color),
-           fillScreen(uint16_t color);
+  virtual ~GFXcanvas1(void);
+  virtual void     drawPixel(int16_t x, int16_t y, uint16_t color),
+                   fillScreen(uint16_t color);
   uint8_t *getBuffer(void);
  private:
   uint8_t *buffer;
@@ -144,9 +151,9 @@
 
 class GFXcanvas16 : public Adafruit_GFX {
   GFXcanvas16(uint16_t w, uint16_t h);
-  ~GFXcanvas16(void);
-  void      drawPixel(int16_t x, int16_t y, uint16_t color),
-            fillScreen(uint16_t color);
+  virtual ~GFXcanvas16(void);
+  virtual void      drawPixel(int16_t x, int16_t y, uint16_t color),
+                    fillScreen(uint16_t color);
   uint16_t *getBuffer(void);
  private:
   uint16_t *buffer;
--- a/Adafruit-GFX-Library-master/fontconvert/fontconvert.c	Mon May 02 11:24:17 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/*
-TrueType to Adafruit_GFX font converter.  Derived from Peter Jakobs'
-Adafruit_ftGFX fork & makefont tool, and Paul Kourany's Adafruit_mfGFX.
-
-NOT AN ARDUINO SKETCH.  This is a command-line tool for preprocessing
-fonts to be used with the Adafruit_GFX Arduino library.
-
-For UNIX-like systems.  Outputs to stdout; redirect to header file, e.g.:
-  ./fontconvert ~/Library/Fonts/FreeSans.ttf 18 > FreeSans18pt7b.h
-
-REQUIRES FREETYPE LIBRARY.  www.freetype.org
-
-Currently this only extracts the printable 7-bit ASCII chars of a font.
-Will eventually extend with some int'l chars a la ftGFX, not there yet.
-Keep 7-bit fonts around as an option in that case, more compact.
-
-See notes at end for glyph nomenclature & other tidbits.
-*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdint.h>
-#include <ft2build.h>
-#include FT_GLYPH_H
-#include "../gfxfont.h" // Adafruit_GFX font structures
-
-#define DPI 141 // Approximate res. of Adafruit 2.8" TFT
-
-// Accumulate bits for output, with periodic hexadecimal byte write
-void enbit(uint8_t value) {
-	static uint8_t row = 0, sum = 0, bit = 0x80, firstCall = 1;
-	if(value) sum |= bit;    // Set bit if needed
-	if(!(bit >>= 1)) {       // Advance to next bit, end of byte reached?
-		if(!firstCall) { // Format output table nicely
-			if(++row >= 12) {        // Last entry on line?
-				printf(",\n  "); //   Newline format output
-				row = 0;         //   Reset row counter
-			} else {                 // Not end of line
-				printf(", ");    //   Simple comma delim
-			}
-		}
-		printf("0x%02X", sum); // Write byte value
-		sum       = 0;         // Clear for next byte
-		bit       = 0x80;      // Reset bit counter
-		firstCall = 0;         // Formatting flag
-	}
-}
-
-int main(int argc, char *argv[]) {
-	int                i, j, err, size, first=' ', last='~',
-	                   bitmapOffset = 0, x, y, byte;
-	char              *fontName, c, *ptr;
-	FT_Library         library;
-	FT_Face            face;
-	FT_Glyph           glyph;
-	FT_Bitmap         *bitmap;
-	FT_BitmapGlyphRec *g;
-	GFXglyph          *table;
-	uint8_t            bit;
-
-	// Parse command line.  Valid syntaxes are:
-	//   fontconvert [filename] [size]
-	//   fontconvert [filename] [size] [last char]
-	//   fontconvert [filename] [size] [first char] [last char]
-	// Unless overridden, default first and last chars are
-	// ' ' (space) and '~', respectively
-
-	if(argc < 3) {
-		fprintf(stderr, "Usage: %s fontfile size [first] [last]\n",
-		  argv[0]);
-		return 1;
-	}
-
-	size = atoi(argv[2]);
-
-	if(argc == 4) {
-		last  = atoi(argv[3]);
-	} else if(argc == 5) {
-		first = atoi(argv[3]);
-		last  = atoi(argv[4]);
-	}
-
-	if(last < first) {
-		i     = first;
-		first = last;
-		last  = i;
-	}
-
-	ptr = strrchr(argv[1], '/'); // Find last slash in filename
-	if(ptr) ptr++;         // First character of filename (path stripped)
-	else    ptr = argv[1]; // No path; font in local dir.
-
-	// Allocate space for font name and glyph table
-	if((!(fontName = malloc(strlen(ptr) + 20))) ||
-	   (!(table = (GFXglyph *)malloc((last - first + 1) *
-	    sizeof(GFXglyph))))) {
-		fprintf(stderr, "Malloc error\n");
-		return 1;
-	}
-
-	// Derive font table names from filename.  Period (filename
-	// extension) is truncated and replaced with the font size & bits.
-	strcpy(fontName, ptr);
-	ptr = strrchr(fontName, '.'); // Find last period (file ext)
-	if(!ptr) ptr = &fontName[strlen(fontName)]; // If none, append
-	// Insert font size and 7/8 bit.  fontName was alloc'd w/extra
-	// space to allow this, we're not sprintfing into Forbidden Zone.
-	sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7);
-	// Space and punctuation chars in name replaced w/ underscores.  
-	for(i=0; (c=fontName[i]); i++) {
-		if(isspace(c) || ispunct(c)) fontName[i] = '_';
-	}
-
-	// Init FreeType lib, load font
-	if((err = FT_Init_FreeType(&library))) {
-		fprintf(stderr, "FreeType init error: %d", err);
-		return err;
-	}
-	if((err = FT_New_Face(library, argv[1], 0, &face))) {
-		fprintf(stderr, "Font load error: %d", err);
-		FT_Done_FreeType(library);
-		return err;
-	}
-
-	// << 6 because '26dot6' fixed-point format
-	FT_Set_Char_Size(face, size << 6, 0, DPI, 0);
-
-	// Currently all symbols from 'first' to 'last' are processed.
-	// Fonts may contain WAY more glyphs than that, but this code
-	// will need to handle encoding stuff to deal with extracting
-	// the right symbols, and that's not done yet.
-	// fprintf(stderr, "%ld glyphs\n", face->num_glyphs);
-
-	printf("const uint8_t %sBitmaps[] PROGMEM = {\n  ", fontName);
-
-	// Process glyphs and output huge bitmap data array
-	for(i=first, j=0; i<=last; i++, j++) {
-		// MONO renderer provides clean image with perfect crop
-		// (no wasted pixels) via bitmap struct.
-		if((err = FT_Load_Char(face, i, FT_LOAD_TARGET_MONO))) {
-			fprintf(stderr, "Error %d loading char '%c'\n",
-			  err, i);
-			continue;
-		}
-
-		if((err = FT_Render_Glyph(face->glyph,
-		  FT_RENDER_MODE_MONO))) {
-			fprintf(stderr, "Error %d rendering char '%c'\n",
-			  err, i);
-			continue;
-		}
-
-		if((err = FT_Get_Glyph(face->glyph, &glyph))) {
-			fprintf(stderr, "Error %d getting glyph '%c'\n",
-			  err, i);
-			continue;
-		}
-
-		bitmap = &face->glyph->bitmap;
-		g      = (FT_BitmapGlyphRec *)glyph;
-
-		// Minimal font and per-glyph information is stored to
-		// reduce flash space requirements.  Glyph bitmaps are
-		// fully bit-packed; no per-scanline pad, though end of
-		// each character may be padded to next byte boundary
-		// when needed.  16-bit offset means 64K max for bitmaps,
-		// code currently doesn't check for overflow.  (Doesn't
-		// check that size & offsets are within bounds either for
-		// that matter...please convert fonts responsibly.)
-		table[j].bitmapOffset = bitmapOffset;
-		table[j].width        = bitmap->width;
-		table[j].height       = bitmap->rows;
-		table[j].xAdvance     = face->glyph->advance.x >> 6;
-		table[j].xOffset      = g->left;
-		table[j].yOffset      = 1 - g->top;
-
-		for(y=0; y < bitmap->rows; y++) {
-			for(x=0;x < bitmap->width; x++) {
-				byte = x / 8;
-				bit  = 0x80 >> (x & 7);
-				enbit(bitmap->buffer[
-				  y * bitmap->pitch + byte] & bit);
-			}
-		}
-
-		// Pad end of char bitmap to next byte boundary if needed
-		int n = (bitmap->width * bitmap->rows) & 7;
-		if(n) { // Pixel count not an even multiple of 8?
-			n = 8 - n; // # bits to next multiple
-			while(n--) enbit(0);
-		}
-		bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8;
-
-		FT_Done_Glyph(glyph);
-	}
-
-	printf(" };\n\n"); // End bitmap array
-
-	// Output glyph attributes table (one per character)
-	printf("const GFXglyph %sGlyphs[] PROGMEM = {\n", fontName);
-	for(i=first, j=0; i<=last; i++, j++) {
-		printf("  { %5d, %3d, %3d, %3d, %4d, %4d }",
-		  table[j].bitmapOffset,
-		  table[j].width,
-		  table[j].height,
-		  table[j].xAdvance,
-		  table[j].xOffset,
-		  table[j].yOffset);
-		if(i < last) {
-			printf(",   // 0x%02X", i);
-			if((i >= ' ') && (i <= '~')) {
-				printf(" '%c'", i);
-			}
-			putchar('\n');
-		}
-	}
-	printf(" }; // 0x%02X", last);
-	if((last >= ' ') && (last <= '~')) printf(" '%c'", last);
-	printf("\n\n");
-
-	// Output font structure
-	printf("const GFXfont %s PROGMEM = {\n", fontName);
-	printf("  (uint8_t  *)%sBitmaps,\n", fontName);
-	printf("  (GFXglyph *)%sGlyphs,\n", fontName);
-	printf("  0x%02X, 0x%02X, %ld };\n\n",
-	  first, last, face->size->metrics.height >> 6);
-	printf("// Approx. %d bytes\n",
-	  bitmapOffset + (last - first + 1) * 7 + 7);
-	// Size estimate is based on AVR struct and pointer sizes;
-	// actual size may vary.
-
-	FT_Done_FreeType(library);
-
-	return 0;
-}
-
-/* -------------------------------------------------------------------------
-
-Character metrics are slightly different from classic GFX & ftGFX.
-In classic GFX: cursor position is the upper-left pixel of each 5x7
-character; lower extent of most glyphs (except those w/descenders)
-is +6 pixels in Y direction.
-W/new GFX fonts: cursor position is on baseline, where baseline is
-'inclusive' (containing the bottom-most row of pixels in most symbols,
-except those with descenders; ftGFX is one pixel lower).
-
-Cursor Y will be moved automatically when switching between classic
-and new fonts.  If you switch fonts, any print() calls will continue
-along the same baseline.
-
-                    ...........#####.. -- yOffset
-                    ..........######..
-                    ..........######..
-                    .........#######..
-                    ........#########.
-   * = Cursor pos.  ........#########.
-                    .......##########.
-                    ......#####..####.
-                    ......#####..####.
-       *.#..        .....#####...####.
-       .#.#.        ....##############
-       #...#        ...###############
-       #...#        ...###############
-       #####        ..#####......#####
-       #...#        .#####.......#####
-====== #...# ====== #*###.........#### ======= Baseline
-                    || xOffset
-
-glyph->xOffset and yOffset are pixel offsets, in GFX coordinate space
-(+Y is down), from the cursor position to the top-left pixel of the
-glyph bitmap.  i.e. yOffset is typically negative, xOffset is typically
-zero but a few glyphs will have other values (even negative xOffsets
-sometimes, totally normal).  glyph->xAdvance is the distance to move
-the cursor on the X axis after drawing the corresponding symbol.
-
-There's also some changes with regard to 'background' color and new GFX
-fonts (classic fonts unchanged).  See Adafruit_GFX.cpp for explanation.
-*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit-GFX-Library-master/fontconvert/fontconvert.txt	Mon May 02 16:49:40 2016 +0000
@@ -0,0 +1,278 @@
+/*
+TrueType to Adafruit_GFX font converter.  Derived from Peter Jakobs'
+Adafruit_ftGFX fork & makefont tool, and Paul Kourany's Adafruit_mfGFX.
+
+NOT AN ARDUINO SKETCH.  This is a command-line tool for preprocessing
+fonts to be used with the Adafruit_GFX Arduino library.
+
+For UNIX-like systems.  Outputs to stdout; redirect to header file, e.g.:
+  ./fontconvert ~/Library/Fonts/FreeSans.ttf 18 > FreeSans18pt7b.h
+
+REQUIRES FREETYPE LIBRARY.  www.freetype.org
+
+Currently this only extracts the printable 7-bit ASCII chars of a font.
+Will eventually extend with some int'l chars a la ftGFX, not there yet.
+Keep 7-bit fonts around as an option in that case, more compact.
+
+See notes at end for glyph nomenclature & other tidbits.
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <ft2build.h>
+#include FT_GLYPH_H
+#include "../gfxfont.h" // Adafruit_GFX font structures
+
+#define DPI 141 // Approximate res. of Adafruit 2.8" TFT
+
+// Accumulate bits for output, with periodic hexadecimal byte write
+void enbit(uint8_t value) {
+	static uint8_t row = 0, sum = 0, bit = 0x80, firstCall = 1;
+	if(value) sum |= bit;    // Set bit if needed
+	if(!(bit >>= 1)) {       // Advance to next bit, end of byte reached?
+		if(!firstCall) { // Format output table nicely
+			if(++row >= 12) {        // Last entry on line?
+				printf(",\n  "); //   Newline format output
+				row = 0;         //   Reset row counter
+			} else {                 // Not end of line
+				printf(", ");    //   Simple comma delim
+			}
+		}
+		printf("0x%02X", sum); // Write byte value
+		sum       = 0;         // Clear for next byte
+		bit       = 0x80;      // Reset bit counter
+		firstCall = 0;         // Formatting flag
+	}
+}
+
+int main(int argc, char *argv[]) {
+	int                i, j, err, size, first=' ', last='~',
+	                   bitmapOffset = 0, x, y, byte;
+	char              *fontName, c, *ptr;
+	FT_Library         library;
+	FT_Face            face;
+	FT_Glyph           glyph;
+	FT_Bitmap         *bitmap;
+	FT_BitmapGlyphRec *g;
+	GFXglyph          *table;
+	uint8_t            bit;
+
+	// Parse command line.  Valid syntaxes are:
+	//   fontconvert [filename] [size]
+	//   fontconvert [filename] [size] [last char]
+	//   fontconvert [filename] [size] [first char] [last char]
+	// Unless overridden, default first and last chars are
+	// ' ' (space) and '~', respectively
+
+	if(argc < 3) {
+		fprintf(stderr, "Usage: %s fontfile size [first] [last]\n",
+		  argv[0]);
+		return 1;
+	}
+
+	size = atoi(argv[2]);
+
+	if(argc == 4) {
+		last  = atoi(argv[3]);
+	} else if(argc == 5) {
+		first = atoi(argv[3]);
+		last  = atoi(argv[4]);
+	}
+
+	if(last < first) {
+		i     = first;
+		first = last;
+		last  = i;
+	}
+
+	ptr = strrchr(argv[1], '/'); // Find last slash in filename
+	if(ptr) ptr++;         // First character of filename (path stripped)
+	else    ptr = argv[1]; // No path; font in local dir.
+
+	// Allocate space for font name and glyph table
+	if((!(fontName = malloc(strlen(ptr) + 20))) ||
+	   (!(table = (GFXglyph *)malloc((last - first + 1) *
+	    sizeof(GFXglyph))))) {
+		fprintf(stderr, "Malloc error\n");
+		return 1;
+	}
+
+	// Derive font table names from filename.  Period (filename
+	// extension) is truncated and replaced with the font size & bits.
+	strcpy(fontName, ptr);
+	ptr = strrchr(fontName, '.'); // Find last period (file ext)
+	if(!ptr) ptr = &fontName[strlen(fontName)]; // If none, append
+	// Insert font size and 7/8 bit.  fontName was alloc'd w/extra
+	// space to allow this, we're not sprintfing into Forbidden Zone.
+	sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7);
+	// Space and punctuation chars in name replaced w/ underscores.  
+	for(i=0; (c=fontName[i]); i++) {
+		if(isspace(c) || ispunct(c)) fontName[i] = '_';
+	}
+
+	// Init FreeType lib, load font
+	if((err = FT_Init_FreeType(&library))) {
+		fprintf(stderr, "FreeType init error: %d", err);
+		return err;
+	}
+	if((err = FT_New_Face(library, argv[1], 0, &face))) {
+		fprintf(stderr, "Font load error: %d", err);
+		FT_Done_FreeType(library);
+		return err;
+	}
+
+	// << 6 because '26dot6' fixed-point format
+	FT_Set_Char_Size(face, size << 6, 0, DPI, 0);
+
+	// Currently all symbols from 'first' to 'last' are processed.
+	// Fonts may contain WAY more glyphs than that, but this code
+	// will need to handle encoding stuff to deal with extracting
+	// the right symbols, and that's not done yet.
+	// fprintf(stderr, "%ld glyphs\n", face->num_glyphs);
+
+	printf("const uint8_t %sBitmaps[] PROGMEM = {\n  ", fontName);
+
+	// Process glyphs and output huge bitmap data array
+	for(i=first, j=0; i<=last; i++, j++) {
+		// MONO renderer provides clean image with perfect crop
+		// (no wasted pixels) via bitmap struct.
+		if((err = FT_Load_Char(face, i, FT_LOAD_TARGET_MONO))) {
+			fprintf(stderr, "Error %d loading char '%c'\n",
+			  err, i);
+			continue;
+		}
+
+		if((err = FT_Render_Glyph(face->glyph,
+		  FT_RENDER_MODE_MONO))) {
+			fprintf(stderr, "Error %d rendering char '%c'\n",
+			  err, i);
+			continue;
+		}
+
+		if((err = FT_Get_Glyph(face->glyph, &glyph))) {
+			fprintf(stderr, "Error %d getting glyph '%c'\n",
+			  err, i);
+			continue;
+		}
+
+		bitmap = &face->glyph->bitmap;
+		g      = (FT_BitmapGlyphRec *)glyph;
+
+		// Minimal font and per-glyph information is stored to
+		// reduce flash space requirements.  Glyph bitmaps are
+		// fully bit-packed; no per-scanline pad, though end of
+		// each character may be padded to next byte boundary
+		// when needed.  16-bit offset means 64K max for bitmaps,
+		// code currently doesn't check for overflow.  (Doesn't
+		// check that size & offsets are within bounds either for
+		// that matter...please convert fonts responsibly.)
+		table[j].bitmapOffset = bitmapOffset;
+		table[j].width        = bitmap->width;
+		table[j].height       = bitmap->rows;
+		table[j].xAdvance     = face->glyph->advance.x >> 6;
+		table[j].xOffset      = g->left;
+		table[j].yOffset      = 1 - g->top;
+
+		for(y=0; y < bitmap->rows; y++) {
+			for(x=0;x < bitmap->width; x++) {
+				byte = x / 8;
+				bit  = 0x80 >> (x & 7);
+				enbit(bitmap->buffer[
+				  y * bitmap->pitch + byte] & bit);
+			}
+		}
+
+		// Pad end of char bitmap to next byte boundary if needed
+		int n = (bitmap->width * bitmap->rows) & 7;
+		if(n) { // Pixel count not an even multiple of 8?
+			n = 8 - n; // # bits to next multiple
+			while(n--) enbit(0);
+		}
+		bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8;
+
+		FT_Done_Glyph(glyph);
+	}
+
+	printf(" };\n\n"); // End bitmap array
+
+	// Output glyph attributes table (one per character)
+	printf("const GFXglyph %sGlyphs[] PROGMEM = {\n", fontName);
+	for(i=first, j=0; i<=last; i++, j++) {
+		printf("  { %5d, %3d, %3d, %3d, %4d, %4d }",
+		  table[j].bitmapOffset,
+		  table[j].width,
+		  table[j].height,
+		  table[j].xAdvance,
+		  table[j].xOffset,
+		  table[j].yOffset);
+		if(i < last) {
+			printf(",   // 0x%02X", i);
+			if((i >= ' ') && (i <= '~')) {
+				printf(" '%c'", i);
+			}
+			putchar('\n');
+		}
+	}
+	printf(" }; // 0x%02X", last);
+	if((last >= ' ') && (last <= '~')) printf(" '%c'", last);
+	printf("\n\n");
+
+	// Output font structure
+	printf("const GFXfont %s PROGMEM = {\n", fontName);
+	printf("  (uint8_t  *)%sBitmaps,\n", fontName);
+	printf("  (GFXglyph *)%sGlyphs,\n", fontName);
+	printf("  0x%02X, 0x%02X, %ld };\n\n",
+	  first, last, face->size->metrics.height >> 6);
+	printf("// Approx. %d bytes\n",
+	  bitmapOffset + (last - first + 1) * 7 + 7);
+	// Size estimate is based on AVR struct and pointer sizes;
+	// actual size may vary.
+
+	FT_Done_FreeType(library);
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------
+
+Character metrics are slightly different from classic GFX & ftGFX.
+In classic GFX: cursor position is the upper-left pixel of each 5x7
+character; lower extent of most glyphs (except those w/descenders)
+is +6 pixels in Y direction.
+W/new GFX fonts: cursor position is on baseline, where baseline is
+'inclusive' (containing the bottom-most row of pixels in most symbols,
+except those with descenders; ftGFX is one pixel lower).
+
+Cursor Y will be moved automatically when switching between classic
+and new fonts.  If you switch fonts, any print() calls will continue
+along the same baseline.
+
+                    ...........#####.. -- yOffset
+                    ..........######..
+                    ..........######..
+                    .........#######..
+                    ........#########.
+   * = Cursor pos.  ........#########.
+                    .......##########.
+                    ......#####..####.
+                    ......#####..####.
+       *.#..        .....#####...####.
+       .#.#.        ....##############
+       #...#        ...###############
+       #...#        ...###############
+       #####        ..#####......#####
+       #...#        .#####.......#####
+====== #...# ====== #*###.........#### ======= Baseline
+                    || xOffset
+
+glyph->xOffset and yOffset are pixel offsets, in GFX coordinate space
+(+Y is down), from the cursor position to the top-left pixel of the
+glyph bitmap.  i.e. yOffset is typically negative, xOffset is typically
+zero but a few glyphs will have other values (even negative xOffsets
+sometimes, totally normal).  glyph->xAdvance is the distance to move
+the cursor on the X axis after drawing the corresponding symbol.
+
+There's also some changes with regard to 'background' color and new GFX
+fonts (classic fonts unchanged).  See Adafruit_GFX.cpp for explanation.
+*/