Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

RA8875.h

Committer:
WiredHome
Date:
2014-03-23
Revision:
63:ed787f5fcdc4
Parent:
53:86d24b9480b9

File content as of revision 63:ed787f5fcdc4:

#ifndef RA8875_H
#define RA8875_H
#include <mbed.h>

#include "GraphicsDisplay.h"
#include "PNG.h"

#define RA8875_DEFAULT_SPI_FREQ 5000000

// Define this to enable code that monitors the performance of various
// graphics commands.
#define PERF_METRICS

// What better place for some test code than in here and the companion
// .cpp file. See also the bottom of this file.
#define TESTENABLE

/// DOS colors - slightly color enhanced
#define Black       (color_t)(RGB(0,0,0))
#define Blue        (color_t)(RGB(0,0,187))
#define Green       (color_t)(RGB(0,187,0))
#define Cyan        (color_t)(RGB(0,187,187))
#define Red         (color_t)(RGB(187,0,0))
#define Magenta     (color_t)(RGB(187,0,187))
#define Brown       (color_t)(RGB(187,187,0))
#define Gray        (color_t)(RGB(187,187,187))
#define Charcoal    (color_t)(RGB(85,85,85))
#define BrightBlue  (color_t)(RGB(85,85,255))
#define BrightGreen (color_t)(RGB(85,255,85))
#define BrightCyan  (color_t)(RGB(85,255,255))
#define Orange      (color_t)(RGB(255,85,85))
#define Pink        (color_t)(RGB(255,85,255))
#define Yellow      (color_t)(RGB(255,255,85))
#define White       (color_t)(RGB(255,255,255))

#define BrightRed   (color_t)(RGB(255,0,0))

//namespace SW_graphics
//{


/// This is a graphics library for the Raio RA8875 Display Controller chip
/// attached to a 4-wire SPI interface.
///
/// It offers both primitive and high level APIs.\\
/// Central to this API is a coordinate system, where the origin (0,0) is in
/// the top-left corner of the display, and the width extends positive to the
/// right and the height extends positive toward the bottom.
///
/// As there are both graphics and text commands, one must take care to use
/// the proper coordinate system for each. Some of the text APIs are in units
/// of column and row, which is measured in character positions (and dependent
/// on the font size), and other text APIs permit pixel level positioning.
///
/// @todo Add Scroll support for text.
/// @todo Improve sync between internal and external font support - cursor, window, scroll.
/// @todo Find out why it can't shift frequency after constructor runs.
/// @todo Add Hardware reset signal.
/// @todo Add Touch Screen support.
/// @todo Add Keypad Support.
/// @todo Add high level objects - x-y graph, meter, others... but these will
///     probably be best served in another class, since they may not
///     be needed for many uses.
/// 
class RA8875 : public GraphicsDisplay
{
public:   
    /// cursor type to be shown as the text cursor.
    typedef enum
    {
        NOCURSOR,   ///< cursor is hidden
        IBEAM,      ///< | cursor
        UNDER,      ///< _ cursor
        BLOCK       ///< Block cursor
    } cursor_t;

    /// font type selection.
    typedef enum
    {
        ISO8859_1,      ///< ISO8859-1 font
        ISO8859_2,      ///< ISO8859-2 font
        ISO8859_3,      ///< ISO8859-3 font
        ISO8859_4       ///< ISO8859-4 font
    } font_t;
    
    /// font rotation selection
    typedef enum
    {
        normal,         ///< normal orientation
        rotated         ///< rotated orientation
    } font_angle_t;
    
    /// alignment  
    typedef enum
    {
        align_none,     ///< align - none
        align_full      ///< align - full
    } alignment_t;    
    
    /// Scale factor - 1, 2, 3 4
    typedef int HorizontalScale;
    
    /// Scale factor - 1, 2, 3, 4
    typedef int VerticalScale;

    /// Clear screen region
    typedef enum
    {
        FULLWINDOW,     ///< Full screen
        ACTIVEWINDOW    ///< active window/region
    } Region_t;
    
    /// Set the Layer 1/2 Display Mode
    typedef enum
    {
        OnlyLayer1,         ///< Only layer 1 is visible
        OnlyLayer2,         ///< Only layer 2 is visible
        LightenOverlay,     ///< Lighten-overlay mode
        TransparentMode,    ///< Transparent mode
        BooleanOR,          ///< Boolean OR mode
        BooleanAND,         ///< Boolean AND mode
        FloatingWindow      ///< Floating Window mode
    } LayerMode_T;
    
    /// Constructor for a display based on the RAiO RA8875 
    /// display controller.
    ///
    /// @param mosi is the SPI master out slave in pin on the mbed.
    /// @param miso is the SPI master in slave out pin on the mbed.
    /// @param sclk is the SPI shift clock pin on the mbed.
    /// @param csel is the DigitalOut pin on the mbed to use as the
    ///         active low chip select for the display controller.
    /// @param reset is the DigitalOut pin on the mbed to use as the 
    ///         active low reset input on the display controller - 
    ///         but this is not currently used.
    /// @param name is a text name for this object, which will permit
    ///         capturing stdout and printf() directly to it.
    ///
    RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char * name = "lcd");
    
    // Destructor doesn't have much to do as this would typically be created
    // at startup, and not at runtime.
    //~RA8875();
    
    /// Select the drawing layer for subsequent commands.
    ///
    /// If the screen configuration is 480 x 272, or if it is 800 x 480 
    /// and 8-bit color, the the display supports two layers, which can 
    /// be independently drawn on and shown. Additionally, complex
    /// operations involving both layers are permitted.
    ///
    /// @note The user manual refers to Layer 1 and Layer 2, however the
    ///     actual register values are value 0 and 1. This and other APIs
    ///     that reference the layers use the values 0 and 1.
    ///
    /// @param layer selects the layer for subsequence commands, where
    ///     the values 0 and 1 represent layers 1 and 2 (as referred
    ///     to in the user manual).
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SelectDrawingLayer(uint16_t layer);
    
    /// Set the Layer presentation mode.
    ///
    /// This sets the presentation mode for layers, and permits showing
    /// a single layer, or applying a mode where the two layers
    /// are combined using one of the hardware methods.
    ///
    /// @param mode sets the mode in the Layer Transparency Register.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SetLayerMode(LayerMode_T mode);
    
    /// Set the layer transparency for each layer.
    ///
    /// Set the transparency, where the range of values is
    /// from zero (fully visible) to eight (fully transparent).
    /// The input value is automatically limited to this range.
    ///
    /// @param layer1 sets the layer 1 transparency.
    /// @param layer2 sets the layer 2 transparency.
    /// @returns success/failure code. @see RetCode_t.
    /// 
    RetCode_t SetLayerTransparency(uint8_t layer1, uint8_t layer2);
    
    /// Set the background color register used for transparency.
    ///
    /// This command sets the background color registers that are used
    /// in the transparent color operations involving the layers.
    /// 
    /// @param color is optional and expressed in 16-bit format. If not
    ///     supplied, a default of Black is used.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SetBackgroundTransparencyColor(color_t color = RGB(0,0,0));
    
    /// Write a command to the display with a word of data.
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @param command is the command to write.
    /// @param data is data to be written to the command register.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t WriteCommandW(uint8_t command, uint16_t data);

    /// Write a command to the display
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @param command is the command to write.
    /// @param data is optional data to be written to the command register
    ///     and only occurs if the data is in the range [0 - 0xFF].
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t WriteCommand(unsigned char command, unsigned int data = 0xFFFF);
    
    /// Write a data word to the display
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @param data is the data to write.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t WriteDataW(uint16_t data);
    
    /// Write a data byte to the display
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @param data is the data to write.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t WriteData(unsigned char data);
    
    /// Read a command register
    ///
    /// @param command is the command register to read.
    /// @returns the value read from the register.
    ///
    unsigned char ReadCommand(unsigned char command);
    
    /// Read a data byte from the display
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @returns data that was read.
    ///
    unsigned char ReadData(void);
    
    /// Read a word from the display
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @returns data that was read.
    ///
    uint16_t ReadDataW(void);

    /// Read the display status
    ///
    /// This is a high level command, and may invoke several primitives.
    ///
    /// @returns data that was read.
    ///
    unsigned char ReadStatus(void);

    /// get the width in pixels of the currently active font
    ///
    /// @returns font width in pixels.
    ///    
    dim_t fontwidth(void);
    
    /// get the height in pixels of the currently active font
    ///
    /// @returns font height in pixels.
    ///    
    dim_t fontheight(void);
    
    /// get the number of colums based on the currently active font
    ///
    /// @returns number of columns.
    ///    
    virtual int columns(void);

    /// get the number of rows based on the currently active font
    ///
    /// @returns number of rows.
    ///    
    virtual int rows(void);

    /// get the screen width in pixels
    ///
    /// @returns screen width in pixels.
    ///
    virtual dim_t width(void);

    /// get the screen height in pixels
    ///
    /// @returns screen height in pixels.
    ///
    virtual dim_t height(void);

    /// get the color depth in bits per pixel.
    ///
    /// @returns 8 or 16 only.
    ///
    virtual dim_t color_bpp(void);

    /// Set cursor position based on the current font size.
    /// 
    /// @param column is the horizontal position in character positions
    /// @param row is the vertical position in character positions
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t locate(textloc_t column, textloc_t row);

    /// Prepare the controller to write text to the screen by positioning
    /// the cursor.
    ///
    /// @param x is the horizontal position in pixels (from the left edge)
    /// @param y is the vertical position in pixels (from the top edge)
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SetTextCursor(loc_t x, loc_t y);

    /// Get the current cursor position in pixels.
    ///
    /// @returns cursor position.
    ///
    point_t GetTextCursor(void);
    
    /// Get the current cursor horizontal position in pixels.
    ///
    /// @returns cursor position horizontal offset.
    ///
    loc_t GetTextCursor_X(void);

    /// Get the current cursor vertical position in pixels.
    ///
    /// @returns cursor position vertical offset.
    ///
    loc_t GetTextCursor_Y(void);

    /// Configure additional Cursor Control settings.
    ///
    /// This API lets you modify other cursor control settings; 
    /// Cursor visible/hidden, Cursor blink/normal, 
    /// Cursor I-Beam/underscore/box.
    ///
    /// @param cursor can be set to NOCURSOR (default), IBEAM,
    ///         UNDER, or BLOCK.
    /// @param blink can be set to true or false (default false)
    /// @returns success/failure code. @see RetCode_t
    ///
    RetCode_t SetTextCursorControl(cursor_t cursor = NOCURSOR, bool blink = false);
    
    /// Select the ISO 8859-X font to use next.
    ///
    /// Supported fonts: ISO 8859-1, -2, -3, -4
    ///
    /// @param font selects the font for the subsequent text rendering.
    ///
    /// @note if either hScale or vScale is outside of its permitted range,
    ///     the command is not executed.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SetTextFont(font_t font = ISO8859_1);
    
    /// Control the font behavior.
    ///
    /// This command lets you make several modifications to any text that
    /// is written.
    ///
    /// Options can be combined:
    /// Default:
    /// @li Full alignment disabled, 
    /// @li Font with Background color, 
    /// @li Font in normal orientiation,
    /// @li Horizontal scale x 1
    /// @li Vertical scale x 1
    /// @li alignment
    /// 
    /// @param fillit defaults to FILL, but can be NOFILL
    /// @param angle defaults to normal, but can be rotated
    /// @param hScale defaults to 1, but can be 1, 2, 3, or 4,
    ///     and scales the font size by this amount.
    /// @param vScale defaults to 1, but can be 1, 2, 3, or 4,
    ///     and scales the font size by this amount.
    /// @param alignment defaults to align_none, but can be
    ///     align_full.
    /// 
    /// @note if either hScale or vScale is outside of its permitted range,
    ///     the command is not executed.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SetTextFontControl(fill_t fillit = FILL, 
        font_angle_t angle = normal, 
        HorizontalScale hScale = 1, 
        VerticalScale vScale = 1, 
        alignment_t alignment = align_none);
    
    /// Control the font size
    ///
    /// This command lets you set the font enlargement for both horizontal
    /// and vertical, independent of the rotation, background, and 
    /// alignment. @see SetTextFontControl.
    ///
    /// @param hScale defaults to 1, but can be 1, 2, 3, or 4,
    ///     and scales the font size by this amount.
    /// @param vScale is an optional parameter that defaults to the hScale value, 
    ///     but can be 1, 2, 3, or 4, and scales the font size by this amount.
    ///
    /// @code
    ///     lcd.SetTextFontSize(2);     // Set the font to 2x normal size
    ///     lcd.SetTextFontSize(2,3);   // Set the font to 2x Width and 3x Height
    ///     lcd.SetTextFontSize();      // Restore to normal size in both dimensions
    /// @endcode
    ///
    /// @note if either hScale or vScale is outside of its permitted range,
    ///     the command is not executed.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t SetTextFontSize(HorizontalScale hScale = 1, VerticalScale vScale = -1);
    
    /// put a character on the screen.
    ///
    /// @param c is the character.
    /// @returns the character, or EOF if there is an error.
    ///
    virtual int _putc(int c);

    /// Write string of text to the display
    ///
    /// @param string is the null terminated string to send to the display.
    ///
    void puts(const char * string);
    
    /// Write string of text to the display at the specified location.
    ///
    /// @param x is the horizontal position in pixels (from the left edge)
    /// @param y is the vertical position in pixels (from the top edge)
    /// @param string is the null terminated string to send to the display.
    ///
    void puts(loc_t x, loc_t y, const char * string);
    
    /// Prepare the controller to write binary data to the screen by positioning
    /// the memory cursor.
    ///
    /// @param x is the horizontal position in pixels (from the left edge)
    /// @param y is the vertical position in pixels (from the top edge)
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t SetGraphicsCursor(loc_t x, loc_t y);
    
    /// Prepare the controller to read binary data from the screen by positioning
    /// the memory read cursor.
    ///
    /// @param x is the horizontal position in pixels (from the left edge)
    /// @param y is the vertical position in pixels (from the top edge)
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t SetGraphicsCursorRead(loc_t x, loc_t y);
    
    /// Set the window, which controls where items are written to the screen.
    ///
    /// When something hits the window width, it wraps back to the left side
    /// and down a row. If the initial write is outside the window, it will
    /// be captured into the window when it crosses a boundary.
    ///
    /// @param x is the left edge in pixels.
    /// @param y is the top edge in pixels.
    /// @param width is the window width in pixels.
    /// @param height is the window height in pixels.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t window(loc_t x, loc_t y, dim_t width, dim_t height);
    
    /// Clear the screen.
    ///
    /// The behavior is to clear the whole screen. @see clsw().
    ///
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t cls(void);
    
    /// Clear the screen, or clear only the active window.
    ///
    /// The default behavior is to clear the whole screen. With the optional 
    /// parameter, the action can be restricted to the active window, which
    /// can be set with the @see window method.
    ///
    /// @param region is an optional parameter that defaults to FULLWINDOW
    ///         or may be set to ACTIVEWINDOW.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t clsw(RA8875::Region_t region = FULLWINDOW);

    /// Set the background color.
    ///
    /// @param color is expressed in 16-bit format.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t background(color_t color);
    
    /// Set the background color.
    ///
    /// @param r is the red element of the color.
    /// @param g is the green element of the color.
    /// @param b is the blue element of the color.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t background(unsigned char r, unsigned char g, unsigned char b);
    
    /// Set the foreground color.
    ///
    /// @param color is expressed in 16-bit format.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t foreground(color_t color);
    
    /// Set the foreground color.
    ///
    /// @param r is the red element of the color.
    /// @param g is the green element of the color.
    /// @param b is the blue element of the color.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t foreground(unsigned char r, unsigned char g, unsigned char b);
    
    /// Get the current foreground color value.
    ///
    /// @returns the current foreground color.
    ///
    color_t GetForeColor(void);
        
    /// Draw a pixel in the specified color.
    ///
    /// @note Unlike many other operations, this does not
    ///         set the forecolor!
    ///
    /// @param x is the horizontal offset to this pixel.
    /// @param y is the vertical offset to this pixel.
    /// @param color defines the color for the pixel.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t pixel(loc_t x, loc_t y, color_t color);
    
    /// Draw a pixel in the current foreground color.
    ///
    /// @param x is the horizontal offset to this pixel.
    /// @param y is the veritical offset to this pixel.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t pixel(loc_t x, loc_t y);
    
    /// Get a pixel from the display.
    ///
    /// @param x is the horizontal offset to this pixel.
    /// @param y is the vertical offset to this pixel.
    /// @returns the pixel. see @color_t
    ///
    virtual color_t getPixel(loc_t x, loc_t y);
    
    /// Write a stream of pixels to the display.
    ///
    /// @param p is a pointer to a color_t array to write.
    /// @param count is the number of pixels to write.
    /// @param x is the horizontal position on the display.
    /// @param y is the vertical position on the display.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y);
    
    /// Get a stream of pixels from the display.
    ///
    /// @param p is a pointer to a color_t array to accept the stream.
    /// @param count is the number of pixels to read.
    /// @param x is the horizontal offset to this pixel.
    /// @param y is the vertical offset to this pixel.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y);
    
    /// Draw a line in the specified color
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal start of the line.
    /// @param y1 is the vertical start of the line.
    /// @param x2 is the horizontal end of the line.
    /// @param y2 is the vertical end of the line.
    /// @param color defines the foreground color.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        color_t color);

    /// Draw a line
    ///
    /// Draws a line using the foreground color setting.
    ///
    /// @param x1 is the horizontal start of the line.
    /// @param y1 is the vertical start of the line.
    /// @param x2 is the horizontal end of the line.
    /// @param y2 is the vertical end of the line.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t line(loc_t x1, loc_t y1, loc_t x2, loc_t y2);

    /// Draw a rectangle in the specified color
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal start of the line.
    /// @param y1 is the vertical start of the line.
    /// @param x2 is the horizontal end of the line.
    /// @param y2 is the vertical end of the line.
    /// @param color defines the foreground color.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        color_t color, fill_t fillit = NOFILL);

    /// Draw a filled rectangle in the specified color
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal start of the line.
    /// @param y1 is the vertical start of the line.
    /// @param x2 is the horizontal end of the line.
    /// @param y2 is the vertical end of the line.
    /// @param color defines the foreground color.
    /// @param fillit is optional to NOFILL the rectangle. default is FILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    virtual RetCode_t fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        color_t color, fill_t fillit = FILL);

    /// Draw a rectangle
    ///
    /// Draws a rectangle using the foreground color setting.
    ///
    /// @param x1 is the horizontal start of the line.
    /// @param y1 is the vertical start of the line.
    /// @param x2 is the horizontal end of the line.
    /// @param y2 is the vertical end of the line.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        fill_t fillit = NOFILL);

    /// Draw a filled rectangle with rounded corners using the specified color.
    ///
    /// This draws a rounded rectangle. A numbers of checks are made on the values,
    /// and it could reduce this to drawing a line (if either x1 == x2, or y1 == y2),
    /// or a single point (x1 == x2 && y1 == y2). If the radius parameters are
    /// > 1/2 the length of that side (width or height), an error value is returned.
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal start of the line and must be <= x2.
    /// @param y1 is the vertical start of the line and must be <= y2.
    /// @param x2 is the horizontal end of the line and must be >= x1.
    /// @param y2 is the vertical end of the line and must be >= y1.
    /// @param radius1 defines the horizontal radius of the curved corner. Take care
    ///         that this value < 1/2 the width of the rectangle, or bad_parameter 
    ///         is returned.
    /// @param radius2 defines the vertical radius of the curved corner. Take care
    ///         that this value < 1/2 the height of the rectangle, or bad_parameter 
    ///         is returned.
    /// @param color defines the foreground color.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t fillroundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        dim_t radius1, dim_t radius2, color_t color, fill_t fillit = FILL);

    /// Draw a rectangle with rounded corners using the specified color.
    ///
    /// This draws a rounded rectangle. A numbers of checks are made on the values,
    /// and it could reduce this to drawing a line (if either x1 == x2, or y1 == y2),
    /// or a single point (x1 == x2 && y1 == y2). If the radius parameters are
    /// > 1/2 the length of that side (width or height), an error value is returned.
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal start of the line and must be <= x2.
    /// @param y1 is the vertical start of the line and must be <= y2.
    /// @param x2 is the horizontal end of the line and must be >= x1.
    /// @param y2 is the vertical end of the line and must be >= y1.
    /// @param radius1 defines the horizontal radius of the curved corner. Take care
    ///         that this value < 1/2 the width of the rectangle, or bad_parameter 
    ///         is returned.
    /// @param radius2 defines the vertical radius of the curved corner. Take care
    ///         that this value < 1/2 the height of the rectangle, or bad_parameter 
    ///         is returned.
    /// @param color defines the foreground color.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        dim_t radius1, dim_t radius2, color_t color, fill_t fillit = NOFILL);

    /// Draw a rectangle with rounded corners.
    ///
    /// This draws a rounded rectangle. A numbers of checks are made on the values,
    /// and it could reduce this to drawing a line (if either x1 == x2, or y1 == y2),
    /// or a single point (x1 == x2 && y1 == y2). If the radius parameters are
    /// > 1/2 the length of that side (width or height), an error value is returned.
    ///
    /// @param x1 is the horizontal start of the line and must be <= x2.
    /// @param y1 is the vertical start of the line and must be <= y2.
    /// @param x2 is the horizontal end of the line and must be >= x1.
    /// @param y2 is the vertical end of the line and must be >= y1.
    /// @param radius1 defines the horizontal radius of the curved corner. Take care
    ///         that this value < 1/2 the width of the rectangle, or bad_parameter 
    ///         is returned.
    /// @param radius2 defines the vertical radius of the curved corner. Take care
    ///         that this value < 1/2 the height of the rectangle, or bad_parameter 
    ///         is returned.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        dim_t radius1, dim_t radius2, fill_t fillit = NOFILL);

    /// Draw a triangle in the specified color.
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal for point 1.
    /// @param y1 is the vertical for point 1. 
    /// @param x2 is the horizontal for point 2.
    /// @param y2 is the vertical for point 2.
    /// @param x3 is the horizontal for point 3.
    /// @param y3 is the vertical for point 3.
    /// @param color defines the foreground color.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        loc_t x3, loc_t y3, color_t color, fill_t fillit = NOFILL);
    
    /// Draw a filled triangle in the specified color.
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x1 is the horizontal for point 1.
    /// @param y1 is the vertical for point 1.
    /// @param x2 is the horizontal for point 2.
    /// @param y2 is the vertical for point 2.
    /// @param x3 is the horizontal for point 3.
    /// @param y3 is the vertical for point 3.
    /// @param color defines the foreground color.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t filltriangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        loc_t x3, loc_t y3, color_t color, fill_t fillit = FILL);

    /// Draw a triangle
    ///
    /// Draws a triangle using the foreground color setting.
    ///
    /// @param x1 is the horizontal for point 1.
    /// @param y1 is the vertical for point 1.
    /// @param x2 is the horizontal for point 2.
    /// @param y2 is the vertical for point 2.
    /// @param x3 is the horizontal for point 3.
    /// @param y3 is the vertical for point 3.
    /// @param fillit is optional to FILL the rectangle. default is NOFILL.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
        loc_t x3, loc_t y3, fill_t fillit = NOFILL);
    
    /// Draw a circle using the specified color.
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x is the horizontal center of the circle.
    /// @param y is the vertical center of the circle.
    /// @param radius defines the size of the circle.
    /// @param color defines the foreground color.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t circle(loc_t x, loc_t y, dim_t radius, color_t color, fill_t fillit = NOFILL);

    /// Draw a filled circle using the specified color.
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x is the horizontal center of the circle.
    /// @param y is the vertical center of the circle.
    /// @param radius defines the size of the circle.
    /// @param color defines the foreground color.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t fillcircle(loc_t x, loc_t y, dim_t radius, color_t color, fill_t fillit = FILL);

    /// Draw a circle.
    ///
    /// Draws a circle using the foreground color setting.
    ///
    /// @param x is the horizontal center of the circle.
    /// @param y is the vertical center of the circle.
    /// @param radius defines the size of the circle.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t circle(loc_t x, loc_t y, dim_t radius, fill_t fillit = NOFILL);

    /// Draw an Ellipse using the specified color
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x is the horizontal center of the ellipse.
    /// @param y is the vertical center of the ellipse.
    /// @param radius1 defines the horizontal radius of the ellipse.
    /// @param radius2 defines the vertical radius of the ellipse.
    /// @param color defines the foreground color.
    /// @param fillit defines whether the circle is filled or not.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, 
        color_t color, fill_t fillit = NOFILL);

    /// Draw a filled Ellipse using the specified color
    ///
    /// @note As a side effect, this changes the current
    ///     foreground color for subsequent operations.
    ///
    /// @param x is the horizontal center of the ellipse.
    /// @param y is the vertical center of the ellipse.
    /// @param radius1 defines the horizontal radius of the ellipse.
    /// @param radius2 defines the vertical radius of the ellipse.
    /// @param color defines the foreground color.
    /// @param fillit defines whether the circle is filled or not.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t fillellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, 
        color_t color, fill_t fillit = FILL);

    /// Draw an Ellipse
    ///
    /// Draws it using the foreground color setting.
    ///
    /// @param x is the horizontal center of the ellipse.
    /// @param y is the vertical center of the ellipse.
    /// @param radius1 defines the horizontal radius of the ellipse.
    /// @param radius2 defines the vertical radius of the ellipse.
    /// @param fillit defines whether the circle is filled or not.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, fill_t fillit = NOFILL);
    
    /// Control display power
    ///
    /// @param on when set to true will turn on the display, when false it is turned off.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t Power(bool on);

    /// Reset the display controller via the Software Reset interface.
    ///
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t Reset(void);
    
    /// Set backlight brightness.
    ///
    /// When the built-in PWM is used to control the backlight, this 
    /// API can be used to set the brightness.
    /// 
    /// @param brightness ranges from 0 (off) to 255 (full on)
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t Backlight_u8(unsigned char brightness);
    
    /// Set backlight brightness.
    ///
    /// When the built-in PWM is used to control the backlight, this 
    /// API can be used to set the brightness.
    /// 
    /// @param brightness ranges from 0.0 (off) to 1.0 (full on)
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t Backlight(float brightness);

    /// Select a bitmap font (provided by the user) for all subsequent text.
    ///
    /// @note Tool to create the fonts is accessible from its creator
    ///     available at http://www.mikroe.com. 
    ///     Change the data to an array of type char[].
    ///
    /// @param font is a pointer to a specially formed font array.
    ///     This special font array has a 4-byte header, followed by 
    ///     the data:
    ///   - the number of bytes per char
    ///   - the vertical size in pixels for each character
    ///   - the horizontal size in pixels for each character
    ///   - the number of bytes per vertical line (width of the array)
    /// @returns error code.
    ///
    virtual RetCode_t set_font(const unsigned char * font = NULL);

    /// Get the RGB value for a DOS color.
    ///
    /// @param i is the color, in the range 0 to 15;
    /// @returns the RGB color of the selected index, or 0 
    ///     if the index is out of bounds.
    ///
    color_t DOSColor(int i);

    /// Get the color name (string) for a DOS color.
    ///
    /// @param i is the color, in the range 0 to 15;
    /// @returns a pointer to a string with the color name,
    ///     or NULL if the index is out of bounds.
    /// 
    const char * DOSColorNames(int i);


#ifdef PERF_METRICS
    /// Clear the performance metrics to zero.
    void ClearPerformance();
    
    /// Report the performance metrics for drawing functions using
    /// the available serial channel.
    ///
    /// @param pc is the serial channel to write to.
    ///
    void ReportPerformance(Serial & pc);
#endif

private:
    /// Set the SPI port frequency (in Hz).
    ///
    /// @note attempts to call this API at runtime, with the display
    ///         already online, cause the system to lockup. 
    ///         Not sure why, so moving this to private to run once.
    ///
    /// This uses the mbed SPI driver, and is therefore dependent on
    /// its capabilities. Limited tests were performed for the display
    /// in the range of 1,000,000 to 50,000,000 Hz. The display was
    /// a bit erratic above 20,000,000 Hz, so this became the default,
    /// even though it might have been the bench-level wiring that posed
    /// the limit.
    ///
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t frequency(unsigned long Hz = RA8875_DEFAULT_SPI_FREQ);
    

    /// Initialize the chip, which is normally done as part of the
    /// constructor, so not called by the user.
    ///
    /// @note This API permits configuration, however it is not [yet]
    ///     available to the end user. Be sure the parameters
    ///     are consistent with each other - see the RA8875 user
    ///     manual.
    ///
    /// @param width in pixels to configure the display for.
    /// @param height in pixels to configure the display for.
    /// @param color_bpp can be either 8 or 16, but must be consistent
    ///     with the width and height parameters.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t init(int width, int height, int color_bpp);
    
    /// method indicating the start of a graphics stream.
    ///
    /// This is called prior to a stream of pixel data being sent.
    /// This may cause register configuration changes in the derived
    /// class in order to prepare the hardware to accept the streaming
    /// data.
    ///
    /// Following this command, a series of @see putp() commands can
    /// be used to send individual pixels to the screen.
    ///
    /// To conclude the graphics stream, @see _EndGraphicsStream should
    /// be callled.
    ///
    /// @returns error code.
    ///
    virtual RetCode_t _StartGraphicsStream(void);
    
    /// method to put a single color pixel to the screen.
    ///
    /// This method may be called as many times as necessary after 
    /// @see _StartGraphicsStream() is called, and it should be followed 
    /// by _EndGraphicsStream.
    ///
    /// @param pixel is a color value to be put on the screen.
    /// @returns error code.
    ///
    virtual RetCode_t putp(color_t pixel);
    
    /// method indicating the end of a graphics stream.
    ///
    /// This is called to conclude a stream of pixel data that was sent.
    /// This may cause register configuration changes in the derived
    /// class in order to stop the hardware from accept the streaming
    /// data.
    ///
    /// @returns error code.
    ///
    virtual RetCode_t _EndGraphicsStream(void);

    /// Internal function to put a character using the built-in (internal) font engine
    ///
    /// @param is the character to put to the screen.
    /// @returns the character put.
    ///
    int _internal_putc(int c);
    
    /// Internal function to put a character using the external font engine
    ///
    /// @param is the character to put to the screen.
    /// @returns the character put.
    ///
    int _external_putc(int c);
    
    /// Select the peripheral to use it.
    ///
    /// @param chipsel when true will select the peripheral, and when false
    ///     will deselect the chip. This is the logical selection, and
    ///     the pin selection is the invert of this.
    /// @returns success/failure code. @see RetCode_t.
    ///
    RetCode_t select(bool chipsel);

    /// The most primitive - to write a data value to the SPI interface.
    ///
    /// @param data is the value to write.
    /// @returns a value read from the port, since SPI is often shift
    ///     in while shifting out.
    ///
    unsigned char spiwrite(unsigned char data);
    
    /// The most primitive - to read a data value to the SPI interface.
    ///
    /// This is really just a specialcase of the write command, where
    /// the value zero is written in order to read.
    ///
    /// @returns a value read from the port, since SPI is often shift
    ///     in while shifting out.
    ///
    unsigned char spiread();
    
    SPI spi;                        ///< spi port
    DigitalOut cs;                  ///< chip select pin, assumed active low
    DigitalOut res;                 ///< reset pin, assumed active low
    const unsigned char * font;     ///< reference to an external font somewhere in memory
    loc_t cursor_x, cursor_y;    ///< used for external fonts only
    
    #ifdef PERF_METRICS
    typedef enum
    {
        PRF_CLS,
        PRF_DRAWPIXEL,
        PRF_PIXELSTREAM,
        PRF_READPIXEL,
        PRF_READPIXELSTREAM,
        PRF_DRAWLINE,
        PRF_DRAWRECTANGLE,
        PRF_DRAWROUNDEDRECTANGLE,
        PRF_DRAWTRIANGLE,
        PRF_DRAWCIRCLE,
        PRF_DRAWELLIPSE,
        METRICCOUNT
    } method_e;
    unsigned long metrics[METRICCOUNT];
    void RegisterPerformance(method_e method);
    Timer performance;
    #endif
};

//}     // namespace

//using namespace SW_graphics;


#ifdef TESTENABLE
//      ______________  ______________  ______________  _______________
//     /_____   _____/ /  ___________/ /  ___________/ /_____   ______/
//          /  /      /  /            /  /                  /  /
//         /  /      /  /___         /  /__________        /  /
//        /  /      /  ____/        /__________   /       /  /
//       /  /      /  /                       /  /       /  /
//      /  /      /  /__________  ___________/  /       /  /
//     /__/      /_____________/ /_____________/       /__/

#include "WebColors.h"
#include "Arial12x12.h"
#include <algorithm>

extern "C" void mbed_reset();

/// This activates a small set of tests for the graphics library. 
///
/// Call this API and pass it the reference to the display class.
/// It will then run a series of tests. It accepts interaction via
/// stdin to switch from automatic test mode to manual, run a specific
/// test, or to exit the test mode.
///
/// @param lcd is a reference to the display class.
/// @param pc is a reference to a serial interface, typically the USB to PC.
///
void RunTestSet(RA8875 & lcd, Serial & pc);


// To enable the test code, uncomment this section, or copy the
// necessary pieces to your "main()".
//
// #include "mbed.h"
// #include "RA8875.h"
// RA8875 lcd(p5, p6, p7, p12, NC, "tft");    // MOSI, MISO, SCK, /ChipSelect, /reset, name
// Serial pc(USBTX, USBRX);
// extern "C" void mbed_reset();
// int main()
// {
//     pc.baud(460800);    // I like a snappy terminal, so crank it up!
//     pc.printf("\r\nRA8875 Test - Build " __DATE__ " " __TIME__ "\r\n");
// 
//     pc.printf("Turning on display\r\n");
//     lcd.Reset();
//     lcd.Power(true);  // display power is on, but the backlight is independent
//     lcd.Backlight(0.5);
//     RunTestSet(lcd, pc);
// }

#endif // TESTENABLE

#endif