Jenn Holt's updated firmware for Sparkfun Graphical LCD backpack

This is ONLY for the 128x64 display. All the code for the larger display has
been removed. The author owns the small one and this was all that could be
tested. Others are welcome to adapt the code if they want.

The notes below should be compared with the original Sparkfun graphic LCD
backpack software.

Interface Information
=====================

Default baud is 115200 and will revert to this when a character is sent during
the splash screen

The display implements XON/XOFF flow control. If your application supports
this, you can re-compile the code with a smaller RX_BUFFER_SIZE value to make
more room for sprites. The default RX_BUFFER_SIZE is the 256 max. If you are
going to BitBlt large images I recommend implementing XON/XOFF or you may
overrun the buffer. You could also put a delay in your host code if you
overrun the buffer while BitBlt'ing a large image.

ASCII characters sent to the display will be printed left to right, top to
bottom commands are prefaced by 0x7C

There are basic debug messages that get sent when command mode is entered and
exited, these are set with command 0x02 0x## with ##=(0,1,2)

    0 = no messages
    1 = binary format messages
    2 = ASCII format messages.

The messages are sent out on the UART.

There is an LCD reset command that resets the LCD should things get corrupted;
this is command 0x06. This pulls the RESET low, then high and then clears the
screen and sets x_offset=0, y_offset=0.

Text Information
================

The display now responds to carriage returns and line feeds. by default a
carriage return also executes a line feed. you can toggle this with command
0x04

There is no more demo mode.

Text rendering is now much faster.

You can define your own fonts, however you must decide what fonts you want at
compile time. All font data is in two files font.h and aux_font.h, replace
them with your own fonts if you wish.

There is a utility called bmp2header_font which will create a font.h file from
a bitmap(one large image with characters sequential in the x direction), not
you must manually rename text_array to aux_text array in the header if you
want to use it for aux_font.h.

By default the code builds with the original Sparkfun font as default in
addition to a double sized font in aux, you can switch back and forth with
command 0x08.

The text is now rendered using the bitblt function, so you can use all the
logical modes (0..7) for drawing text, set the mode with command 0x0A 0x##.

Graphical Information
=====================

The coordinate system is now (0,0) in upper left and increasing right and
down.

The line and circle algorithms have been replaced to use integer math only.
The Bresenham's line algorithm and midpoint circle algorithm are used.

Support for NUM_SPRITES sprites labelled 0..(NUM_SPRITES-1). Each sprite has
SPRITE_SIZE bytes of data dedicated to it.

The default #defines in the code set these numbers to 8 sprites of 34 bytes
each, you can change this if you want, but be careful not to use up all the
SRAM as the ATmega168 only has 1K. 34 bytes/sprite is enough for a 16x16
block, although sprites do not have to be square. Command 0c0b draws a sprite,
the Sparkfun logo is sprite 0, but this can be overwritten. Command 0x0d
uploads a sprite.

Draw filled box command has been added. This draws a box filled with a
repeating byte (vertical stripe of data) ie 0x00 would clear every pixel, 0xFF
would set them, 0xAA would draw stripes

Use bitblt if you want to draw something larger than a sprite.

New commands include a raw read/write function:
 - write_command
 - write_data
 - write_block
 - read_data
 - read_byte
 - read_block

Reverse mode now inverts the graphics on the screen instead of clearing it.

Command List
============

All commands must start with 0x7C, this informs the display that the following
bytes are part of a command:

0x00 -  Clear screen

        0x7c 0x00

        Clears or sets all pixels on the screen (depending on whether reverse
        is set). The command sets the x_offset and y_offset to 0.

0x01 -  Set debug level

        0x7c 0x00 <debug_level>

        Sets the debugging level of the display. Where <debug_level> is
        defined as follows:

        0 = No messages (default)
            The messages are turned off.

        1 = Binary messages.
            The display will echo a byte = command when the command is started
            and a byte = 0x00 when the command is finished

        2 = Text messages.
            This is useful when using a terminal and will echo "Entered
            Command n" when command n is started and will echo "Exited Command
            n, RX_buffer=y" when the command is done, and will report how many
            bytes are in the receive buffer.

0x02 -  Set backing duty cycle

        0x7c 0x02 <percentage>

        Where the argument <percentage> is the brightness specified as a
        percentage 0..100.

        Example: 0x7C 0x02 0x32 will set the back light to 50%

0x03 -  Draw circle

        0x7c <x> <y> <radius> <set_reset>

        Where arguments are defined as:

        <x> - The x coordinate 0..127

        <y> - The y coordinate 0..63

        <radius> - The radius of the circle.

        <set_reset> - What is this??

        Example: 0x7c 0x03 0x20 0x20 0x0a 0x01 will draw a circle at (32,32)
        with a radius of 10 by setting the pixels

0x04 -  Toggles CR/LF

        0x7c 0x04

        Each time this command is sent, whether or not a CR automatically
        executes a LF is toggled. The value is saved to EEPROM and is
        persistent over power cycles

0x05 -  Erase block

        0x7c 0x05 <x1> <y1> <x2> <y2>

        Draws a block on the screen with clear (reverse=0) or set (reverse=1)
        pixels. Arguments <x1>,<y1>, <x2>, <y2> are the coordinates of two
        opposite corners of the block.

        Example: 0x7c 0x05 0x00 0x00 0x0f 0x0f clears from (0,0) to (15,15)
        inclusive which is a block of 16x16 pixels.

0x06 -  LCD reset

        0x7c 0x6

        Resets the LCD and clears the screen The x_offset and y_offset are set
        to 0.

0x07 -  Change baud rate

        0x7c 0x07 <baud_rate>

        Changes the default baud rate, the setting is persistent over power
        cycles. Where <baud_rate> is a value 1..6 defined as follows:

        1 - 4800
        2 - 9600
        3 - 19200
        4 - 38400
        5 - 57600
        6 - 115200 (Default)

        Example: 0x7c 0x07 0x05 sets the baud rate to 57600.

0x08 -  Toggle aux font

        0x7c 0x08

        This command toggles which font is used for rendering text. The
        command does not effect characters already displayed, just characters
        sent after the command has been issued.

0x0a  - Set font mode

        0x7c 0x0a <draw_mode>

        This command determines how the font is rendered to the screen. It
        uses the same modes as bitblt mode 7 (copy) is the default and this
        mode respects reverse. i.e. it clears pixels to draw characters if
        reverse = 1. The other modes do not respect reverse and are rendered
        with whatever the logical operation gives. Characters in internal
        memory are a stored set of clear characters i.e. a black font stroke
        on clear background.

        The <draw_mode> is defined as follows:

        0 - AND
        1 - NAND
        2 - OR
        3 - NOR
        4 - XOR
        5 - NXOR
        6 - Reserved (Do not use as this will result in corrupted characters).
        7 - Copy. This is the default mode and overwrites whatever is in the
            background, and is the only mode that respects reverse.

0x0b -  Draw sprite

        0x7c 0x0b <x> <y> <sprite_id> <draw_mode>

        Draws a sprite to the screen where <x> and <y> defined the coordinates
        of the top left corner of the sprit draw position. <sprite_id> is the
        identity of the sprite to draw and <draw_mode> is the mode to draw the
        sprite (See 0x08 Set font mode for a description of the modes).

        Example: 0x7c 0x0b 0x20 0x20 0x01 0x04 will XOR sprite 1 with the
        background at location (32, 32).

0x0c -  Draw line

        0x07c 0x0c <x1> <y1> <x2> <y2> <S_R>

        Draws a line on the screen from screen coordinate (x1, y1) to
        coordinate (x2, y2) inclusive. Where <S_R> defines how the line is
        drawn as follows:

        0 - Clear pixels
        1 - Set pixels.

        The command respects reverse, i.e. if reverse=1, S_R=1 clears pixels.

0x0d -  Upload sprite

        0x7c 0x0d <sprite_id> <width> <height> <sprite_data>*

        Uploads a sprite into memory where.

        <sprite_id> is the identity of the sprite to write 0..7
        (0..NUM_SPRITES-1). If the value sent is out of range, it will be
        written to the last sprite (NUM_SPRITES-1).

        <width> is the width of the sprite in pixels.

        <height> is the height of the sprite in pixels.

        <sprite_data> is <width> * <hight> bytes of image data.

        Image data is stored left to right, top to bottom. each byte defines
        an 8 pixel vertical stripe. So an nx8 sprite is n bytes long with one
        byte for each column.

        If the image is taller than 8 pixels, then the next n bytes store the
        next row. Height does not have to be a multiple of 8, but there must
        be enough rows so that (Number of rows)*8 >= (height in pixels). For
        example a 10x10 sprite would require 10 bytes/row (for x dimension)
        and 2 rows (2*8=16>10) or 20 bytes total.

        An example sprite is the Sparkfun logo; the command is defined as:

        0x7c 0x0d          // Command
        0x0n               // Sprite number
        0x0a 0x10          // Width = 10, Height = 16
        0x80 0xc0 0x40 0x0c 0x3e 0xfe 0xf2 0xe0 0xf0 0xe0 // Row 1
        0xff 0x7f 0x3f 0x1f 0x1f 0x1f 0x1f 0x0f 0x07 0x03 // Row 2
        0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 // Padding to ...
        0x00 0x00                                         // ... SPRITE_SIZE-2

        Notice that the logo itself is 10x16 and only requires 20 bytes to
        define, but you must send all (SPRITE_SIZE-2) image data bytes (data
        after those necessary to draw the sprite are ignored) or the display
        will get out of sync.

        There is a program in the utilities folder to convert a 24bbp bitmap
        to a sprite. it outputs the exact sprite data in binary format to
        stdout.

        NUM_SPRITES=8, SPRITE_SIZE=34 by default, to change this requires
        re-compiling the code takes 1 argument and SPRITE_SIZE data bytes.

0x0f -  Draw box

        0x7c 0x0f <x1> <y1> <x2> <y2> <S_R>

        This command draws an outline of a box with opposing corners (x1, y1)
        and (x2, y2). <S_R> defines the line type which respects reverse.

        Example: 0x7c 0x0f 0x04 0x05 0x0f 0x10 0x01 draws a box from (4,5) to
        (15,16).

0x10 -  Set pixel

        0x7c 0x10 <x> <y> <S_R>

        Sets or resets a pixel at coordinate (x, y) with colour S_R.

        Example: 0x7c 0x10 0x9 0x4 0x01 sets the pixel at (9, 4) to be on.

0x12 -  Draw filled box

        0x7c 0x12 <x1> <y1> <x2> <y2> <fill_byte>

        This draws a box much like the previous draw box command which is
        described by the opposing corners (x1, y1) and (x2, y2), but fills the
        box with the fill_byte. The fill byte describes an 8-pixel high stripe
        that is repeated every x pixels and every 8 y pixels. The most useful
        values of fill_byte are 0x00 to clear the box and 0xff to fill it.

0x14 -  Reverse mode

        0x7c 0x14

        Toggles reverse (white on black) mode. The new reverse mode inverts
        the screen in place, it does not clear the screen or change the text
        drawing position.

0x15 -  Toggle splash

        0x7c 0x15

        Toggles whether or not the splash screen is displayed on startup. The
        setting is persistent over power cycles.

0x16:   BitBlt

        0x7c 0x16 <x> <y> <draw_mode> <width> <height> <sprite_data>*

        The BitBlt command allows graphics to be immediately drawn to the
        screen like sprites, but the data does not have to be uploaded first.
        There are no size restrictions other than the data must fit the
        drawable area of the display. The arguments are defined as follows:

        <x> - The x coordinate 0..127

        <y> - The y coordinate 0..63

        <draw_mode> The drawing mode (XOR, Copy etc.)

        <width> is the width of the sprite in pixels.

        <height> is the height of the sprite in pixels.

        <sprite_data> is <width> * <hight> bytes of image data.

        The width and height are ordered so you can send sprite data directly
        to BitBlt from a file with a terminal program. Sent the x, y,
        draw_mode bytes first and then send the file (i.e. made with the
        bmp2bin_sprite program in the utilities folder).

0x18  - Set x_offset

        0x7c 0x18 <x>

        Sets the x coordinate where the upper left corner where the next
        character will be drawn.

0x19 -  Set y_offset

        0x7c 0x19 <y>

        Sets the y coordinate where the upper left corner where the next
        character will be drawn.

The following commands are exposed interfaces to the internal LCD read/write
functions. It is recommend that these are not used, but if there is something
you absolutely cannot do with the standard graphical functions, these provide
direct access to the LCD.

0x1a -  Write command

        0x7c 0x1a <byte> <chip>

        Writes a command to the LCD controller chips. The command does not set
        the address registers which must be set before hand.

        The command takes two arguments:

        <byte> is the value of the byte to write

        <chip> selects which of the 2 KS0108 chips to send it to which may be
        1, 2 or 3 which indicates both chips.

0x1b -  Write data

        0x7c 0x1b <data> <chip>

        Writes a data byte to the LCD controller chips. The command does not set
        the address registers which must be set before hand.

        The command takes two arguments:

        <data> is the value of the byte to write

        <chip> selects which of the 2 KS0108 chips to send it to which may be
        1, 2 or 3 which indicates both chips.

0x1c -  Write block

        0x7c 0x1c <x> <page> <length> <data>*

        This is a slightly higher level function that writes a sequence of
        bytes to the display. The command automatically crosses chips and sets
        the correct registers. The command takes three arguments followed by a
        sequence of data bytes where:

        <x> - The x coordinate 0..127

        <page> - The page.

        <length> defines the length of the following data (max 128).

0x1d -  Read data

        0x7c 0x1d <side>

        Reads a data byte from one of the controller chips. This command does
        not set the address registers, which must be set before hand.

        The command takes a single argument <side> which may be 1 or 2 which
        is used to select which KS0108 to read.

        The command returns data bytes on the UART. Where the debug_level is 0
        or 1 the data is returned as a binary value, otherwise it is ASCII.

0x1e -  Read byte

        0x7c 0x1e <x> <side>

        A slightly higher level function which returns a byte at a specific
        <x> coordinate, the page must be set separately. The command takes two
        arguments, <x> which is the x coordinate and <side> which is 1 or 2 to
        select the chip to read.

        The command returns values on the UART. Where debug_level is 0 or 1
        the data is returned as a binary values otherwise it is ASCII.

0x1f -  Read block

        0x7c 0x1f <x> <page> <length>

        A slightly higher level function which returns a sequence of data
        bytes from a specific page. The command automatically crosses chips
        and sets the address registers appropriately.

        The command takes 3 arguments:

        <x> is the  x-coordinate

        <page> is the page index.

        <length> is the amount of data to read, maximum is 128.

        The command returns the data on the UART. Where debug_level is 0 or 1
        the data is returned as binary values, otherwise it is ASCII.

0x20 -  Set y register

        0x7c 0x20 <y>

        For reasons unknown the data sheet for the KS0108 uses y to label the
        horizontal axis. This sets the y register on the LCD controller chips.
        y counts from 0 to 63 and starts at the left of the display. Any value
        over 63 is handled by the second chip.

        The command takes a single argument, <y> and sets it on both chips
        simultaneously.

0x21 -  Set page

        0x7x 0x21 <page>

        The display is broken up into 8 pages which describe horizontal rows 8
        pixels high. Pages start at 0 at the top of the display and go to 7 at
        the bottom.

        This command takes a single argument <page> and sets both chips
        simultaneously.

Change History
==============

2015-03-19 - Jon Green

Fixed bitblt. When the bitblt data has a height of less than 8 then the
display incorrectly clears the remainder of the row block if the data is not
split over a row boundary. This fault also affects box fill.

Fixed box fill. The box width and height were incorrectly calculated as the
difference of the x and y coordinates respectively. The actual width and
height are the difference of the two opposing vertices plus 1. The box
parameters are then the same as the unfilled box.

Fixed USART ISR vector which has changed since this code was originally
written.

Fixed font.h and aux_font.h should be defined as 'const' in order to utilise
PROGMEM memory.

Formatted the README notes to make a little easier to read and print.

The RX buffer is reduced to 200 bytes. The memory of Jen Holt was so tight
that adding a single additional char (or just using a later version of GCC
maybe) to the bitblt operation collided the stack with the heap causing a
crash in the display firmware. The reduced RX buffer should provide sufficient
headroom for the stack without compromising the sprites and is not a problem
when using XON/OFF and 200 is still generous.

Tool chain to build serialGLCD
==============================

On a Mac you need the AVR tools.

http://www.obdev.at/products/crosspack/download.html

The library was built against CrossPack-AVR-20131216

To program the Sparkfun Graphic LCD Backpack
============================================

See the following for some background reference to programming the backpack:

https://learn.sparkfun.com/tutorials/installing-an-arduino-bootloader
http://arduino.cc/en/Tutorial/ArduinoISP

Looking at the back of the Sparkfun LCD Backpack then the pin out is defined
as follows:

+------------------------------------------------------+
|                      Top of Panel                    |
|                                                      |
|                                                      |
|                                                      |
|   +----------------------------------------+         |
|   |           (2) (4) (6)      Graphic LCD |         |
|   |           VCC MOSI GND       Backpack  |         |
|   |            x   x   x                   |         |
|   |            x   x   x                   |         |
|   |          MISO SCK Reset                |         |
|   |           (1) (3) (5)                  |         |
|   |                                        |         |
|   +----------------------------------------+         |
|                                                      |
+------------------------------------------------------+

Solder connectors to the ICSP pin holes on the middle top of the Sparkfun
Graphic LCD Backpack. It is easier to fed the wires with connector from below
and solder from the top.

If you do not have a programmer then use a 5v Arduino (i.e. UNO). To use the
Arduino then load the ArduinoISP sketch and then power off.

Connect up the Sparkfun GLCD to the Arduino as follows:

Arduino    Sparkfun
-------    --------
5v/Vcc      VCC / Pin 2
GND         GND / Pin 6
MOSI/D11    MOSI / Pin 4
MISO/D12    MISO / Pin 1
SCK/D13     SCK / Pin 3
D10         Reset / Pin 5

Use a 10uF / 16v capacitor connected between the Arduino Reset and GND pins on
the UNO (In the UK you can get one in Maplins with code AT98G).

Once connected then power up the Arduino, modify the Makefile for the Arduino
and then:

zsh% make program

This will program the Sparkfun Graphics LCD.

cd /Users/jon/dev/serialGLCD/firmware/trunk/ make program

avrdude -p atmega168 -P /dev/cu.usbmodem000001 -c arduino    -b 19200 -U flash:w:main.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e9406
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "main.hex"
avrdude: input file main.hex auto detected as Intel Hex
avrdude: writing flash (11278 bytes):

Writing | ################################################## | 100% 14.32s

avrdude: 11278 bytes of flash written
avrdude: verifying flash memory against main.hex:
avrdude: load data flash data from input file main.hex:
avrdude: input file main.hex auto detected as Intel Hex
avrdude: input file main.hex contains 11278 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 8.41s

avrdude: verifying ...
avrdude: 11278 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

[EXIT 0]
