changeset 212:d1725a29353f main

First version of the ILI9340 LCD driver module.
author Bob Cook <bob@bobcookdev.com>
date Sat, 10 May 2014 08:13:43 -0700
parents ddd95e6ede8a
children 8245c6f136b5
files main/packages/avr/lcd/ili9340/ili9340.cpp main/packages/avr/lcd/ili9340/ili9340.h main/packages/avr/lcd/ili9340/jamfile
diffstat 3 files changed, 1245 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/packages/avr/lcd/ili9340/ili9340.cpp	Sat May 10 08:13:43 2014 -0700
@@ -0,0 +1,916 @@
+// ----------------------------------------------------------------------------------------
+//
+//  avr/lcd/ili9340/ili9340.cpp
+//    
+//  Bob Cook Development, Robotics Library
+//  http://www.bobcookdev.com/rl/
+//    
+//  This file implements support for the ILI9340 240x320 RGB LCD driver.
+//
+//  Copyright (C) 2014 Bob Cook
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//  
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//  
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+//  Portions copied from "Adafruit_ILI9340" written by Limor Fried, Adafruit Industries.
+//  See https://github.com/adafruit/Adafruit_ILI9340
+//
+//  Portions copied from "Nokia 6100 LCD Display Driver" written by James P. Lynch.
+//  See http://www.sparkfun.com/tutorial/Nokia%206100%20LCD%20Display%20Driver.pdf
+//
+// ----------------------------------------------------------------------------------------
+
+#include "ili9340.h"
+
+#include <avr/io.h>
+
+#include "packages/avr/device/spi.h"
+#include "packages/avr/device/spinwait.h"
+
+#include "project_defs.h"
+
+// always after other includes
+#include "packages/avr/device/workaround34734.h"
+
+
+#if defined( PRJ_ILI9340_ENABLE )
+
+// ----------------------------------------------------------------------------------------
+
+#if !defined( PRJ_SPI_ENABLE_MASTER )
+#error PRJ_SPI_ENABLE_MASTER is required for SPI communications!
+#endif
+
+#if !defined( PRJ_SPI_DATA_DIRECTION_MSB )
+#error PRJ_SPI_DATA_DIRECTION_MSB is required!
+#endif
+
+// ----------------------------------------------------------------------------------------
+
+#if !defined( PRJ_ILI9340_SELECT_PORT )
+#error PRJ_ILI9340_SELECT_PORT is required!
+#endif
+
+#if !defined( PRJ_ILI9340_SELECT_PIN )
+#error PRJ_ILI9340_SELECT_PIN is required!
+#endif
+
+#if !defined( PRJ_ILI9340_SELECT_DDR )
+#error PRJ_ILI9340_SELECT_DDR is required!
+#endif
+
+#if !defined( PRJ_ILI9340_COMMAND_PORT )
+#error PRJ_ILI9340_COMMAND_PORT is required!
+#endif
+
+#if !defined( PRJ_ILI9340_COMMAND_PIN )
+#error PRJ_ILI9340_COMMAND_PIN is required!
+#endif
+
+#if !defined( PRJ_ILI9340_COMMAND_DDR )
+#error PRJ_ILI9340_COMMAND_DDR is required!
+#endif
+
+#if defined( PRJ_ILI9340_USE_HW_RESET )
+
+#if !defined( PRJ_ILI9340_RESET_PORT )
+#error PRJ_ILI9340_RESET_PORT is required!
+#endif
+
+#if !defined( PRJ_ILI9340_RESET_PIN )
+#error PRJ_ILI9340_RESET_PIN is required!
+#endif
+
+#if !defined( PRJ_ILI9340_RESET_DDR )
+#error PRJ_ILI9340_RESET_DDR is required!
+#endif
+
+#endif // #if defined( PRJ_ILI9340_USE_HW_RESET )
+
+#if defined( PRJ_ILI9340_INC_WRITE_CSTRINGS ) || defined( PRJ_ILI9340_INC_WRITE_PGM_CSTRINGS )
+#if !defined( PRJ_ILI9340_INC_WRITE_CHAR )
+#define PRJ_ILI9340_INC_WRITE_CHAR
+#endif
+#endif
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_DISPLAY_ORIENTATION_0 ) \
+    || defined( PRJ_ILI9340_DISPLAY_ORIENTATION_180 )
+
+const uint16_t ILI9340_MAX_HORIZONTAL_PIXELS = 240;
+const uint16_t ILI9340_MAX_VERTICAL_PIXELS   = 320;
+
+#elif defined( PRJ_ILI9340_DISPLAY_ORIENTATION_90 ) \
+    || defined( PRJ_ILI9340_DISPLAY_ORIENTATION_270 )
+
+const uint16_t ILI9340_MAX_HORIZONTAL_PIXELS = 320;
+const uint16_t ILI9340_MAX_VERTICAL_PIXELS   = 240;
+
+#else
+#error PRJ_ILI9340_DISPLAY_ORIENTATION_* must be defined!
+#endif
+
+// ----------------------------------------------------------------------------------------
+
+const uint8_t ILI9340_COMMAND_SWRESET = 0x01;
+
+const uint8_t ILI9340_COMMAND_MADCTL = 0x36;
+const uint8_t ILI9340_MADCTL_MH      = ( 1 << 2 );
+const uint8_t ILI9340_MADCTL_BGR     = ( 1 << 3 );
+const uint8_t ILI9340_MADCTL_ML      = ( 1 << 4 );
+const uint8_t ILI9340_MADCTL_MV      = ( 1 << 5 );
+const uint8_t ILI9340_MADCTL_MX      = ( 1 << 6 );
+const uint8_t ILI9340_MADCTL_MY      = ( 1 << 7 );
+
+const uint8_t ILI9340_COMMAND_PWCTRL1  = 0xc0;
+const uint8_t ILI9340_PWCTRL1_VRH_MASK = 0x3f;
+const uint8_t ILI9340_PWCTRL1_VC_MASK  = 0x0f;
+
+const uint8_t ILI9340_COMMAND_PWCTRL2 = 0xc1;
+const uint8_t ILI9340_PWCTRL2_BT_MASK = 0x0f;
+
+const uint8_t ILI9340_COMMAND_VMCTR1  = 0xc5;
+const uint8_t ILI9340_VMCTR1_VMH_MASK = 0x7f;
+const uint8_t ILI9340_VMCTR1_VML_MASK = 0x7f;
+
+const uint8_t ILI9340_COMMAND_VMCTR2  = 0xc7;
+const uint8_t ILI9340_VMCTR2_nVM      = ( 1 << 7 );
+const uint8_t ILI9340_VMCTR2_VMF_MASK = 0x7f;
+
+const uint8_t ILI9340_COMMAND_PIXSET = 0x3a;
+const uint8_t ILI9340_PIXSET_16BPP   = 0x55;
+const uint8_t ILI9340_PIXSET_18BPP   = 0x66;
+
+const uint8_t ILI9340_COMMAND_FRMCTR1   = 0xb1;
+const uint8_t ILI9340_FRMCTR1_DIVA_MASK = 0x03;
+const uint8_t ILI9340_FRMCTR1_RTNA_MASK = 0x1f;
+
+const uint8_t ILI9340_COMMAND_DISCTRL    = 0xb6;
+const uint8_t ILI9340_DISCTRL_PTG_00     = ( 0x00 << 2 );
+const uint8_t ILI9340_DISCTRL_PTG_01     = ( 0x01 << 2 );
+const uint8_t ILI9340_DISCTRL_PTG_10     = ( 0x10 << 2 );
+const uint8_t ILI9340_DISCTRL_PTG_11     = ( 0x11 << 2 );
+const uint8_t ILI9340_DISCTRL_PT_00      = 0x00;
+const uint8_t ILI9340_DISCTRL_PT_01      = 0x01;
+const uint8_t ILI9340_DISCTRL_PT_10      = 0x10;
+const uint8_t ILI9340_DISCTRL_PT_11      = 0x11;
+const uint8_t ILI9340_DISCTRL_ISC_MASK   = 0x0f;
+const uint8_t ILI9340_DISCTRL_SM         = ( 1 << 4 );
+const uint8_t ILI9340_DISCTRL_SS         = ( 1 << 5 );
+const uint8_t ILI9340_DISCTRL_GS         = ( 1 << 6 );
+const uint8_t ILI9340_DISCTRL_REV        = ( 1 << 7 );
+const uint8_t ILI9340_DISCTRL_NL_MASK    = 0x1f;
+const uint8_t ILI9340_DISCTRL_PCDIV_MASK = 0x1f;
+
+const uint8_t ILI9340_COMMAND_SPLIN  = 0x10;
+const uint8_t ILI9340_COMMAND_SLPOUT = 0x11;
+
+const uint8_t ILI9340_COMMAND_DISPON = 0x29;
+
+const uint8_t ILI9340_COMMAND_CASET = 0x2a;
+const uint8_t ILI9340_COMMAND_PASET = 0x2b;
+const uint8_t ILI9340_COMMAND_RAMWR = 0x2c;
+
+// ----------------------------------------------------------------------------------------
+//
+//  This is an 8x6 monospaced font, organized as one byte per horizontal row.
+//
+
+#if defined( PRJ_ILI9340_INC_WRITE_CHAR )
+
+const uint8_t ILI9340_GLYPH_HEIGHT = 8;
+const uint8_t ILI9340_GLYPH_WIDTH  = 6;
+
+const uint8_t ILI9340_MAX_HORIZONTAL_CHARS
+    = ( ILI9340_MAX_HORIZONTAL_PIXELS / ILI9340_GLYPH_WIDTH );
+
+const uint8_t ILI9340_MAX_VERTICAL_CHARS
+    = ( ILI9340_MAX_VERTICAL_PIXELS / ILI9340_GLYPH_HEIGHT );
+
+typedef uint8_t ili9340_glyph_t[ 8 ];
+
+static const ili9340_glyph_t PROGMEM glyphs[] =
+{
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },     // space, ascii 0x20
+    { 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00 },     // !
+    { 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00 },     // "
+    { 0x28, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x28, 0x00 },     // #
+    { 0x10, 0x3c, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00 },     // $
+    { 0x60, 0x64, 0x08, 0x10, 0x20, 0x4c, 0x0c, 0x00 },     // %
+    { 0x10, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 },     // &
+    { 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 },     // '
+    { 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00 },     // (
+    { 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00 },     // )
+    { 0x00, 0x10, 0x54, 0x38, 0x54, 0x10, 0x00, 0x00 },     // *
+    { 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00 },     // +
+    { 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00 },     // ,
+    { 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00 },     // -
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00 },     // .
+    { 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00 },     // /
+    { 0x38, 0x44, 0x4c, 0x54, 0x64, 0x44, 0x38, 0x00 },     // 0
+    { 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },     // 1
+    { 0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x7c, 0x00 },     // 2
+    { 0x7c, 0x08, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00 },     // 3
+    { 0x08, 0x18, 0x28, 0x48, 0x7c, 0x08, 0x08, 0x00 },     // 4
+    { 0x7c, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00 },     // 5
+    { 0x18, 0x20, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00 },     // 6
+    { 0x7c, 0x04, 0x08, 0x10, 0x20, 0x20, 0x20, 0x00 },     // 7
+    { 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00 },     // 8
+    { 0x38, 0x44, 0x44, 0x38, 0x04, 0x04, 0x38, 0x00 },     // 9
+    { 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00 },     // :
+    { 0x00, 0x30, 0x30, 0x00, 0x30, 0x10, 0x20, 0x00 },     // ;
+    { 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00 },     // <
+    { 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00 },     // =
+    { 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00 },     // >
+    { 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00 },     // ?
+    { 0x38, 0x44, 0x04, 0x34, 0x54, 0x54, 0x38, 0x00 },     // @
+    { 0x38, 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x00 },     // A
+    { 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 },     // B
+    { 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 },     // C
+    { 0x70, 0x48, 0x44, 0x44, 0x44, 0x48, 0x70, 0x00 },     // D
+    { 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7c, 0x00 },     // E
+    { 0x7c, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 },     // F
+    { 0x38, 0x44, 0x40, 0x5c, 0x44, 0x44, 0x3c, 0x00 },     // G
+    { 0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00 },     // H
+    { 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },     // I
+    { 0x1c, 0x08, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00 },     // J
+    { 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 },     // K
+    { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7c, 0x00 },     // L
+    { 0x44, 0x6c, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00 },     // M
+    { 0x44, 0x44, 0x64, 0x54, 0x4c, 0x44, 0x44, 0x00 },     // N
+    { 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 },     // O
+    { 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00 },     // P
+    { 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00 },     // Q
+    { 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00 },     // R
+    { 0x3c, 0x40, 0x40, 0x38, 0x04, 0x04, 0x78, 0x00 },     // S
+    { 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 },     // T
+    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 },     // U
+    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 },     // V
+    { 0x44, 0x44, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00 },     // W
+    { 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 },     // X
+    { 0x44, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x00 },     // Y
+    { 0x7c, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7c, 0x00 },     // Z
+    { 0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x00 },     // [
+    { 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00 },     // \ (backslash)
+    { 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00 },     // ]
+    { 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 },     // ^
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00 },     // _
+    { 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 },     // `
+    { 0x00, 0x00, 0x38, 0x04, 0x3c, 0x44, 0x3c, 0x00 },     // a
+    { 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x78, 0x00 },     // b
+    { 0x00, 0x00, 0x38, 0x40, 0x40, 0x44, 0x38, 0x00 },     // c
+    { 0x04, 0x04, 0x34, 0x4c, 0x44, 0x44, 0x3c, 0x00 },     // d
+    { 0x00, 0x00, 0x38, 0x44, 0x7c, 0x40, 0x38, 0x00 },     // e
+    { 0x18, 0x24, 0x20, 0x70, 0x20, 0x20, 0x20, 0x00 },     // f
+    { 0x00, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x38, 0x00 },     // g
+    { 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00 },     // h
+    { 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00 },     // i
+    { 0x04, 0x00, 0x0c, 0x04, 0x04, 0x24, 0x18, 0x00 },     // j
+    { 0x40, 0x40, 0x48, 0x50, 0x60, 0x50, 0x48, 0x00 },     // k
+    { 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 },     // l
+    { 0x00, 0x00, 0x68, 0x54, 0x54, 0x44, 0x44, 0x00 },     // m
+    { 0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00 },     // n
+    { 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 },     // o
+    { 0x00, 0x00, 0x78, 0x44, 0x78, 0x40, 0x40, 0x00 },     // p
+    { 0x00, 0x00, 0x34, 0x4c, 0x3c, 0x04, 0x04, 0x00 },     // q
+    { 0x00, 0x00, 0x58, 0x64, 0x40, 0x40, 0x40, 0x00 },     // r
+    { 0x00, 0x00, 0x38, 0x40, 0x38, 0x04, 0x78, 0x00 },     // s
+    { 0x20, 0x20, 0x70, 0x20, 0x20, 0x24, 0x18, 0x00 },     // t
+    { 0x00, 0x00, 0x44, 0x44, 0x44, 0x4c, 0x34, 0x00 },     // u
+    { 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 },     // v
+    { 0x00, 0x00, 0x44, 0x44, 0x54, 0x54, 0x28, 0x00 },     // w
+    { 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 },     // x
+    { 0x00, 0x00, 0x44, 0x44, 0x3c, 0x04, 0x38, 0x00 },     // y
+    { 0x00, 0x00, 0x7c, 0x08, 0x10, 0x20, 0x7c, 0x00 },     // z
+    { 0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00 },     // {
+    { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 },     // |
+    { 0x10, 0x08, 0x08, 0x04, 0x08, 0x08, 0x10, 0x00 },     // }
+    { 0x00, 0x00, 0x14, 0x28, 0x00, 0x00, 0x00, 0x00 },     // ~
+    { 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x00 }      // DEL
+};
+
+#endif
+
+// ----------------------------------------------------------------------------------------
+
+inline void select_controller()
+{
+    PRJ_ILI9340_SELECT_PORT &= ~( 1 << PRJ_ILI9340_SELECT_PIN );
+}
+
+inline void deselect_controller()
+{
+    PRJ_ILI9340_SELECT_PORT |= ( 1 << PRJ_ILI9340_SELECT_PIN );
+}
+
+// ----------------------------------------------------------------------------------------
+
+inline void set_controller_command_mode()
+{
+    PRJ_ILI9340_COMMAND_PORT &= ~( 1 << PRJ_ILI9340_COMMAND_PIN );
+}
+
+inline void set_controller_data_mode()
+{
+    PRJ_ILI9340_COMMAND_PORT |= ( 1 << PRJ_ILI9340_COMMAND_PIN );
+}
+
+// ----------------------------------------------------------------------------------------
+
+static void send_command( uint8_t cmd )
+{
+    set_controller_command_mode();
+    select_controller();
+    spi_write( cmd );
+    deselect_controller();
+}
+
+static void send_data( uint8_t data )
+{
+    set_controller_data_mode();
+    select_controller();
+    spi_write( data );
+    deselect_controller();
+}
+
+// ----------------------------------------------------------------------------------------
+
+void ili9340_init()
+{
+    //--    Configure our select line and mode line.
+
+    PRJ_ILI9340_SELECT_DDR  |= ( 1 << PRJ_ILI9340_SELECT_PIN );
+    PRJ_ILI9340_SELECT_PORT |= ( 1 << PRJ_ILI9340_SELECT_PIN );
+
+    PRJ_ILI9340_COMMAND_DDR  |=  ( 1 << PRJ_ILI9340_COMMAND_PIN );
+    PRJ_ILI9340_COMMAND_PORT &= ~( 1 << PRJ_ILI9340_COMMAND_PIN );
+
+    //--    Configure our reset line (if supplied); it should be pulled high normally.
+
+#if defined( PRJ_ILI9340_USE_HW_RESET )
+
+    PRJ_ILI9340_RESET_DDR  |= ( 1 << PRJ_ILI9340_RESET_PIN );
+    PRJ_ILI9340_RESET_PORT |= ( 1 << PRJ_ILI9340_RESET_PIN );
+
+#endif
+
+    //--    Reset the display.
+
+    ili9340_reset();
+
+    //--    Configure the display controller. This is mostly copied from example code
+    //      and reading the ILITEK datasheet.
+
+    send_command( ILI9340_COMMAND_PWCTRL1 );
+    send_data( 0x23 & ILI9340_PWCTRL1_VRH_MASK );   // GVDD = 4.60 V
+    send_data( 0x00 & ILI9340_PWCTRL1_VC_MASK );    // VCI1 = 2.30 V
+
+    send_command( ILI9340_COMMAND_PWCTRL2 );
+    send_data( 0x00 & ILI9340_PWCTRL2_BT_MASK );    // BT = 0b0000
+
+    send_command( ILI9340_COMMAND_VMCTR1 );
+    send_data( 0x3e & ILI9340_VMCTR1_VMH_MASK );    // VCOMH =  4.250 V
+    send_data( 0x28 & ILI9340_VMCTR1_VML_MASK );    // VCOML = -1.500 V
+
+    send_command( ILI9340_COMMAND_VMCTR2 );
+    send_data( ILI9340_VMCTR2_nVM | ( 0x06 & ILI9340_VMCTR2_VMF_MASK ) );
+
+#if defined( PRJ_ILI9340_DISPLAY_ORIENTATION_0 )
+
+    send_command( ILI9340_COMMAND_MADCTL );
+    send_data( ILI9340_MADCTL_MX | ILI9340_MADCTL_BGR );
+
+#elif defined( PRJ_ILI9340_DISPLAY_ORIENTATION_90 )
+
+    send_command( ILI9340_COMMAND_MADCTL );
+    send_data( ILI9340_MADCTL_MV | ILI9340_MADCTL_BGR );
+
+#elif defined( PRJ_ILI9340_DISPLAY_ORIENTATION_180 )
+
+    send_command( ILI9340_COMMAND_MADCTL );
+    send_data( ILI9340_MADCTL_MY | ILI9340_MADCTL_BGR );
+
+#elif defined( PRJ_ILI9340_DISPLAY_ORIENTATION_270 )
+
+    send_command( ILI9340_COMMAND_MADCTL );
+    send_data( ILI9340_MADCTL_MV | ILI9340_MADCTL_MY | ILI9340_MADCTL_MX | ILI9340_MADCTL_BGR );
+
+#endif
+
+    send_command( ILI9340_COMMAND_PIXSET );
+    send_data( ILI9340_PIXSET_16BPP );
+
+    send_command( ILI9340_COMMAND_FRMCTR1 );
+    send_data( 0x00 & ILI9340_FRMCTR1_DIVA_MASK );
+    send_data( 0x18 & ILI9340_FRMCTR1_RTNA_MASK );      // 79 Hz refresh rate
+
+    send_command( ILI9340_COMMAND_DISCTRL );
+    send_data( ILI9340_DISCTRL_PTG_10 | ILI9340_DISCTRL_PT_00 );
+    send_data( ILI9340_DISCTRL_REV | ( 0x02 & ILI9340_DISCTRL_ISC_MASK ) );
+    send_data( 0x27 & ILI9340_DISCTRL_NL_MASK );
+    send_data( 0x00 & ILI9340_DISCTRL_PCDIV_MASK );
+
+    send_command( ILI9340_COMMAND_SLPOUT );
+    spinwait_delay_ms( 120 );
+
+    send_command( ILI9340_COMMAND_DISPON );
+}
+
+// ----------------------------------------------------------------------------------------
+
+void ili9340_reset()
+{
+
+#if defined( PRJ_ILI9340_USE_HW_RESET )
+
+    spinwait_delay_ms( 5 );
+    PRJ_ILI9340_RESET_PORT &= ~( 1 << PRJ_ILI9340_RESET_PIN );
+    spinwait_delay_ms( 20 );
+    PRJ_ILI9340_RESET_PORT |= ( 1 << PRJ_ILI9340_RESET_PIN );
+    spinwait_delay_ms( 150 );
+
+#else
+
+    spinwait_delay_ms( 5 );
+    send_command( ILI9340_COMMAND_SWRESET );
+    spinwait_delay_ms( 150 );
+
+#endif
+
+}
+
+// ----------------------------------------------------------------------------------------
+//  Prepare to write to the display memory to a given rectangle.
+//
+
+static void prep_page_col_address( uint16_t x, uint16_t dx, uint16_t y, uint16_t dy )
+{
+    send_command( ILI9340_COMMAND_CASET );
+    send_data( x >> 8 );
+    send_data( x & 0xff );
+    send_data( ( x + dx ) >> 8 );
+    send_data( ( x + dx ) & 0xff );
+
+    send_command( ILI9340_COMMAND_PASET );
+    send_data( y >> 8 );
+    send_data( y & 0xff );
+    send_data( ( y + dx ) >> 8 );
+    send_data( ( y + dx ) & 0xff );
+
+    send_command( ILI9340_COMMAND_RAMWR );
+}
+
+
+// ----------------------------------------------------------------------------------------
+
+void ili9340_fill_screen( ili9340_color_t color )
+{
+    select_controller();
+
+    //--    Set the page and column addressing to 0 - 131.
+
+    prep_page_col_address( 0, ILI9340_MAX_HORIZONTAL_PIXELS - 1,
+                           0, ILI9340_MAX_VERTICAL_PIXELS - 1 );
+
+    uint8_t color_hi = static_cast< uint8_t >( color >> 8 );
+    uint8_t color_lo = static_cast< uint8_t >( color );
+
+    for ( uint16_t i = 0;
+          i < ( ILI9340_MAX_HORIZONTAL_PIXELS * ILI9340_MAX_VERTICAL_PIXELS );
+          ++i ) 
+    {
+        send_data( color_hi );
+        send_data( color_lo );
+    }
+
+    deselect_controller();
+}
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_WRITE_CHAR )
+
+void ili9340_write( char            c, 
+                    uint8_t         x, 
+                    uint8_t         y, 
+                    ili9340_color_t fg_color,
+                    ili9340_color_t bg_color )
+{
+    //--    Convert the glyph coordinates to pixel coordinates.
+
+    x %= ILI9340_MAX_HORIZONTAL_CHARS;
+    x *= ILI9340_GLYPH_WIDTH;
+
+    y %= ILI9340_MAX_VERTICAL_CHARS;
+    y *= ILI9340_GLYPH_HEIGHT;
+
+    //--    Glyphs are stored starting with the space character: ASCII 32 = 0x20.
+
+    if ( c < 0x20 )
+    {
+        c = 0x7f;   // generic character glyph
+    }
+
+    c -= 0x20;
+    
+    const prog_uint8_t* this_glyph
+      = reinterpret_cast< const prog_uint8_t* >( &glyphs[ static_cast< uint8_t >( c ) ] );
+
+    //--    Write the glyph pixels at the specified location.
+
+    uint8_t fg_color_hi = static_cast< uint8_t >( fg_color >> 8 );
+    uint8_t fg_color_lo = static_cast< uint8_t >( fg_color );
+
+    uint8_t bg_color_hi = static_cast< uint8_t >( bg_color >> 8 );
+    uint8_t bg_color_lo = static_cast< uint8_t >( bg_color );
+
+    select_controller();
+    
+    prep_page_col_address( x, ILI9340_GLYPH_WIDTH - 1, y, ILI9340_GLYPH_HEIGHT - 1 );
+
+    for ( uint8_t i = 0; i < ILI9340_GLYPH_HEIGHT; i++ )
+    {
+        uint8_t data = pgm_read_byte_near( this_glyph++ );
+
+        for ( uint8_t j = 0; j < ILI9340_GLYPH_WIDTH; j++ )
+        {
+            if ( data & 0x80 )
+            {
+                send_data( fg_color_hi );
+                send_data( fg_color_lo );
+            }
+            else
+            {
+                send_data( bg_color_hi );
+                send_data( bg_color_lo );
+            }
+            data <<= 1;
+        }
+    }
+
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_WRITE_CSTRINGS )
+
+void ili9340_write
+    ( 
+        const char*    str, 
+        uint8_t        x, 
+        uint8_t        y, 
+        ili9340_color_t fg_color,
+        ili9340_color_t bg_color 
+    )
+{
+    while ( *str )
+    {
+        ili9340_write( *str++, x++, y, fg_color, bg_color );
+    }
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_WRITE_PGM_CSTRINGS )
+
+void ili9340_write_pgm
+    ( 
+        const prog_char* str, 
+        uint8_t          x, 
+        uint8_t          y, 
+        ili9340_color_t   fg_color,
+        ili9340_color_t   bg_color 
+    )
+{
+    for ( ;; )
+    {
+        char c = static_cast< char >( pgm_read_byte_near( str++ ) );
+
+        if ( c == '\0' )
+        {
+            return;
+        }
+
+        ili9340_write( c, x++, y, fg_color, bg_color );
+    }
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_SET_PIXEL )
+
+void ili9340_set_pixel( uint8_t x, uint8_t y, ili9340_color_t color )
+{
+    x %= ILI9340_MAX_HORIZONTAL_PIXELS;
+    y %= ILI9340_MAX_VERTICAL_PIXELS;
+
+    select_controller();
+    
+    prep_page_col_address( x, 0, y, 0 );
+    send_data( color );
+    
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_DRAWING )
+
+void ili9340_line_h( uint8_t x, uint8_t y, uint8_t len, ili9340_color_t color )
+{
+    x %= ILI9340_MAX_HORIZONTAL_PIXELS;
+    y %= ILI9340_MAX_VERTICAL_PIXELS;
+    
+    if ( len + x > ILI9340_MAX_HORIZONTAL_PIXELS )
+    {
+        len = ILI9340_MAX_HORIZONTAL_PIXELS - x;
+    }
+
+    select_controller();
+    
+    prep_page_col_address( x, len - 1, y, 0 );
+    
+    while ( len-- )
+    {
+        send_data( color );
+    }
+
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_DRAWING )
+
+void ili9340_line_v( uint8_t x, uint8_t y, uint8_t len, ili9340_color_t color )
+{
+    x %= ILI9340_MAX_HORIZONTAL_PIXELS;
+    y %= ILI9340_MAX_VERTICAL_PIXELS;
+    
+    if ( len + y > ILI9340_MAX_VERTICAL_PIXELS )
+    {
+        len = ILI9340_MAX_VERTICAL_PIXELS - y;
+    }
+
+    select_controller();
+    
+    prep_page_col_address( x, 0, y, len - 1 );
+    
+    while ( len-- )
+    {
+        send_data( color );
+    }
+
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_DRAWING )
+
+void ili9340_rect( uint8_t x, uint8_t y, uint8_t w, uint8_t h, ili9340_color_t color )
+{
+    ili9340_line_h( x, y, w, color );
+    ili9340_line_h( x, y + h - 1, w, color );
+    ili9340_line_v( x, y, h - 1, color );
+    ili9340_line_v( x + w - 1, y, h - 1, color );
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_DRAWING )
+
+void ili9340_fill( uint8_t x, uint8_t y, uint8_t w, uint8_t h, ili9340_color_t color )
+{
+    x %= ILI9340_MAX_HORIZONTAL_PIXELS;
+    y %= ILI9340_MAX_VERTICAL_PIXELS;
+    
+    if ( w + x > ILI9340_MAX_HORIZONTAL_PIXELS )
+    {
+        w = ILI9340_MAX_HORIZONTAL_PIXELS - x;
+    }
+
+    if ( h + y > ILI9340_MAX_VERTICAL_PIXELS )
+    {
+        h = ILI9340_MAX_VERTICAL_PIXELS - y;
+    }
+
+    select_controller();
+    
+    prep_page_col_address( x, w - 1, y, h - 1 );
+    
+    for ( uint16_t i = 0; i < static_cast< uint16_t >( h * w ); i++ )
+    {
+        send_data( color );
+    }
+
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_DRAWING )
+
+void ili9340_line( uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, ili9340_color_t color )
+{
+    //--    Bresenham's line rasterization algorithm: 
+    //      http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
+
+    int16_t dy = y1 - y0;
+    int16_t dx = x1 - x0;
+    int8_t  step_x = 1;
+    int8_t  step_y = 1;
+
+    if ( dy < 0 )
+    {
+        dy *= -1;
+        step_y = -1;
+    }
+
+    if ( dx < 0 )
+    {
+        dx *= -1;
+        step_x = -1;
+    }
+
+    dy <<= 1;
+    dx <<= 1;
+
+    ili9340_set_pixel( x0, y0, color );
+
+    if ( dx > dy )
+    {
+        int16_t fraction = dy - ( dx >> 1 );
+
+        while ( x0 != x1 )
+        {
+            if ( fraction >= 0 ) 
+            {
+                y0 += step_y;
+                fraction -= dx;
+            }
+
+            x0 += step_x;
+            fraction += dy;
+
+            ili9340_set_pixel( x0, y0, color );
+        }
+    }
+    else
+    {
+        int16_t fraction = dx - ( dy >> 1 );
+
+        while ( y0 != y1 )
+        {
+            if ( fraction >= 0 )
+            {
+                x0 += step_x;
+                fraction -= dy;
+            }
+
+            y0 += step_y;
+            fraction += dx;
+
+            ili9340_set_pixel( x0, y0, color );
+        }
+    }
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_IMAGEMASK )
+
+void ili9340_imagemask
+    (
+        uint8_t             x,
+        uint8_t             y,
+        uint8_t             w,
+        uint8_t             h,
+        ili9340_color_t      fg_color,
+        ili9340_color_t      bg_color,
+        const prog_uint8_t* pixels
+    )
+{
+    x %= ILI9340_MAX_HORIZONTAL_PIXELS;
+    y %= ILI9340_MAX_VERTICAL_PIXELS;
+
+    select_controller();
+    
+    prep_page_col_address( x, w - 1, y, h - 1 );
+    
+    while ( h-- )
+    {
+        uint8_t pix_bit = 0x00;
+        uint8_t data    = 0x00;
+
+        for ( uint8_t i = 0; i < w; i++ )
+        {
+            if ( pix_bit == 0x00 )
+            {
+                data = pgm_read_byte_near( pixels++ );
+                pix_bit = 0x80;
+            }
+
+            if ( data & pix_bit )
+            {
+                send_data( fg_color );
+            }
+            else
+            {
+                send_data( bg_color );
+            }
+
+            pix_bit >>= 1;
+        }
+    }
+
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_ILI9340_INC_COLORIMAGE )
+
+void ili9340_colorimage
+    (
+        uint8_t x,
+        uint8_t y,
+        uint8_t w,
+        uint8_t h,
+        const prog_uint8_t* pixels
+    )
+{
+    x %= ILI9340_MAX_HORIZONTAL_PIXELS;
+    y %= ILI9340_MAX_VERTICAL_PIXELS;
+
+    select_controller();
+    
+    prep_page_col_address( x, w - 1, y, h - 1 );
+    
+    while ( h-- )
+    {
+        for ( uint8_t i = 0; i < w; i++ )
+        {
+            send_data( pgm_read_byte_near( pixels++ ) );
+        }
+    }
+
+    deselect_controller();
+}
+
+#endif
+
+
+// ----------------------------------------------------------------------------------------
+
+#endif  // #if defined( PRJ_ILI9340_ENABLE )
+// ----------------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/packages/avr/lcd/ili9340/ili9340.h	Sat May 10 08:13:43 2014 -0700
@@ -0,0 +1,288 @@
+// ----------------------------------------------------------------------------------------
+//
+//  avr/lcd/ili9340/ili9340.h
+//    
+//  Bob Cook Development, Robotics Library
+//  http://www.bobcookdev.com/rl/
+//    
+//  This file implements support for the ILI9340 240x320 RGB LCD driver.
+//
+//  Copyright (C) 2014 Bob Cook
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//  
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//  
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+// ----------------------------------------------------------------------------------------
+
+#if !defined( BCDRL_AVR_LCD_ILI9340_H )
+#define BCDRL_AVR_LCD_ILI9340_H
+
+#include <stdint.h>
+#include <avr/pgmspace.h>
+
+// ----------------------------------------------------------------------------------------
+//  definitions from "project_defs.h"
+//
+//  enable support for the ILI9340 240x320 RGB LCD driver with:
+//
+//      + PRJ_ILI9340_ENABLE
+//
+//  specify the SELECT pin for SPI communications with:
+//
+//      + PRJ_ILI9340_SELECT_PORT
+//      + PRJ_ILI9340_SELECT_PIN
+//      + PRJ_ILI9340_SELECT_DDR
+//
+//  specify the MODE pin (for setting either command or data) with:
+//
+//      + PRJ_ILI9340_COMMAND_PORT
+//      + PRJ_ILI9340_COMMAND_PIN
+//      + PRJ_ILI9340_COMMAND_DDR
+//
+//  specify the (optional) RESET pin with:
+//
+//      + PRJ_ILI9340_USE_HW_RESET
+//      + PRJ_ILI9340_RESET_PORT
+//      + PRJ_ILI9340_RESET_PIN
+//      + PRJ_ILI9340_RESET_DDR
+//
+//  specify the orientation with one (and only one) of the following:
+//
+//      + PRJ_ILI9340_DISPLAY_ORIENTATION_0
+//      + PRJ_ILI9340_DISPLAY_ORIENTATION_90
+//      + PRJ_ILI9340_DISPLAY_ORIENTATION_180
+//      + PRJ_ILI9340_DISPLAY_ORIENTATION_270
+//
+//  optional features can be enabled with one or more of the following:
+//
+//      + PRJ_ILI9340_INC_WRITE_CHAR
+//      + PRJ_ILI9340_INC_WRITE_CSTRINGS
+//      + PRJ_ILI9340_INC_WRITE_PGM_CSTRINGS
+//      + PRJ_ILI9340_INC_SET_PIXEL
+//      + PRJ_ILI9340_INC_DRAWING
+//      + PRJ_ILI9340_INC_IMAGEMASK
+//      + PRJ_ILI9340_INC_COLORIMAGE
+//
+// ----------------------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_color_t
+//
+//      The display driver uses 16-bit color values, packed as: RRRRRGGGGGGBBBBB (5-6-5)
+//
+
+typedef uint16_t ili9340_color_t;
+
+const ili9340_color_t ili9340_color_black   = 0x0000;
+const ili9340_color_t ili9340_color_white   = 0xffff;
+const ili9340_color_t ili9340_color_red     = 0xf800;
+const ili9340_color_t ili9340_color_green   = 0x07e0;
+const ili9340_color_t ili9340_color_blue    = 0x001f;
+const ili9340_color_t ili9340_color_cyan    = 0x07ff;
+const ili9340_color_t ili9340_color_magenta = 0xf81f;
+const ili9340_color_t ili9340_color_yellow  = 0xffe0;
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_init
+//
+//      Initialize the ILI9340 LCD driver package, setting up the hardware and clearing
+//      the display. Call this function prior to any other.
+//
+
+void ili9340_init();
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_reset
+//
+//      Reset the display, using the hardware reset line if available. Otherwise uses
+//      the software reset command.
+//
+
+void ili9340_reset();
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_fill_screen
+//
+//      Fill the entire screen with the specified color. Use this function to erase the
+//      screen by filling it with "ili9340_color_black".
+//
+
+void ili9340_fill_screen( ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_write
+//
+//      Write a character to the display in the *character* row and column. The maximum
+//      number of characters depends on the orientation:
+//      
+//          horizontal: 53 characters wide x 30 characters high
+//          vertical:   40 characters wide x 40 characters high
+//
+//      This function is only available if PRJ_ILI9340_INC_WRITE_CHAR is defined.
+//
+
+void ili9340_write
+    (
+        char           c, 
+        uint8_t        x, 
+        uint8_t        y, 
+        ili9340_color_t fg_color,
+        ili9340_color_t bg_color 
+    );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_write
+//
+//      Write a string to the display in the *character* row and column. The display
+//      can support 16 rows by 21 columns.
+//
+//      This function is only available if PRJ_ILI9340_INC_WRITE_CSTRINGS is defined.
+//
+
+void ili9340_write
+    ( 
+        const char*    str, 
+        uint8_t        x, 
+        uint8_t        y, 
+        ili9340_color_t fg_color,
+        ili9340_color_t bg_color 
+    );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_write_pgm
+//
+//      Write a string from flash memory to the display in the *character* row and column.
+//      The display can support 16 rows by 21 columns.
+//
+//      This function is only available if PRJ_ILI9340_INC_WRITE_PGM_CSTRINGS is defined.
+//
+
+void ili9340_write_pgm
+    ( 
+        const prog_char* str, 
+        uint8_t          x, 
+        uint8_t          y, 
+        ili9340_color_t   fg_color,
+        ili9340_color_t   bg_color 
+    );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_set_pixel
+//
+//      Paint a specific pixel. The display supports 240 rows by 320 columns.
+//
+//      This function is only available if PRJ_ILI9340_INC_SET_PIXEL is defined.
+//
+
+void ili9340_set_pixel( uint8_t x, uint8_t y, ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_line_h
+//
+//      Paint a row of pixels.
+//
+//      This function is only available if PRJ_ILI9340_INC_DRAWING is defined.
+//
+
+void ili9340_line_h( uint8_t x, uint8_t y, uint8_t len, ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_line_v
+//
+//      Paint a column of pixels.
+//
+//      This function is only available if PRJ_ILI9340_INC_DRAWING is defined.
+//
+
+void ili9340_line_v( uint8_t x, uint8_t y, uint8_t len, ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_rect
+//
+//      Paint the frame (edge) pixels of a rectangular region.
+//
+//      This function is only available if PRJ_ILI9340_INC_DRAWING is defined.
+//
+
+void ili9340_rect( uint8_t x, uint8_t y, uint8_t w, uint8_t h, ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_fill
+//
+//      Turn on all the pixels inside of a rectangular region.
+//
+//      This function is only available if PRJ_ILI9340_INC_DRAWING is defined.
+//
+
+void ili9340_fill( uint8_t x, uint8_t y, uint8_t w, uint8_t h, ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_line
+//
+//      Turn on or off the pixels in a line between two points. This is much more
+//      expensive for horizontal or vertical lines; prefer to use the optimized
+//      functions (ili9340_line_h, ili9340_line_v) for those cases when possible.
+//
+//      This function is only available if PRJ_ILI9340_INC_DRAWING is defined.
+//
+
+void ili9340_line( uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, ili9340_color_t color );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_imagemask
+//
+//      Paint pixels with the specified color using the 1-bit image as a mask, at the
+//      specified pixel location. The pixel data must be stored in flash memory and be 
+//      organized by rows, padded to whole bytes per row.
+//
+//      This function is only available if PRJ_ILI9340_INC_IMAGEMASK is defined.
+//
+
+void ili9340_imagemask
+    (
+        uint8_t             x,
+        uint8_t             y,
+        uint8_t             w,
+        uint8_t             h,
+        ili9340_color_t     fg_color,
+        ili9340_color_t     bg_color,
+        const prog_uint8_t* pixels
+    );
+
+// ----------------------------------------------------------------------------------------
+//  ili9340_colorimage
+//
+//      Paint an image at the specified pixel location. The pixel data must be stored in
+//      flash memory and be organized by rows, padded to an even number of bytes per row.
+//      Each pixel must the 16-bit format: RRRRRGGGGGGBBBBB (5-6-5).
+//
+//      This function is only available if PRJ_ILI9340_INC_COLORIMAGE is defined.
+//
+
+void ili9340_colorimage
+    (
+        uint8_t             x,
+        uint8_t             y,
+        uint8_t             w,
+        uint8_t             h,
+        const prog_uint8_t* pixels
+    );
+
+#endif  // #if !defined( BCDRL_AVR_LCD_ILI9340_H )
+// ----------------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/packages/avr/lcd/ili9340/jamfile	Sat May 10 08:13:43 2014 -0700
@@ -0,0 +1,41 @@
+# -----------------------------------------------------------------------------------------
+#
+#   avr/lcd/ili9340/jamfile
+#
+#   Bob Cook Development, Robotics Library
+#   http://www.bobcookdev.com/rl/
+#
+#   Copyright (C) 2014 Bob Cook
+#
+#   Permission is hereby granted, free of charge, to any person obtaining a copy
+#   of this software and associated documentation files (the "Software"), to deal
+#   in the Software without restriction, including without limitation the rights
+#   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#   copies of the Software, and to permit persons to whom the Software is
+#   furnished to do so, subject to the following conditions:
+#  
+#   The above copyright notice and this permission notice shall be included in
+#   all copies or substantial portions of the Software.
+#  
+#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#   THE SOFTWARE.
+#
+# -----------------------------------------------------------------------------------------
+
+if $(TRACE) { echo "trace /packages/avr/lcd/ili9340/jamfile" ; }
+
+SubDir TOP packages avr lcd ili9340 ;
+
+# -----------------------------------------------------------------------------------------
+
+PackageSources
+    ili9340.cpp
+    ;
+    
+# -----------------------------------------------------------------------------------------
+