Added SparkFun ColorLCDLibrary which this project depends upon

This commit is contained in:
Mike C 2013-03-10 22:05:44 -04:00
parent 68f5b7b101
commit 1bab2aa107
7 changed files with 1489 additions and 0 deletions

View file

@ -0,0 +1,623 @@
/*
LCDShield.cpp - Arduino Library to control a Nokia 6100 LCD,
specifically that found on SparkFun's Color LCD Shield.
This code should work for both Epson and Phillips display drivers
normally found on the Color LCD Shield.
License: CC BY-SA 3.0: Creative Commons Share-alike 3.0. Feel free
to use and abuse this code however you'd like. If you find it useful
please attribute, and SHARE-ALIKE!
This is based on code by Mark Sproul, and Peter Davenport.
Thanks to Coleman Sellers and Harold Timmis for help getting it to work with the Phillips Driver 7-31-2011
*/
#include "ColorLCDShield.h"
/*extern "C" {
#include "wiring.h"
}*/
#include "Arduino.h"
static char x_offset = 0;
static char y_offset = 0;
LCDShield::LCDShield()
{
#if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
DDRB = ((1<<DIO)|(1<<SCK_PIN)); //Set DIO and SCK_PIN pins on PORTB as outputs
DDRH = ((1<<CS)|(1<<LCD_RES)); //Set CS and RES pins PORTH as outputs
#elif defined(__AVR_ATmega32U4__)
DDRB = (1<<LCD_RES) | (1<<CS) | (1<<DIO);
DDRC = (1<<SCK_PIN);
#else
DDRB = ((1<<CS)|(1<<DIO)|(1<<SCK_PIN)|(1<<LCD_RES)); //Set the control pins as outputs
#endif
DDRD = 0x00;
PORTD = 0xFF;
}
void LCDShield::LCDCommand(unsigned char data)
{
char jj;
cbi(LCD_PORT_CS, CS); // enable chip
cbi(LCD_PORT_DIO, DIO); // output low on data out (9th bit low = command)
cbi(LCD_PORT_SCK, SCK_PIN); // send clock pulse
delayMicroseconds(1);
sbi(LCD_PORT_SCK, SCK_PIN);
for (jj = 0; jj < 8; jj++)
{
if ((data & 0x80) == 0x80)
sbi(LCD_PORT_DIO, DIO);
else
cbi(LCD_PORT_DIO, DIO);
cbi(LCD_PORT_SCK, SCK_PIN); // send clock pulse
delayMicroseconds(1);
sbi(LCD_PORT_SCK, SCK_PIN);
data <<= 1;
}
sbi(LCD_PORT_CS, CS); // disable
}
void LCDShield::LCDData(unsigned char data)
{
char j;
cbi(LCD_PORT_CS, CS); // enable chip
sbi(LCD_PORT_DIO, DIO); // output high on data out (9th bit high = data)
cbi(LCD_PORT_SCK, SCK_PIN); // send clock pulse
delayMicroseconds(1);
sbi(LCD_PORT_SCK, SCK_PIN); // send clock pulse
for (j = 0; j < 8; j++)
{
if ((data & 0x80) == 0x80)
sbi(LCD_PORT_DIO, DIO);
else
cbi(LCD_PORT_DIO, DIO);
cbi(LCD_PORT_SCK, SCK_PIN); // send clock pulse
delayMicroseconds(1);
sbi(LCD_PORT_SCK, SCK_PIN);
data <<= 1;
}
LCD_PORT_CS |= (1<<CS); // disable
}
void LCDShield::init(int type, bool colorSwap)
{
driver = type;
// Initialize the control pins, and reset display:
cbi(LCD_PORT_SCK, SCK_PIN); // CLK = LOW
cbi(LCD_PORT_DIO, DIO); // DIO = LOW
delayMicroseconds(10); // 10us delay
sbi(LCD_PORT_CS, CS); // CS = HIGH
delayMicroseconds(10); // 10uS Delay
cbi(LCD_PORT_RES, LCD_RES); // RESET = LOW
delay(200); // 200ms delay
sbi(LCD_PORT_RES, LCD_RES); // RESET = HIGH
delay(200); // 200ms delay
sbi(LCD_PORT_SCK, SCK_PIN); // SCK_PIN = HIGH
sbi(LCD_PORT_DIO, DIO); // DIO = HIGH
delayMicroseconds(10); // 10us delay
if (driver == EPSON)
{
LCDCommand(DISCTL); // Display control (0xCA)
LCDData(0x0C); // 12 = 1100 - CL dividing ratio [don't divide] switching period 8H (default)
LCDData(0x20); // nlines/4 - 1 = 132/4 - 1 = 32 duty
LCDData(0x00); // No inversely highlighted lines
LCDCommand(COMSCN); // common scanning direction (0xBB)
LCDData(0x01); // 1->68, 132<-69 scan direction
LCDCommand(OSCON); // internal oscialltor ON (0xD1)
LCDCommand(SLPOUT); // sleep out (0x94)
LCDCommand(PWRCTR); // power ctrl (0x20)
LCDData(0x0F); // everything on, no external reference resistors
LCDCommand(DISINV); // invert display mode (0xA7)
LCDCommand(DATCTL); // data control (0xBC)
LCDData(0x03); // Inverse page address, reverse rotation column address, column scan-direction !!! try 0x01
LCDData(0x00); // normal RGB arrangement
LCDData(0x02); // 16-bit Grayscale Type A (12-bit color)
LCDCommand(VOLCTR); // electronic volume, this is the contrast/brightness (0x81)
LCDData(32); // volume (contrast) setting - fine tuning, original (0-63)
LCDData(3); // internal resistor ratio - coarse adjustment (0-7)
LCDCommand(NOP); // nop (0x25)
delay(100);
LCDCommand(DISON); // display on (0xAF)
}
else if (driver == PHILIPS)
{
LCDCommand(SLEEPOUT); // Sleep Out (0x11)
LCDCommand(BSTRON); // Booster voltage on (0x03)
LCDCommand(DISPON); // Display on (0x29)
//LCDCommand(INVON); // Inversion on (0x20)
// 12-bit color pixel format:
LCDCommand(COLMOD); // Color interface format (0x3A)
LCDData(0x03); // 0b011 is 12-bit/pixel mode
LCDCommand(MADCTL); // Memory Access Control(PHILLIPS)
if (colorSwap)
LCDData(0x08);
else
LCDData(0x00);
LCDCommand(SETCON); // Set Contrast(PHILLIPS)
LCDData(0x30);
LCDCommand(NOPP); // nop(PHILLIPS)
}
}
void LCDShield::clear(int color)
{
if (driver) // if it's an Epson
{
LCDCommand(PASET);
LCDData(0);
LCDData(131);
LCDCommand(CASET);
LCDData(0);
LCDData(131);
LCDCommand(RAMWR);
}
else // otherwise it's a phillips
{
LCDCommand(PASETP);
LCDData(0);
LCDData(131);
LCDCommand(CASETP);
LCDData(0);
LCDData(131);
LCDCommand(RAMWRP);
}
for(unsigned int i=0; i < (131*131)/2; i++)
{
LCDData((color>>4)&0x00FF);
LCDData(((color&0x0F)<<4)|(color>>8));
LCDData(color&0x0FF);
}
x_offset = 0;
y_offset = 0;
}
void LCDShield::contrast(char setting)
{
if (driver == EPSON)
{
setting &= 0x3F; // 2 msb's not used, mask out
LCDCommand(VOLCTR); // electronic volume, this is the contrast/brightness(EPSON)
LCDData(setting); // volume (contrast) setting - course adjustment, -- original was 24
LCDData(3); // TODO: Make this coarse adjustment variable, 3's a good place to stay
}
else if (driver == PHILIPS)
{
setting &= 0x7F; // msb is not used, mask it out
LCDCommand(SETCON); // contrast command (PHILLIPS)
LCDData(setting); // volume (contrast) setting - course adjustment, -- original was 24
}
}
// Added by Steve Sparks @ Big Nerd Ranch.
// This swaps the Epson RGB order into the Philips RGB order. (Or, vice versa, I suppose.)
uint16_t LCDShield::swapColors(uint16_t in) {
return ((in & 0x000F)<<8)|(in & 0x00F0)|((in & 0x0F00)>>8);
}
void LCDShield::setPixel(int color, unsigned char x, unsigned char y)
{
y = (COL_HEIGHT - 1) - y;
x = (ROW_LENGTH - 1) - x;
if (driver == EPSON) // if it's an epson
{
LCDCommand(PASET); // page start/end ram
LCDData(x);
LCDData(ENDPAGE);
LCDCommand(CASET); // column start/end ram
LCDData(y);
LCDData(ENDCOL);
LCDCommand(RAMWR); // write
LCDData((color>>4)&0x00FF);
LCDData(((color&0x0F)<<4)|(color>>8));
LCDData(color&0x0FF);
}
else if (driver == PHILIPS) // otherwise it's a phillips
{
LCDCommand(PASETP); // page start/end ram
LCDData(x);
LCDData(x);
LCDCommand(CASETP); // column start/end ram
LCDData(y);
LCDData(y);
LCDCommand(RAMWRP); // write
LCDData((unsigned char)((color>>4)&0x00FF));
LCDData((unsigned char)(((color&0x0F)<<4)|0x00));
}
}
// 2/18/2013 This Methos added by Tony Contrada in order to create arc segments in varied line thickness, or Filled
void LCDShield::setArc(int x0, int y0, int radius, int arcSegments[], int numSegments, int lineThickness, int color)
{
//Line Thickness (Num Pixels)
if(lineThickness == FILL) lineThickness = radius;
for(int i = 0; i < lineThickness; i++)
{
int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
for(int i = 0; i < numSegments; i++)
{
if(arcSegments[i] == NNE) setPixel(color, x0 - y, y0 + x); //SHOW NNE
if(arcSegments[i] == ENE) setPixel(color, x0 - x, y0 + y); //SHOW ENE
if(arcSegments[i] == ESE) setPixel(color, x0 + x, y0 + y); //SHOW ESE
if(arcSegments[i] == SSE) setPixel(color, x0 + y, y0 + x); //SHOW SSE
if(arcSegments[i] == SSW) setPixel(color, x0 + y, y0 - x); //SHOW SSW
if(arcSegments[i] == WSW) setPixel(color, x0 + x, y0 - y); //SHOW WSW
if(arcSegments[i] == WNW) setPixel(color, x0 - x, y0 - y); //SHOW WNW
if(arcSegments[i] == NNW) setPixel(color, x0 - y, y0 - x); //SHOW NNW
}
}
radius--;
}
}
// 2/22/2013 - Modified by Tony Contrada to include Line Thickness (in pixels) or a Filled Circle
void LCDShield::setCircle (int x0, int y0, int radius, int color, int lineThickness)
{
if(lineThickness == FILL) lineThickness = radius;
for(int r = 0; r < lineThickness; r++)
{
int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
setPixel(color, x0, y0 + radius);
setPixel(color, x0, y0 - radius);
setPixel(color, x0 + radius, y0);
setPixel(color, x0 - radius, y0);
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
setPixel(color, x0 + x, y0 + y);
setPixel(color, x0 - x, y0 + y);
setPixel(color, x0 + x, y0 - y);
setPixel(color, x0 - x, y0 - y);
setPixel(color, x0 + y, y0 + x);
setPixel(color, x0 - y, y0 + x);
setPixel(color, x0 + y, y0 - x);
setPixel(color, x0 - y, y0 - x);
}
radius--;
}
}
void LCDShield::setChar(char c, int x, int y, int fColor, int bColor)
{
y = (COL_HEIGHT - 1) - y; // make display "right" side up
x = (ROW_LENGTH - 2) - x;
int i,j;
unsigned int nCols;
unsigned int nRows;
unsigned int nBytes;
unsigned char PixelRow;
unsigned char Mask;
unsigned int Word0;
unsigned int Word1;
unsigned char *pFont;
unsigned char *pChar;
// get pointer to the beginning of the selected font table
pFont = (unsigned char *)FONT8x16;
// get the nColumns, nRows and nBytes
nCols = *pFont;
nRows = *(pFont + 1);
nBytes = *(pFont + 2);
// get pointer to the last byte of the desired character
pChar = pFont + (nBytes * (c - 0x1F)) + nBytes - 1;
if (driver) // if it's an epson
{
// Row address set (command 0x2B)
LCDCommand(PASET);
LCDData(x);
LCDData(x + nRows - 1);
// Column address set (command 0x2A)
LCDCommand(CASET);
LCDData(y);
LCDData(y + nCols - 1);
// WRITE MEMORY
LCDCommand(RAMWR);
// loop on each row, working backwards from the bottom to the top
for (i = nRows - 1; i >= 0; i--) {
// copy pixel row from font table and then decrement row
PixelRow = *pChar++;
// loop on each pixel in the row (left to right)
// Note: we do two pixels each loop
Mask = 0x80;
for (j = 0; j < nCols; j += 2)
{
// if pixel bit set, use foreground color; else use the background color
// now get the pixel color for two successive pixels
if ((PixelRow & Mask) == 0)
Word0 = bColor;
else
Word0 = fColor;
Mask = Mask >> 1;
if ((PixelRow & Mask) == 0)
Word1 = bColor;
else
Word1 = fColor;
Mask = Mask >> 1;
// use this information to output three data bytes
LCDData((Word0 >> 4) & 0xFF);
LCDData(((Word0 & 0xF) << 4) | ((Word1 >> 8) & 0xF));
LCDData(Word1 & 0xFF);
}
}
}
else
{
fColor = swapColors(fColor);
bColor = swapColors(bColor);
// Row address set (command 0x2B)
LCDCommand(PASETP);
LCDData(x);
LCDData(x + nRows - 1);
// Column address set (command 0x2A)
LCDCommand(CASETP);
LCDData(y);
LCDData(y + nCols - 1);
// WRITE MEMORY
LCDCommand(RAMWRP);
// loop on each row, working backwards from the bottom to the top
pChar+=nBytes-1; // stick pChar at the end of the row - gonna reverse print on phillips
for (i = nRows - 1; i >= 0; i--) {
// copy pixel row from font table and then decrement row
PixelRow = *pChar--;
// loop on each pixel in the row (left to right)
// Note: we do two pixels each loop
Mask = 0x01; // <- opposite of epson
for (j = 0; j < nCols; j += 2)
{
// if pixel bit set, use foreground color; else use the background color
// now get the pixel color for two successive pixels
if ((PixelRow & Mask) == 0)
Word0 = bColor;
else
Word0 = fColor;
Mask = Mask << 1; // <- opposite of epson
if ((PixelRow & Mask) == 0)
Word1 = bColor;
else
Word1 = fColor;
Mask = Mask << 1; // <- opposite of epson
// use this information to output three data bytes
LCDData((Word0 >> 4) & 0xFF);
LCDData(((Word0 & 0xF) << 4) | ((Word1 >> 8) & 0xF));
LCDData(Word1 & 0xFF);
}
}
}
}
void LCDShield::setStr(char *pString, int x, int y, int fColor, int bColor)
{
x = x + 16;
y = y + 8;
int originalY = y;
// loop until null-terminator is seen
while (*pString != 0x00) {
// draw the character
setChar(*pString++, x, y, fColor, bColor);
// advance the y position
y = y + 8;
// bail out if y exceeds 131
if (y > 131) {
x = x + 16;
y = originalY;
}
if (x > 123) break;
}
}
void LCDShield::setLine(int x0, int y0, int x1, int y1, int color)
{
int dy = y1 - y0; // Difference between y0 and y1
int dx = x1 - x0; // Difference between x0 and x1
int stepx, stepy;
if (dy < 0)
{
dy = -dy;
stepy = -1;
}
else
stepy = 1;
if (dx < 0)
{
dx = -dx;
stepx = -1;
}
else
stepx = 1;
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
setPixel(color, x0, y0);
if (dx > dy)
{
int fraction = dy - (dx >> 1);
while (x0 != x1)
{
if (fraction >= 0)
{
y0 += stepy;
fraction -= dx;
}
x0 += stepx;
fraction += dy;
setPixel(color, x0, y0);
}
}
else
{
int fraction = dx - (dy >> 1);
while (y0 != y1)
{
if (fraction >= 0)
{
x0 += stepx;
fraction -= dy;
}
y0 += stepy;
fraction += dx;
setPixel(color, x0, y0);
}
}
}
void LCDShield::setRect(int x0, int y0, int x1, int y1, unsigned char fill, int color)
{
// check if the rectangle is to be filled
if (fill == 1)
{
int xDiff;
if(x0 > x1)
xDiff = x0 - x1; //Find the difference between the x vars
else
xDiff = x1 - x0;
while(xDiff > 0)
{
setLine(x0, y0, x0, y1, color);
if(x0 > x1)
x0--;
else
x0++;
xDiff--;
}
}
else
{
// best way to draw an unfilled rectangle is to draw four lines
setLine(x0, y0, x1, y0, color);
setLine(x0, y1, x1, y1, color);
setLine(x0, y0, x0, y1, color);
setLine(x1, y0, x1, y1, color);
}
}
void LCDShield::printLogo(void)
{
int x = 4, y = 25, logo_ix = 0, z;
char logo;
for (logo_ix = 0; logo_ix < 1120; logo_ix++)
{
logo = logo_spark[logo_ix];
for (z = 0; z < 8; z++)
{
if ((logo & 0x80) == 0x80) setPixel(RED, y, x);
x++;
if (x == 132)
{
x = 4;
y++;
}
logo <<= 1;
}
}
}
void LCDShield::off(void)
{
if (driver) // If it's an epson
LCDCommand(DISOFF);
else // otherwise it's a phillips
LCDCommand(DISPOFF);
}
void LCDShield::on(void)
{
if (driver) // If it's an epson
LCDCommand(DISON);
else // otherwise it's a phillips
LCDCommand(DISPON);
}

View file

@ -0,0 +1,384 @@
/*
ColorLCDShield.h - Arduino Library to control a Nokia 6100 LCD,
specifically that found on SparkFun's Color LCD Shield.
This code should work for both Epson and Phillips display drivers
normally found on the Color LCD Shield.
License: CC BY-SA 3.0: Creative Commons Share-alike 3.0. Feel free
to use and abuse this code however you'd like. If you find it useful
please attribute, and SHARE-ALIKE!
This is based on code by Mark Sproul, and Peter Davenport.
*/
#ifndef ColorLCDShield_H
#define ColorLCDShield_H
#define PHILLIPS 0
#define PHILIPS 0
#define EPSON 1
//#include <WProgram.h>
#include <inttypes.h>
//*******************************************************
// Macros
//*******************************************************
#define sbi(var, mask) ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask))
//********************************************************************
//
// LCD Dimension Definitions
//
//********************************************************************
#define ROW_LENGTH 132
#define COL_HEIGHT 132
#define ENDPAGE 132
#define ENDCOL 130
//********************************************************************
//
// EPSON Controller Definitions
//
//********************************************************************
#define DISON 0xAF // Display on
#define DISOFF 0xAE // Display off
#define DISNOR 0xA6 // Normal display
#define DISINV 0xA7 // Inverse display
#define SLPIN 0x95 // Sleep in
#define SLPOUT 0x94 // Sleep out
#define COMSCN 0xBB // Common scan direction
#define DISCTL 0xCA // Display control
#define PASET 0x75 // Page address set
#define CASET 0x15 // Column address set
#define DATCTL 0xBC // Data scan direction, etc.
#define RGBSET8 0xCE // 256-color position set
#define RAMWR 0x5C // Writing to memory
#define RAMRD 0x5D // Reading from memory
#define PTLIN 0xA8 // Partial display in
#define PTLOUT 0xA9 // Partial display out
#define RMWIN 0xE0 // Read and modify write
#define RMWOUT 0xEE // End
#define ASCSET 0xAA // Area scroll set
#define SCSTART 0xAB // Scroll start set
#define OSCON 0xD1 // Internal oscillation on
#define OSCOFF 0xD2 // Internal osciallation off
#define PWRCTR 0x20 // Power control
#define VOLCTR 0x81 // Electronic volume control
#define VOLUP 0xD6 // Increment electronic control by 1
#define VOLDOWN 0xD7 // Decrement electronic control by 1
#define TMPGRD 0x82 // Temperature gradient set
#define EPCTIN 0xCD // Control EEPROM
#define EPCOUT 0xCC // Cancel EEPROM control
#define EPMWR 0xFC // Write into EEPROM
#define EPMRD 0xFD // Read from EEPROM
#define EPSRRD1 0x7C // Read register 1
#define EPSRRD2 0x7D // Read register 2
#define NOP 0x25 // No op
//********************************************************************
//
// PHILLIPS Controller Definitions
//
//********************************************************************
//LCD Commands
#define NOPP 0x00 // No operation
#define BSTRON 0x03 // Booster voltage on
#define SLEEPIN 0x10 // Sleep in
#define SLEEPOUT 0x11 // Sleep out
#define NORON 0x13 // Normal display mode on
#define INVOFF 0x20 // Display inversion off
#define INVON 0x21 // Display inversion on
#define SETCON 0x25 // Set contrast
#define DISPOFF 0x28 // Display off
#define DISPON 0x29 // Display on
#define CASETP 0x2A // Column address set
#define PASETP 0x2B // Page address set
#define RAMWRP 0x2C // Memory write
#define RGBSET 0x2D // Color set
#define MADCTL 0x36 // Memory data access control
#define COLMOD 0x3A // Interface pixel format
#define DISCTR 0xB9 // Super frame inversion
#define EC 0xC0 // Internal or external oscillator
//*******************************************************
// 12-Bit Color Definitions
//*******************************************************
#define BLACK 0x000
#define NAVY 0x008
#define BLUE 0x00F
#define TEAL 0x088
#define EMERALD 0x0C5
#define GREEN 0x0F0
#define CYAN 0x0FF
#define SLATE 0x244
#define INDIGO 0x408
#define TURQUOISE 0x4ED
#define OLIVE 0x682
#define MAROON 0x800
#define PURPLE 0x808
#define GRAY 0x888
#define SKYBLUE 0x8CE
#define BROWN 0xB22
#define CRIMSON 0xD13
#define ORCHID 0xD7D
#define RED 0xF00
#define MAGENTA 0xF0F
#define ORANGE 0xF40
#define PINK 0xF6A
#define CORAL 0xF75
#define SALMON 0xF87
#define GOLD 0xFD0
#define YELLOW 0xFF0
#define WHITE 0xFFF
//*******************************************************
// Circle Definitions
//*******************************************************
#define FILL 0
//******************************************************
// Arc Definitions
//******************************************************
#define ESE 1
#define ENE 2
#define WSW 3
#define WNW 4
#define SSE 5
#define NNE 6
#define SSW 7
#define NNW 8
#if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
//* Arduino Mega 2560 bit numbers
#define LCD_RES 5 // D8
#define CS 6 // D9
#define DIO 5 // D11
#define SCK_PIN 7 // D13
//* Arduino Mega ports
//* NOTE: See LCDShield::LCDShield() if making changes here
#define LCD_PORT_CS PORTH
#define LCD_PORT_SCK PORTB
#define LCD_PORT_RES PORTH
#define LCD_PORT_DIO PORTB
#elif defined (__AVR_ATmega32U4__)
//* Standard Arduino Leonardo port bits
#define LCD_RES 4 // D8
#define CS 5 // D9
#define DIO 7 // D11
#define SCK_PIN 7 // D13
//* Arduino Leonardo ports:
#define LCD_PORT_RES PORTB
#define LCD_PORT_CS PORTB
#define LCD_PORT_DIO PORTB
#define LCD_PORT_SCK PORTC
#else
//* Arduino Duemilanove bit numbers
#define LCD_RES 0 // D8
#define CS 1 // D9
#define DIO 3 // D11
#define SCK_PIN 5 // D13
//#define LCD_PORT PORTB
//* Arduino Duemilanove ports
#define LCD_PORT_CS PORTB
#define LCD_PORT_SCK PORTB
#define LCD_PORT_RES PORTB
#define LCD_PORT_DIO PORTB
#endif
const unsigned char FONT8x16[97][16] = {
{0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes, ...
{0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes, ...
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ' '
{0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // '!'
{0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // '"'
{0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // '#'
{0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00}, // '$'
{0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00}, // '%'
{0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},
{0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00},
{0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // '0'
{0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00}, // '5'
{0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // ':'
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00},
{0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // 'A'
{0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00}, // 'C'
{0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},
{0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00},
{0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // 'H'
{0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00},
{0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00},
{0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00},
{0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00},
{0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00},
{0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00},
{0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // 'Z'
{0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, // '\'
{0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00},
{0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // '^'
{0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // '_'
{0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00}, // '`'
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // 'a'
{0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00},
{0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00},
{0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00},
{0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00},
{0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00}, // 't'
{0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00}, // 'z'
{0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, // '{'
{0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, // '|'
{0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, // '}'
{0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // '~'
};
static char logo_spark[1120] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfb,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x3f,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x3f,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x7f,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x20,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0f,0xe0,0x9f,0x01,0xfc,0x09,0x9e,0x1e,0x7f,0x70,0x73,0x9f,0x00,0x00,0x00,0x00,
0x3f,0xf1,0xff,0x87,0xfe,0x3f,0xde,0x3d,0xff,0x78,0xf3,0xff,0x80,0x00,0x00,0x00,
0x3c,0xf9,0xff,0xc7,0xdf,0x3f,0xde,0x79,0xff,0x78,0xf3,0xff,0xc0,0x00,0x00,0x00,
0x78,0x79,0xc3,0xcf,0x0f,0x3f,0x1c,0xf0,0x3c,0x78,0xf3,0xe3,0xc0,0x00,0x00,0x00,
0x7c,0x01,0xc1,0xe0,0x0f,0x3e,0x1f,0xe0,0x3c,0x78,0xf3,0xc3,0xc0,0x00,0x00,0x00,
0x3f,0xc1,0x81,0xe0,0x3f,0x3c,0x1f,0xe0,0x3c,0x78,0xf3,0xc1,0xc0,0x00,0x00,0x00,
0x1f,0xf1,0x81,0xe3,0xff,0x3c,0x1f,0xe0,0x3c,0x78,0xf3,0xc1,0xc0,0x00,0x00,0x00,
0x07,0xf9,0x81,0xe7,0xef,0x3c,0x1f,0xf0,0x3c,0x78,0xf3,0xc1,0xc0,0x00,0x00,0x00,
0x00,0xf9,0x81,0xef,0x07,0x3c,0x1e,0xf8,0x3c,0x78,0xf3,0xc1,0xc0,0x00,0x00,0x00,
0x78,0x79,0xc1,0xef,0x0f,0x3c,0x1e,0x78,0x3c,0x78,0xf3,0xc1,0xc0,0x00,0x00,0x00,
0x78,0x79,0xe3,0xcf,0x0f,0x3c,0x1e,0x3c,0x3c,0x7c,0xf3,0xc1,0xc0,0x00,0x00,0x00,
0x3f,0xf9,0xff,0xcf,0xff,0x3c,0x1e,0x3e,0x3c,0x7f,0xf3,0xc1,0xcf,0x00,0x00,0x00,
0x1f,0xf1,0xff,0x87,0xff,0x3c,0x1e,0x1e,0x3c,0x3f,0xf3,0xc1,0xc7,0x00,0x00,0x00,
0x07,0xc1,0x9e,0x03,0xe0,0x00,0x00,0x02,0x00,0x0e,0x20,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x03,0x80,0x00,0x00,0x00,0xc0,0x00,0x00,0x18,0x00,0x00,0x08,0x08,0x00,0x00,
0x00,0x01,0x87,0xc3,0x03,0xe0,0xe1,0xf0,0xf8,0x3e,0x33,0x08,0x3e,0x1e,0x00,0x00,
0x00,0x01,0x86,0x03,0x03,0x01,0xb0,0xe0,0xdc,0x66,0x3b,0x08,0x66,0x32,0x00,0x00,
0x00,0x00,0x87,0xc3,0x03,0xe1,0x80,0x40,0xd8,0x63,0x3b,0x08,0x60,0x3c,0x00,0x00,
0x00,0x00,0x87,0x83,0x03,0xc1,0x80,0x40,0xf8,0x63,0x3f,0x08,0x60,0x0e,0x00,0x00,
0x00,0x00,0x06,0x03,0x03,0x01,0xb0,0x40,0xd8,0x66,0x37,0x08,0x66,0x32,0x00,0x00,
0x00,0x00,0x07,0xc3,0xe3,0xe0,0xe0,0x40,0xc8,0x3e,0x33,0x08,0x3e,0x3e,0x00,0x00,
0x00,0x00,0x07,0xc3,0xe3,0xe0,0xe0,0x40,0x88,0x3c,0x33,0x08,0x3c,0x1e,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
class LCDShield
{
private:
void LCDCommand(unsigned char data);
void LCDData(unsigned char data);
uint8_t driver;
uint16_t swapColors(uint16_t in);
public:
LCDShield();
void init(int type, bool colorSwap = 0);
void clear(int color);
void contrast(char setting);
void setPixel(int color, unsigned char x, unsigned char y);
void setCircle (int x0, int y0, int radius, int color, int lineThickness = 1);
void setArc(int x0, int y0, int radius, int segments[], int numSegments, int lineThickness, int color);
void setChar(char c, int x, int y, int fColor, int bColor);
void setStr(char *pString, int x, int y, int fColor, int bColor);
void setLine(int x0, int y0, int x1, int y1, int color);
void setRect(int x0, int y0, int x1, int y1, unsigned char fill, int color);
void printLogo(void);
void on(void);
void off(void);
};
#endif // ColorLCDShield_H

View file

@ -0,0 +1,247 @@
/*
ChronoLCD Color - An example sketch for the Color LCD Shield Library
by: Jim Lindblom
SparkFun Electronics
date: 6/23/11
license: CC-BY SA 3.0 - Creative commons share-alike 3.0
use this code however you'd like, just keep this license and
attribute. Let me know if you make hugely, awesome, great changes.
This sketch draws an analog and digital clock on the Color LCD
Shield. You can also use the on-board buttons to set the hours
and minutes.
Use the defines at the top of the code to set the initial time.
You can also adjust the size and color of the clock.
To set the time, first hit S3. Then use S1 and S2 to adjust the
hours and minutes respsectively. Hit S3 to start the clock
back up.
This example code should give you a good idea of how to use
the setCircle, setLine, and setStr functions of the Color LCD
Shield Library.
*/
#include <ColorLCDShield.h>
// Enter the time below in 12-hr format
#define HOURS 10
#define MINUTES 21
#define SECONDS 00
#define AMPM 0 // enter 0 for AM, 1 for PM
#define CLOCK_RADIUS 45 // radius of clock face
#define CLOCK_CENTER 50 // If you adjust the radius, you'll probably want to adjust this
#define H_LENGTH 25 // length of hour hand
#define M_LENGTH 35 // length of minute hand
#define S_LENGTH 43 // length of second hand
#define BACKGROUND BLACK // room for growth, adjust the background color according to daylight
#define C_COLOR RED // This is the color of the clock face, and digital clock
#define H_COLOR BLUE // hour hand color
#define M_COLOR GREEN // minute hand color
#define S_COLOR YELLOW // second hand color
LCDShield lcd;
int hours, minutes, seconds, ampm;
int buttonPins[3] = {3, 4, 5};
void setup()
{
/* Set up the button pins as inputs, set pull-up resistor */
for (int i=0; i<3; i++)
{
pinMode(buttonPins[i], INPUT);
digitalWrite(buttonPins[i], HIGH);
}
hours = HOURS;
minutes = MINUTES;
seconds = SECONDS;
ampm = AMPM;
/* Initialize the LCD, set the contrast, clear the screen */
lcd.init(PHILIPS);
lcd.contrast(-63);
lcd.clear(BACKGROUND);
drawClock(); // Draw the clock face, this includes 12, 3, 6, 9
displayAnalogTime(hours, minutes, seconds); // Draw the clock hands
displayDigitalTime(hours, minutes, seconds, ampm); // Draw the digital clock text
}
void loop()
{
/* We'll run around checking for button presses,
until it's been a second */
while(millis() % 1000)
{
if (!digitalRead(buttonPins[2]))
setTime(); // If S3 was pressed, go set the time
}
/* We'll get here if it's been a second. We need to increase
seconds by 1 and then go from there */
seconds++;
if (seconds >= 60)
{
seconds = 0; // If seconds is 60, set it back to 0
minutes++; // and increase minutes by 1
if (minutes >= 60)
{
minutes = 0; // If minutes is 60, set it back to 0
hours++; // and increase hours by 1
if (hours == 12)
ampm ^= 1; // If it's 12 o'clock, flip ampm
if (hours >= 13)
hours = 1; // If hours is 13, set it to 1. 12-hr clock.
}
}
/* Once each second, we'll redraw the clock with new values */
drawClock();
displayAnalogTime(hours, minutes, seconds);
displayDigitalTime(hours, minutes, seconds, ampm);
}
/*
setTime uses on-shield switches S1, S2, and S3 to set the time
pressing S3 will exit the function. S1 increases hours, S2
increases seconds.
*/
void setTime()
{
/* Reset the clock to midnight */
seconds = 0;
minutes = 0;
hours = 12;
ampm = 0;
/* Draw the clock, so we can see the new time */
drawClock();
displayAnalogTime(hours, minutes, seconds);
displayDigitalTime(hours, minutes, seconds, ampm);
while (!digitalRead(buttonPins[2]))
; // wait till they let go of S1
/* We'll run around this loop until S3 is pressed again */
while(digitalRead(buttonPins[2]))
{
/* If S1 is pressed, we'll update the hours */
if (!digitalRead(buttonPins[0]))
{
hours++; // Increase hours by 1
if (hours == 12)
ampm ^= 1; // Flip am/pm if it's 12 o'clock
if (hours >= 13)
hours = 1; // Set hours to 1 if it's 13. 12-hour clock.
/* and update the clock, so we can see it */
drawClock();
displayAnalogTime(hours, minutes, seconds);
displayDigitalTime(hours, minutes, seconds, ampm);
}
if (!digitalRead(buttonPins[1]))
{
minutes++; // Increase minutes by 1
if (minutes >= 60)
minutes = 0; // If minutes is 60, set it back to 0
/* and update the clock, so we can see it */
drawClock();
displayAnalogTime(hours, minutes, seconds);
displayDigitalTime(hours, minutes, seconds, ampm);
}
}
/* Once S3 is pressed, we'll exit, but not until it's released */
while(!digitalRead(buttonPins[2]))
;
}
/*
displayDigitalTime() takes in values for hours, minutes, seconds
and am/pm. It'll print the time, in digital format, on the
bottom of the screen.
*/
void displayDigitalTime(int h, int m, int s, int ap)
{
char timeChar[12];
if (!ap)
{
sprintf(timeChar, "%.2d:%.2d:%.2d AM", h, m, s);
}
else
{
sprintf(timeChar, "%.2d:%.2d:%.2d PM", h, m, s);
}
/* Print the time on the clock */
lcd.setStr(timeChar, CLOCK_CENTER + CLOCK_RADIUS + 4, 22,
C_COLOR, BACKGROUND);
}
/*
drawClock() simply draws the outer circle of the clock, and '12',
'3', '6', and '9'. Room for growth here, if you want to customize
your clock. Maybe add dashe marks, or even all 12 digits.
*/
void drawClock()
{
/* Draw the circle */
lcd.setCircle(CLOCK_CENTER, 66, CLOCK_RADIUS, C_COLOR);
/* Print 12, 3, 6, 9, a lot of arbitrary values are used here
for the coordinates. Just used trial and error to get them
into a nice position. */
lcd.setStr("12", CLOCK_CENTER - CLOCK_RADIUS, 66-9, C_COLOR, BACKGROUND);
lcd.setStr("3", CLOCK_CENTER - 9, 66 + CLOCK_RADIUS - 12, C_COLOR, BACKGROUND);
lcd.setStr("6", CLOCK_CENTER + CLOCK_RADIUS - 18, 66-4, C_COLOR, BACKGROUND);
lcd.setStr("9", CLOCK_CENTER - 9, 66 - CLOCK_RADIUS + 4, C_COLOR, BACKGROUND);
}
/*
displayAnalogTime() draws the three clock hands in their proper
position. Room for growth here, I'd like to make the clock hands
arrow shaped, or at least thicker and more visible.
*/
void displayAnalogTime(int h, int m, int s)
{
double midHours; // this will be used to slightly adjust the hour hand
static int hx, hy, mx, my, sx, sy;
/* Adjust time to shift display 90 degrees ccw
this will turn the clock the same direction as text */
h -= 3;
m -= 15;
s -= 15;
if (h <= 0)
h += 12;
if (m < 0)
m += 60;
if (s < 0)
s += 60;
/* Delete old lines: */
lcd.setLine(CLOCK_CENTER, 66, CLOCK_CENTER+sx, 66+sy, BACKGROUND); // delete second hand
lcd.setLine(CLOCK_CENTER, 66, CLOCK_CENTER+mx, 66+my, BACKGROUND); // delete minute hand
lcd.setLine(CLOCK_CENTER, 66, CLOCK_CENTER+hx, 66+hy, BACKGROUND); // delete hour hand
/* Calculate and draw new lines: */
s = map(s, 0, 60, 0, 360); // map the 0-60, to "360 degrees"
sx = S_LENGTH * sin(3.14 * ((double) s)/180); // woo trig!
sy = S_LENGTH * cos(3.14 * ((double) s)/180); // woo trig!
lcd.setLine(CLOCK_CENTER, 66, CLOCK_CENTER+sx, 66+sy, S_COLOR); // print second hand
m = map(m, 0, 60, 0, 360); // map the 0-60, to "360 degrees"
mx = M_LENGTH * sin(3.14 * ((double) m)/180); // woo trig!
my = M_LENGTH * cos(3.14 * ((double) m)/180); // woo trig!
lcd.setLine(CLOCK_CENTER, 66, CLOCK_CENTER+mx, 66+my, M_COLOR); // print minute hand
midHours = minutes/12; // midHours is used to set the hours hand to middling levels between whole hours
h *= 5; // Get hours and midhours to the same scale
h += midHours; // add hours and midhours
h = map(h, 0, 60, 0, 360); // map the 0-60, to "360 degrees"
hx = H_LENGTH * sin(3.14 * ((double) h)/180); // woo trig!
hy = H_LENGTH * cos(3.14 * ((double) h)/180); // woo trig!
lcd.setLine(CLOCK_CENTER, 66, CLOCK_CENTER+hx, 66+hy, H_COLOR); // print hour hand
}

View file

@ -0,0 +1,41 @@
// This Sample Created by Tony Contrada (2/22/2013) for use with the Sparkfun Color LCD Shield
// with the updated Arduino Color LCD Library.
// This sample sketch illustrates the new setArf method and an updated setCircle method
// which includes setting a Line Thickness in Pixels and the ability to Fill-In the circle.
#include <ColorLCDShield.h>
LCDShield lcd; // Creates an LCDShield, named lcd
void setup()
{
lcd.init(PHILIPS); // Initializes lcd, using an PHILIPSdriver
lcd.contrast(-64); // -51's usually a good contrast value
lcd.clear(BLACK); // clear the screen
//Creates RED Arc in the ENE Quadrant with a Line Thickness of 5 Pixels
int segmentsRed[1] = {ENE};
lcd.setArc(60,50,40,segmentsRed,sizeof(segmentsRed),5,RED);
//Creates YELLOW Arc in the NNE Quadrant with a Line Thickness of 10 Pixels
int segmentsYellow[1] = {NNE};
lcd.setArc(60,50,40,segmentsYellow,sizeof(segmentsYellow),10,YELLOW);
//Creates GREEN Arc in the WNW and NNW Quadrants with a FILL
int segments[2] = {WNW,NNW};
lcd.setArc(60,50,40,segments,sizeof(segments),FILL,GREEN);
//Creates PINK Circle with a FILL
lcd.setCircle(90,100,20,PINK,FILL);
//Creates CYAN Circle with a Line Thickness of 3 Pixels
lcd.setCircle(90,35,25,CYAN,3);
}
void loop()
{
}

View file

@ -0,0 +1,79 @@
/*
TestPattern - An example sketch for the Color LCD Shield Library
by: Jim Lindblom
SparkFun Electronics
date: 6/23/11
license: CC-BY SA 3.0 - Creative commons share-alike 3.0
use this code however you'd like, just keep this license and
attribute. Let me know if you make hugely, awesome, great changes.
This sketch has example usage of the Color LCD Shield's three
buttons. It also shows how to use the setRect and contrast
functions.
Hit S1 to increase the contrast, S2 decreases the contrast, and
S3 sets the contrast back to the middle.
*/
#include <ColorLCDShield.h>
LCDShield lcd;
int buttons[3] = {3, 4, 5}; // S1 = 3, S2 = 4, S3 = 5
signed char cont = -51; // Philips medium contrast
//signed char cont = 40; // Epson medium contrast
void setup()
{
Serial.begin(9600);
for (int i=0; i<3; i++)
{
pinMode(buttons[i], INPUT); // Set buttons as inputs
digitalWrite(buttons[i], HIGH); // Activate internal pull-up
}
// Initialize the LCD, try using EPSON if it's not working
lcd.init(PHILIPS);
// lcd.init(PHILIPS, 1); // Philips init with colors swapped. (Try this if red makes blue, etc).
lcd.contrast(cont); // Initialize contrast
lcd.clear(WHITE); // Set background to white
lcd.printLogo(); // Print SparkFun test logo
testPattern(); // Print color bars on bottom of screen
}
void loop()
{
while(digitalRead(buttons[0])&&digitalRead(buttons[1])&&digitalRead(buttons[2]))
; // Wait, do nothing, until a button is pressed
if (!digitalRead(buttons[0])) // If S1 is hit, increase contrast
{
cont++;
if (cont > 63) // Philips contrast goes from 63 to -64
cont = -64;
}
else if (!digitalRead(buttons[1])) // If s2 is hit, decrease contrast
{
cont--;
if (cont < -64)
cont = 63;
}
else if (!digitalRead(buttons[2])) // If S3 is hit, reset contrast
{
cont = 0;
}
lcd.contrast(cont); // give LCD contrast command
Serial.println(cont);
delay(100); // Delay to give each button press a little more meaning
}
void testPattern()
{
lcd.setRect(80, 2, 131, 19, 1, WHITE);
lcd.setRect(80, 19, 131, 35, 1, YELLOW);
lcd.setRect(80, 35, 131, 51, 1, CYAN);
lcd.setRect(80, 51, 131, 67, 1, GREEN);
lcd.setRect(80, 67, 131, 83, 1, MAGENTA);
lcd.setRect(80, 83, 131, 99, 1, RED);
lcd.setRect(80, 99, 131, 115, 1, BLUE);
lcd.setRect(80, 115, 131, 131, 1, BLACK);
}

View file

@ -0,0 +1,87 @@
/*
ZanyCircles - An example sketch for the Color LCD Shield Library
by: Jim Lindblom
SparkFun Electronics
date: 6/23/11
license: CC-BY SA 3.0 - Creative commons share-alike 3.0
use this code however you'd like, just keep this license and
attribute. Let me know if you make hugely, awesome, great changes.
This simple sketch shows how you can use setCircle and setPixel
with the Color LCD Shield library.
*/
#include <ColorLCDShield.h>
#define CIRCLES 10 // Number of zany circles in display
#define BACKGROUND ORANGE // Color of background
#define FOREGROUND BLUE // color of circles
int radius = 1; // size of circles
int jump = 5; // +/- of possible jump
int xCir[CIRCLES]; // center points of circles
int yCir[CIRCLES]; // cetner points of circles
LCDShield lcd;
void setup()
{
lcd.init(PHILIPS); // Try EPSON if this doesn't work. If colors are swapped try init(PHILIPS, 1)
lcd.contrast(-51); // Feel free to change this for visibility, values between 0 and 60
lcd.clear(BACKGROUND);
// Initilize all circles' center points
for (int i=0; i<CIRCLES; i++)
{
//xCir[i] = random(2, 131); // random starting points
//yCir[i] = random(2, 131);
xCir[i] = 66; // start in the middle
yCir[i] = 66;
// Circles must be stuck inside the box:
if (xCir[i] >= 131-radius)
xCir[i] = 131-radius;
if (xCir[i] <= radius)
xCir[i] = radius;
if (yCir[i] >= 131-radius)
yCir[i] = 131-radius;
if (yCir[i] <= radius)
yCir[i] = radius;
}
}
void loop()
{
for (int i=0; i<CIRCLES; i++)
{
// add a random number to x, y
xCir[i] += random(-jump, jump+1);
yCir[i] += random(-jump, jump+1);
// Circles must be stuck inside the box:
if (xCir[i] >= 131-radius)
xCir[i] = 131-radius;
if (xCir[i] <= radius)
xCir[i] = radius;
if (yCir[i] >= 131-radius)
yCir[i] = 131-radius;
if (yCir[i] <= radius)
yCir[i] = radius;
}
for (int i=0; i<CIRCLES; i++)
{
for (int j=1; j<=radius; j++)
{
lcd.setCircle(xCir[i], yCir[i], j, FOREGROUND); // draw the new circle
lcd.setPixel(FOREGROUND, xCir[i], yCir[i]); // fill in the center of the new circle
}
}
delay(50); // Little delay for visibility
for (int i=0; i<CIRCLES; i++)
{
for (int j=1; j<=radius; j++)
{
lcd.setCircle(xCir[i], yCir[i], j, BACKGROUND); // clear the circle
lcd.setPixel(BACKGROUND, xCir[i], yCir[i]); // clear center of circle
}
}
}

View file

@ -0,0 +1,28 @@
#######################################
# Syntax Coloring Map For Twitter
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
LCDShield KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
init KEYWORD2
clear KEYWORD2
contrast KEYWORD2
setPixel KEYWORD2
setChar KEYWORD2
setStr KEYWORD2
setLine KEYWORD2
setRect KEYWORD2
setCircle KEYWORD2
setArc KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################