├── CACHE.HTM ├── LCD.cpp ├── LCD.h ├── LCDfont.h ├── PIP_07.ino ├── README.md └── tags.h /CACHE.HTM: -------------------------------------------------------------------------------- 1 | ____ __ ____ 2 | / __ \ / / / __ \ 3 | / /_/ / / / / /_/ / 4 | / ____/ / / / ____/ 5 | / / / / / / 6 | /_/ /_/ /_/ 7 | 8 | PIP Micro Web Browser v0.7 (c) Chris Anderson 2014 9 | -------------------------------------------------------------------------------- /LCD.cpp: -------------------------------------------------------------------------------- 1 | #include "LCD.h" 2 | #include "LCDfont.c" 3 | #include 4 | #include "pins_arduino.h" 5 | #include "wiring_private.h" 6 | //#include 7 | #include 8 | 9 | #define SCLK 13 // Don't change 10 | #define MOSI 11 // Don't change 11 | #define CS 9 12 | #define DC 8 13 | #define RST 7 // you can also connect this to the Arduino reset 14 | 15 | #define DELAY 0x80 16 | 17 | #define TFT_CASET 0x2A 18 | #define TFT_RASET 0x2B 19 | #define TFT_RAMWR 0x2C 20 | 21 | // SPI/TFT setup 22 | volatile uint8_t *csport, *rsport; 23 | uint8_t datapinmask, clkpinmask, cspinmask, rspinmask; 24 | 25 | 26 | //================================================ 27 | // LCD object init 28 | //================================================ 29 | LCD::LCD (int16_t w, int16_t h): 30 | WIDTH(w), HEIGHT(h), CURSOR_WIDTH(w / TEXTWIDTH), CURSOR_HEIGHT (h / TEXTHEIGHT) { 31 | cursorX = 0; 32 | cursorY = 0; 33 | textColour = 0xFFFF; 34 | bgColour = 0x0000; 35 | wrap = true; 36 | } 37 | 38 | //================================================ 39 | // SPI write commands 40 | //================================================ 41 | void spiwrite (uint8_t c) { 42 | SPDR = c; 43 | while (!(SPSR & _BV(SPIF))); 44 | } 45 | 46 | void writecommand (uint8_t c) { 47 | *rsport &= ~rspinmask; 48 | *csport &= ~cspinmask; 49 | spiwrite (c); 50 | *csport |= cspinmask; 51 | } 52 | 53 | void writedata (uint8_t c) { 54 | *rsport |= rspinmask; 55 | *csport &= ~cspinmask; 56 | spiwrite (c); 57 | *csport |= cspinmask; 58 | } 59 | 60 | void setAddrWindow (uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { 61 | writecommand (TFT_CASET); // Column addr set 62 | writedata (y0 >> 8); 63 | writedata (y0 & 0xff); // YSTART 64 | writedata (y1 >> 8); 65 | writedata (y1 & 0xff); // YEND 66 | writecommand (TFT_RASET); // Row addr set 67 | writedata (x0 >> 8); 68 | writedata (x0 & 0xff); // XSTART 69 | writedata (x1 >> 8); 70 | writedata (x1 & 0xff); // XEND 71 | writecommand (TFT_RAMWR); // write to RAM 72 | } 73 | 74 | 75 | //================================================ 76 | // LCD init code store 77 | //================================================ 78 | static const uint8_t PROGMEM LCDinit[] = { 79 | 21, 80 | 0xcb, 5, 0x39, 0x2c, 0x00, 0x34, 0x02, 81 | 0xcf, 3, 0x00, 0xc1, 0x30, 82 | 0xe8, 3, 0x85, 0x00, 0x78, 83 | 0xea, 2, 0x00, 0x00, 84 | 0xed, 4, 0x64, 0x03, 0x12, 0x81, 85 | 0xf7, 1, 0x20, 86 | 0xc0, 1, 0x23, 87 | 0xc1, 1, 0x10, 88 | 0xc5, 2, 0x3e, 0x28, 89 | 0xc7, 1, 0x86, 90 | 0x36, 1, 0x08, 91 | 0x3a, 1, 0x55, 92 | 0xb1, 2, 0x00, 0x18, 93 | 0xb6, 3, 0x08, 0x82, 0x27, 94 | 0xf2, 1, 0x00, 95 | 0x26, 1, 0x01, 96 | 0xe0, 15, 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1, 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00, 97 | 0xe1, 15, 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x031, 0xc1, 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f, 98 | 0x11, 0+DELAY, 120, 99 | 0x29, 0, 100 | 0x2c, 0 101 | }; 102 | //0x08, 103 | 104 | //================================================ 105 | // LCD init code handler 106 | //================================================ 107 | void commandList (const uint8_t *addr) { 108 | uint8_t numCommands, numArgs; 109 | uint16_t ms; 110 | 111 | numCommands = pgm_read_byte (addr++); // Number of commands to follow 112 | 113 | while (numCommands--) { // For each command... 114 | writecommand (pgm_read_byte (addr++)); // Read, issue command 115 | numArgs = pgm_read_byte (addr++); // Number of args to follow 116 | ms = numArgs & DELAY; // If hibit set, delay follows args 117 | numArgs &= ~DELAY; // Mask out delay bit 118 | while (numArgs--) { // For each argument... 119 | writedata (pgm_read_byte (addr++)); // Read, issue argument 120 | } 121 | if (ms) { 122 | ms = pgm_read_byte (addr++); // Read post-command delay time (ms) 123 | if (ms == 255) ms = 500; // If 255, delay for 500 ms 124 | delay (ms); 125 | } 126 | } 127 | } 128 | 129 | 130 | //================================================ 131 | // Init LCD object and LCD panel 132 | //================================================ 133 | void LCD::init() { 134 | pinMode (DC, OUTPUT); 135 | pinMode (CS, OUTPUT); 136 | pinMode (RST, OUTPUT); 137 | csport = portOutputRegister(digitalPinToPort(CS)); 138 | rsport = portOutputRegister(digitalPinToPort(DC)); 139 | cspinmask = digitalPinToBitMask(CS); 140 | rspinmask = digitalPinToBitMask(DC); 141 | 142 | SPI.begin(); 143 | //SPI.setClockDivider (SPI_CLOCK_DIV4); // 4 MHz (half speed) 144 | //Due defaults to 4mHz (clock divider setting of 21) 145 | SPI.setBitOrder (MSBFIRST); 146 | SPI.setDataMode (SPI_MODE0); 147 | 148 | // toggle RST low to reset; CS low so it'll listen to us 149 | *csport &= ~cspinmask; 150 | digitalWrite (RST, HIGH); 151 | delay (10); 152 | digitalWrite (RST, LOW); 153 | delay (10); 154 | digitalWrite (RST, HIGH); 155 | delay (10); 156 | 157 | commandList (LCDinit); 158 | digitalWrite (CS, HIGH); 159 | 160 | fillRect (0 ,0, WIDTH, HEIGHT, BLACK); 161 | } 162 | 163 | 164 | //================================================ 165 | // LCD write 166 | //================================================ 167 | size_t LCD::write (uint8_t c) { 168 | if (c == '\n') { 169 | // fillRect (cursorX, cursorY, WIDTH - cursorX, TEXTHEIGHT, bgColour); // Blank rest of line 170 | cursorX = 0; 171 | cursorY += TEXTHEIGHT; 172 | if (cursorY == CURSOR_HEIGHT) return 1; 173 | } 174 | else if (c != '\r') { // Skip '\r' 175 | drawChar(cursorX, cursorY, c, textColour, bgColour); 176 | cursorX += TEXTWIDTH; 177 | if (wrap && (cursorX > (WIDTH - TEXTWIDTH))) { 178 | cursorX = 0; 179 | cursorY += TEXTHEIGHT; 180 | if (cursorY > HEIGHT) cursorY = 1; 181 | } 182 | } 183 | return 1; 184 | } 185 | 186 | //================================================ 187 | // LCD draw character 188 | //================================================ 189 | void LCD::drawChar (int16_t x, int16_t y, unsigned char c, uint16_t colour, uint16_t bg) { 190 | unsigned char charData; 191 | 192 | if((x >= WIDTH) || (y >= HEIGHT) || ((x + TEXTWIDTH - 1) < 0) || ((y + TEXTHEIGHT - 1) < 0)) 193 | return; 194 | 195 | c -= 32; // Shift ASCII to font array values 196 | if ((c < 0) || (c > 97)) c = 97; 197 | 198 | uint8_t fhi = colour >> 8, flo = colour & 0xff; 199 | uint8_t bhi = bg >> 8, blo = bg & 0xff; 200 | 201 | setAddrWindow (x, y, x + TEXTWIDTH - 1, y + TEXTHEIGHT - 1); 202 | 203 | *rsport |= rspinmask; 204 | *csport &= ~cspinmask; 205 | 206 | for (int8_t i = 0; i < TEXTWIDTH; i++ ) { 207 | charData = pgm_read_byte (font + (c * (TEXTWIDTH - 1)) + i); 208 | 209 | for (int8_t j = 0; j < TEXTHEIGHT; j++) { 210 | 211 | if ((i < (TEXTWIDTH -1)) && ((charData >> j) & 0x01)) { 212 | spiwrite (fhi); 213 | spiwrite (flo); 214 | } 215 | else { 216 | spiwrite (bhi); 217 | spiwrite (blo); 218 | } 219 | 220 | } 221 | } 222 | 223 | *csport |= cspinmask; 224 | 225 | } 226 | 227 | 228 | //================================================ 229 | // Filled rectangle 230 | //================================================ 231 | void LCD::fillRect (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t colour) { 232 | 233 | if ((x >= WIDTH) || (y >= HEIGHT)) return; 234 | if ((x + --w) >= WIDTH) w = WIDTH - x - 1; 235 | if ((y + --h) >= WIDTH) h = WIDTH - y - 1; 236 | 237 | setAddrWindow (x, y, x + w, y + h); 238 | 239 | uint8_t hi = colour >> 8; 240 | uint8_t lo = colour & 0xff; 241 | *rsport |= rspinmask; 242 | *csport &= ~cspinmask; 243 | 244 | for (y = h; y >= 0; y--) { 245 | for (x = w; x >= 0; x--) { 246 | spiwrite (hi); 247 | spiwrite (lo); 248 | } 249 | } 250 | *csport |= cspinmask; 251 | } 252 | 253 | 254 | //================================================ 255 | // Utility functions 256 | //================================================ 257 | void LCD::setCursor (int16_t x, int16_t y) { 258 | cursorX = x * TEXTWIDTH; 259 | cursorY = y * TEXTHEIGHT; 260 | } 261 | 262 | void LCD::setTextColour (uint16_t c) { 263 | textColour = c; 264 | } 265 | 266 | void LCD::setBGColour (uint16_t b) { 267 | bgColour = b; 268 | } 269 | 270 | int16_t LCD::getTextColour () { 271 | return textColour; 272 | } 273 | 274 | int16_t LCD::getBGColour () { 275 | return bgColour; 276 | } 277 | 278 | void LCD::setTextWrap (boolean w) { 279 | wrap = w; 280 | } 281 | 282 | int16_t LCD::getCursorX() { 283 | return cursorX; 284 | } 285 | 286 | int16_t LCD::getCursorY() { 287 | return cursorY; 288 | } 289 | -------------------------------------------------------------------------------- /LCD.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_H 2 | #define _LCD_H 3 | 4 | #include "Arduino.h" 5 | #include "Print.h" 6 | 7 | #define BLACK 0x0000 8 | #define RED 0xF800 9 | #define GREEN 0x07E0 10 | #define BLUE 0x001F 11 | #define YELLOW 0xFFE0 12 | #define MAGENTA 0xF81F 13 | #define CYAN 0x07FF 14 | #define WHITE 0xFFFF 15 | #define GREY 0x632C 16 | 17 | #define TEXTWIDTH 6 18 | #define TEXTHEIGHT 8 19 | 20 | class LCD : 21 | public Print { 22 | 23 | public: 24 | LCD(int16_t w, int16_t h); 25 | 26 | void init(); 27 | 28 | void fillRect (int16_t x, int16_t y, int16_t w, int16_t h, uint16_t colour); 29 | void drawChar (int16_t x, int16_t y, unsigned char c, uint16_t colour, uint16_t bg); 30 | 31 | virtual size_t write (uint8_t); 32 | 33 | void setCursor (int16_t x, int16_t y); 34 | void setTextColour (uint16_t c); 35 | void setBGColour (uint16_t bg); 36 | int16_t getTextColour (); 37 | int16_t getBGColour (); 38 | void setTextWrap (boolean w); 39 | int16_t getCursorX(); 40 | int16_t getCursorY(); 41 | 42 | const int16_t WIDTH, HEIGHT; 43 | const int16_t CURSOR_WIDTH, CURSOR_HEIGHT; 44 | 45 | protected: 46 | int16_t cursorX, cursorY; 47 | uint16_t textColour, bgColour; 48 | boolean wrap; // If set, 'wrap' text at right edge of display 49 | }; 50 | 51 | #endif // _LCD_H 52 | -------------------------------------------------------------------------------- /LCDfont.h: -------------------------------------------------------------------------------- 1 | #ifndef _FONT_C 2 | #define _FONT_C 3 | 4 | // #include 5 | #include 6 | 7 | // Standard ASCII 5x7 font for chars 32+ 8 | static const char font[] PROGMEM = { 9 | 0x00, 0x00, 0x00, 0x00, 0x00, // Space 10 | 0x00, 0x00, 0x5F, 0x00, 0x00, // ! 11 | 0x00, 0x07, 0x00, 0x07, 0x00, // " 12 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 13 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 14 | 0x23, 0x13, 0x08, 0x64, 0x62, 15 | 0x36, 0x49, 0x56, 0x20, 0x50, 16 | 0x00, 0x08, 0x07, 0x03, 0x00, 17 | 0x00, 0x1C, 0x22, 0x41, 0x00, 18 | 0x00, 0x41, 0x22, 0x1C, 0x00, 19 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 20 | 0x08, 0x08, 0x3E, 0x08, 0x08, 21 | 0x00, 0x80, 0x70, 0x30, 0x00, 22 | 0x08, 0x08, 0x08, 0x08, 0x08, 23 | 0x00, 0x00, 0x60, 0x60, 0x00, 24 | 0x20, 0x10, 0x08, 0x04, 0x02, 25 | 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 26 | 0x00, 0x42, 0x7F, 0x40, 0x00, 27 | 0x72, 0x49, 0x49, 0x49, 0x46, 28 | 0x21, 0x41, 0x49, 0x4D, 0x33, 29 | 0x18, 0x14, 0x12, 0x7F, 0x10, 30 | 0x27, 0x45, 0x45, 0x45, 0x39, 31 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 32 | 0x41, 0x21, 0x11, 0x09, 0x07, 33 | 0x36, 0x49, 0x49, 0x49, 0x36, 34 | 0x46, 0x49, 0x49, 0x29, 0x1E, // 9 35 | 0x00, 0x00, 0x14, 0x00, 0x00, 36 | 0x00, 0x40, 0x34, 0x00, 0x00, 37 | 0x00, 0x08, 0x14, 0x22, 0x41, 38 | 0x14, 0x14, 0x14, 0x14, 0x14, 39 | 0x00, 0x41, 0x22, 0x14, 0x08, 40 | 0x02, 0x01, 0x59, 0x09, 0x06, 41 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 42 | 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 43 | 0x7F, 0x49, 0x49, 0x49, 0x36, 44 | 0x3E, 0x41, 0x41, 0x41, 0x22, 45 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 46 | 0x7F, 0x49, 0x49, 0x49, 0x41, 47 | 0x7F, 0x09, 0x09, 0x09, 0x01, 48 | 0x3E, 0x41, 0x41, 0x51, 0x73, 49 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 50 | 0x00, 0x41, 0x7F, 0x41, 0x00, 51 | 0x20, 0x40, 0x41, 0x3F, 0x01, 52 | 0x7F, 0x08, 0x14, 0x22, 0x41, 53 | 0x7F, 0x40, 0x40, 0x40, 0x40, 54 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 55 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 56 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 57 | 0x7F, 0x09, 0x09, 0x09, 0x06, 58 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 59 | 0x7F, 0x09, 0x19, 0x29, 0x46, 60 | 0x26, 0x49, 0x49, 0x49, 0x32, 61 | 0x03, 0x01, 0x7F, 0x01, 0x03, 62 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 63 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 64 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 65 | 0x63, 0x14, 0x08, 0x14, 0x63, 66 | 0x03, 0x04, 0x78, 0x04, 0x03, 67 | 0x61, 0x59, 0x49, 0x4D, 0x43, // Z 68 | 0x00, 0x7F, 0x41, 0x41, 0x41, 69 | 0x02, 0x04, 0x08, 0x10, 0x20, 70 | 0x00, 0x41, 0x41, 0x41, 0x7F, 71 | 0x04, 0x02, 0x01, 0x02, 0x04, 72 | 0x40, 0x40, 0x40, 0x40, 0x40, 73 | 0x00, 0x03, 0x07, 0x08, 0x00, 74 | 0x20, 0x54, 0x54, 0x78, 0x40, // a 75 | 0x7F, 0x28, 0x44, 0x44, 0x38, 76 | 0x38, 0x44, 0x44, 0x44, 0x28, 77 | 0x38, 0x44, 0x44, 0x28, 0x7F, 78 | 0x38, 0x54, 0x54, 0x54, 0x18, 79 | 0x00, 0x08, 0x7E, 0x09, 0x02, 80 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 81 | 0x7F, 0x08, 0x04, 0x04, 0x78, 82 | 0x00, 0x44, 0x7D, 0x40, 0x00, 83 | 0x20, 0x40, 0x40, 0x3D, 0x00, 84 | 0x7F, 0x10, 0x28, 0x44, 0x00, 85 | 0x00, 0x41, 0x7F, 0x40, 0x00, 86 | 0x7C, 0x04, 0x78, 0x04, 0x78, 87 | 0x7C, 0x08, 0x04, 0x04, 0x78, 88 | 0x38, 0x44, 0x44, 0x44, 0x38, 89 | 0xFC, 0x18, 0x24, 0x24, 0x18, 90 | 0x18, 0x24, 0x24, 0x18, 0xFC, 91 | 0x7C, 0x08, 0x04, 0x04, 0x08, 92 | 0x48, 0x54, 0x54, 0x54, 0x24, 93 | 0x04, 0x04, 0x3F, 0x44, 0x24, 94 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 95 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 96 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 97 | 0x44, 0x28, 0x10, 0x28, 0x44, 98 | 0x4C, 0x90, 0x90, 0x90, 0x7C, // y 99 | 0x44, 0x64, 0x54, 0x4C, 0x44, // z 100 | 0x00, 0x08, 0x36, 0x41, 0x00, // { 101 | 0x00, 0x00, 0x7f, 0x00, 0x00, // | 102 | 0x00, 0x41, 0x36, 0x08, 0x00, // } 103 | 0x02, 0x01, 0x02, 0x04, 0x02, // ~ 126 104 | 0x18, 0x3c ,0x18, 0x00, 0x00, // Bullet point (not ASCII) 127 105 | 0x00, 0x00 ,0x00, 0x00, 0x00, //   128 106 | 0x00, 0x7F, 0x41, 0x41, 0x7F // Unprintable characters 129 107 | }; 108 | #endif // _FONT_C 109 | -------------------------------------------------------------------------------- /PIP_07.ino: -------------------------------------------------------------------------------- 1 | /*================================================ 2 | ================================================= 3 | #### ### #### 4 | # # # # # 5 | # # # # # 6 | #### # #### 7 | # # # 8 | # # # 9 | # ### # 10 | 11 | PIP Micro Web Browser v0.7 12 | Suitable for 32KB Arduino/ATmega use. 13 | 14 | (c) Chris Anderson 2014. 15 | 16 | Creative Commons license: 17 | Creative Commons Attribution 4.0 International License 18 | http://creativecommons.org/licenses/by/4.0/ 19 | 20 | PIP is a functional but incomplete web browser for Arduino and runs 21 | well on an Uno. It can download and render plain HTML (no images, CSS 22 | or Javascript) and follow embedded links. It's joystick controlled 23 | and uses a 320x240 LCD screen for output. 24 | 25 | The Ethernet and SD card libraries use about 20KB of code, so the LCD 26 | driver, HTML parser and renderer squeeze in under 12KB. 27 | 28 | Requires: 29 | 30 | * Arduino Uno or similiar ATmega 328 powered board 31 | * Wiz5100 powered Ethernet board with SD card slot (SPI CS = 10 & 4) 32 | * 320x240 TFT LCD screen (SPI CS = 9) Found here: http://tinyurl.com/tftlcd 33 | * Analogue joystick with button (PS2 style) 34 | 35 | Installation: 36 | 37 | * Plug an SD card (MAXIMUM 2GB) into your computer and copy the file 38 | "CACHE.HTM" from this enclosing folder into the root level of the card. 39 | * Download the file "HOME.HTM" from the URL below and put it in the enclosing 40 | folder. Then copy the file to the root level of the SD card. 41 | https://www.dropbox.com/s/v8h2d94uxxcw1oj/HOME.HTM?dl=0 42 | * Put the SD card into your Ethernet shield and upload PIP to your Arduino. 43 | * Rename the enclosing folder of this file to "PIP_07.ino". 44 | * Copy the enclosing folder into you local Arduino sketch folder, as per 45 | usual for new programs. 46 | 47 | Wiring for LCD: 48 | Name Pin 49 | SCLK 13 Clock 50 | MOSI 11 Master Out - Don't change or you loose hardware assisted speed 51 | CS 9 Chip Select 52 | DC 8 Data/Comand 53 | RST 7 Reset 54 | LED Arduino 3.3v 55 | VCC Arduino 5v 56 | GND Ground 57 | 58 | Wiring for joystick: 59 | VRx A0 - Analogue input 0 60 | VRy A1 61 | SW A2 62 | VCC Arduino 5v 63 | GND Ground 64 | 65 | Notes: 66 | 67 | Handles a sub-set of HTML tags. See tags.h file for list. 68 | 69 | HTML pages over 20KB or so can stall and fail somewhat randomly. The Wiz5100 70 | just doesn't seem to like dripping data to an Arduino much. Over 1KB/sec 71 | download speed can be cosidered 'good'. 72 | 73 | Occationally when the browser crashes during a render, the HOME.HTM can get 74 | corrupted. Just copy the file in the enclosing folder back onto the SD card. 75 | 76 | Due to poor Ethernet and SD card interaction on the SPI bus, the cace file 77 | on the SD card is held open as long as possible and only closed and re-opened 78 | during HTML download and parsing. That seems to make things ore reliable. 79 | 80 | HTML files are parsed and made partially binary before being stored on the CD card. 81 | File are generally around 50% smaller when unused junk is removed. The stored 82 | file will be truncated to 64KB as 16 bit pointers are being used for page and 83 | URL indexing. 84 | May fix this by going to relative pointers. 85 | 86 | Currently, URLs over 90 characters in size are truncated. This will undoubtably 87 | break them, or results in 404 errors. Which aren't handled well yet. 88 | 89 | The LCD screen is used via a custom library (very similar to the Adafruit GFX 90 | library) which only implements rectangle and character drawing to save space. 91 | As only rectangle drawing and the print command are used, it should be easy to 92 | adapt PIP to use a different LCD. 93 | 94 | Doesn't do images. Come on, there's only 2KB of memory and a tiny screen 95 | to play with! JPEG parsing might be problematic as there's only 2KB of 96 | program space free. 97 | 98 | Forms are not even attempted. There's no keyboard, so good luck with that. 99 | 100 | To do: 101 | Handle state case when a page break the middle of a tag. 102 | 103 | v0.7 14/10/2014 104 | Fixed exception for 17 | #define PIP 546 // custom tag 18 | 19 | // Use non-printable ASCII characters for tag codes 20 | #define TAG_CR 14 // ~ 21 | #define TAG_HEADING1 15 // [ 22 | #define TAG_HEADING2 16 // ] 23 | #define TAG_BOLD1 17 // ( 24 | #define TAG_BOLD2 18 // ) 25 | #define TAG_LINK1 19 // { 28 | #define TAG_HR 22 // % 29 | #define TAG_LIST 23 // * 30 | #define TAG_PRE 24 // ` 31 | #define TAG_PRE2 25 // ' 32 | #define TAG_HTTP 26 // http:// 33 | 34 | /* 35 | #define TAG_CR 182 //¶ 14 // ~ 36 | #define TAG_HEADING1 167 //§ 15 // [ 37 | #define TAG_HEADING2 168 //¨ 16 // ] 38 | #define TAG_BOLD1 185 //¹ 17 // ( 39 | #define TAG_BOLD2 186 //º 18 // ) 40 | #define TAG_LINK1 188 //¼ 19 // { 43 | #define TAG_HR 172 //¬ 22 // % 44 | #define TAG_LIST 164 //¤ 23 // * 45 | #define TAG_PRE 162 //¢ 24 // ` 46 | #define TAG_PRE2 163 //£ 25 // ' 47 | #define TAG_HTTP 187 //» 26 // http:// 48 | */ 49 | 50 | // Hash flags and masks 51 | #define INLINE 0x8000 // High bit flag for tag allowing post spaces 52 | #define PRE_BREAK 0x4000 // High bit flag for pre-tag render break 53 | #define POST_BREAK 0x2000 // High bit flag for post tag break 54 | #define ATTR_MASK 0x1fff // Mask to remove high bit flags 55 | 56 | // Hash -> tag & flag mappings 57 | #define NUMTAGS 76 58 | static const uint16_t tag_codes[] PROGMEM = { 59 | 161, TAG_HEADING1 | PRE_BREAK, //

60 | 162, TAG_HEADING1 | PRE_BREAK, //

61 | 163, TAG_HEADING1 | PRE_BREAK, //

62 | 164, TAG_HEADING1 | PRE_BREAK, //

63 | 80, TAG_CR | PRE_BREAK, //

64 | 226, TAG_HR | PRE_BREAK | POST_BREAK, //


65 | 246, TAG_CR | PRE_BREAK, //
    66 | 234, TAG_CR | PRE_BREAK, //
      67 | 225, TAG_LIST | PRE_BREAK, //
    1. 68 | PRETAG, TAG_PRE | PRE_BREAK, //
       69 | 
       70 |   221,   TAG_HEADING2 | POST_BREAK,          // 

71 | 222, TAG_HEADING2 | POST_BREAK, // 72 | 223, TAG_HEADING2 | POST_BREAK, // 73 | 224, TAG_HEADING2 | POST_BREAK, // 74 | 75 | 443, TAG_CR | POST_BREAK, //
76 | 214, TAG_CR | POST_BREAK, //
77 | 110, TAG_CR | POST_BREAK, //

78 | 294, TAG_CR | POST_BREAK, // 79 | 306, TAG_CR | POST_BREAK, // 80 | 285, TAG_CR | POST_BREAK, // 81 | PRETAGEND, TAG_PRE2 | POST_BREAK, // 82 | 83 | 66, TAG_BOLD1 | INLINE, // 84 | 96, TAG_BOLD2 | INLINE, // 85 | 5199, TAG_BOLD1 | INLINE, // 86 | 6159, TAG_BOLD2 | INLINE, // 87 | 65, TAG_LINK1 | INLINE, //
88 | HREFTAG, TAG_LINK2 | INLINE, // URL 89 | 95, TAG_LINK3 | INLINE, // 90 | 91 | 1428, 38, // Ampersand 92 | 2682, 96, // 8216; Curly single quote 93 | 2683, 39, // 8217; Curly single quote 94 | 6460, 128, // nbsp; 95 | 2680, 34, // 8220; Curly double quotes 96 | 2681, 34, // 8221; Curly double quotes 97 | 2677, 45, // 8211; Hyphens en 98 | 2678, 45, // 8212; Hyphens em 99 | 368, 62, // Greater than 100 | 388, 60 // Less than 101 | }; 102 | --------------------------------------------------------------------------------