From c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Sun, 29 Jun 2014 12:34:32 +0300 Subject: Add more board models --- boards/dk-tm4c129x/drivers/buttons.c | 261 ++++ boards/dk-tm4c129x/drivers/buttons.h | 105 ++ boards/dk-tm4c129x/drivers/frame.c | 1539 ++++++++++++++++++++ boards/dk-tm4c129x/drivers/frame.h | 55 + .../dk-tm4c129x/drivers/kentec320x240x16_ssd2119.c | 1056 ++++++++++++++ .../dk-tm4c129x/drivers/kentec320x240x16_ssd2119.h | 58 + boards/dk-tm4c129x/drivers/mx66l51235f.c | 534 +++++++ boards/dk-tm4c129x/drivers/mx66l51235f.h | 71 + boards/dk-tm4c129x/drivers/pinout.c | 282 ++++ boards/dk-tm4c129x/drivers/pinout.h | 59 + boards/dk-tm4c129x/drivers/sound.c | 688 +++++++++ boards/dk-tm4c129x/drivers/sound.h | 65 + boards/dk-tm4c129x/drivers/touch.c | 762 ++++++++++ boards/dk-tm4c129x/drivers/touch.h | 61 + boards/dk-tm4c129x/drivers/usb_sound.c | 769 ++++++++++ boards/dk-tm4c129x/drivers/usb_sound.h | 81 ++ 16 files changed, 6446 insertions(+) create mode 100644 boards/dk-tm4c129x/drivers/buttons.c create mode 100644 boards/dk-tm4c129x/drivers/buttons.h create mode 100644 boards/dk-tm4c129x/drivers/frame.c create mode 100644 boards/dk-tm4c129x/drivers/frame.h create mode 100644 boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.c create mode 100644 boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.h create mode 100644 boards/dk-tm4c129x/drivers/mx66l51235f.c create mode 100644 boards/dk-tm4c129x/drivers/mx66l51235f.h create mode 100644 boards/dk-tm4c129x/drivers/pinout.c create mode 100644 boards/dk-tm4c129x/drivers/pinout.h create mode 100644 boards/dk-tm4c129x/drivers/sound.c create mode 100644 boards/dk-tm4c129x/drivers/sound.h create mode 100644 boards/dk-tm4c129x/drivers/touch.c create mode 100644 boards/dk-tm4c129x/drivers/touch.h create mode 100644 boards/dk-tm4c129x/drivers/usb_sound.c create mode 100644 boards/dk-tm4c129x/drivers/usb_sound.h (limited to 'boards/dk-tm4c129x/drivers') diff --git a/boards/dk-tm4c129x/drivers/buttons.c b/boards/dk-tm4c129x/drivers/buttons.c new file mode 100644 index 0000000..d752c24 --- /dev/null +++ b/boards/dk-tm4c129x/drivers/buttons.c @@ -0,0 +1,261 @@ +//***************************************************************************** +// +// buttons.c - DK-TM4C129X development board buttons driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_types.h" +#include "inc/hw_memmap.h" +#include "inc/hw_gpio.h" +#include "driverlib/sysctl.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "driverlib/pin_map.h" +#include "driverlib/gpio.h" +#include "drivers/buttons.h" + +//***************************************************************************** +// +//! \addtogroup buttons_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// Holds the current, debounced state of each button. A 0 in a bit indicates +// that that button is currently pressed, otherwise it is released. +// We assume that we start with all the buttons released (though if one is +// pressed when the application starts, this will be detected). +// +//***************************************************************************** +static uint8_t g_ui8ButtonStates; + +static uint8_t g_uiButtonsEnabled; + +//***************************************************************************** +// +//! Polls the current state of the buttons and determines which have changed. +//! +//! \param pui8Delta points to a character that will be written to indicate +//! which button states changed since the last time this function was called. +//! This value is derived from the debounced state of the buttons. +//! \param pui8RawState points to a location where the raw button state will +//! be stored. +//! +//! This function should be called periodically by the application to poll the +//! pushbuttons. It determines both the current debounced state of the buttons +//! and also which buttons have changed state since the last time the function +//! was called. +//! +//! In order for button debouncing to work properly, this function should be +//! caled at a regular interval, even if the state of the buttons is not needed +//! that often. +//! +//! If button debouncing is not required, the the caller can pass a pointer +//! for the \e pui8RawState parameter in order to get the raw state of the +//! buttons. The value returned in \e pui8RawState will be a bit mask where +//! a 1 indicates the buttons is pressed. +//! +//! \return Returns the current debounced state of the buttons where a 1 in the +//! button ID's position indicates that the button is pressed and a 0 +//! indicates that it is released. +// +//***************************************************************************** +uint8_t +ButtonsPoll(uint8_t *pui8Delta, uint8_t *pui8RawState) +{ + uint32_t ui32Delta; + uint32_t ui32Data; + static uint8_t ui8SwitchClockA = 0; + static uint8_t ui8SwitchClockB = 0; + + // + // Read the raw state of the push buttons. Save the raw state + // (inverting the bit sense) if the caller supplied storage for the + // raw value. + // + ui32Data = 0; + if(g_uiButtonsEnabled & UP_BUTTON) + { + ui32Data = ROM_GPIOPinRead(GPIO_PORTN_BASE, UP_BUTTON); + } + if(g_uiButtonsEnabled & DOWN_BUTTON) + { + ui32Data |= ROM_GPIOPinRead(GPIO_PORTE_BASE, DOWN_BUTTON); + } + if(g_uiButtonsEnabled & SELECT_BUTTON) + { + ui32Data |= ROM_GPIOPinRead(GPIO_PORTP_BASE, SELECT_BUTTON); + } + + if(pui8RawState) + { + *pui8RawState = (uint8_t)~ui32Data; + } + + // + // Determine the switches that are at a different state than the debounced + // state. + // + ui32Delta = ui32Data ^ g_ui8ButtonStates; + + // + // Increment the clocks by one. + // + ui8SwitchClockA ^= ui8SwitchClockB; + ui8SwitchClockB = ~ui8SwitchClockB; + + // + // Reset the clocks corresponding to switches that have not changed state. + // + ui8SwitchClockA &= ui32Delta; + ui8SwitchClockB &= ui32Delta; + + // + // Get the new debounced switch state. + // + g_ui8ButtonStates &= ui8SwitchClockA | ui8SwitchClockB; + g_ui8ButtonStates |= (~(ui8SwitchClockA | ui8SwitchClockB)) & ui32Data; + + // + // Determine the switches that just changed debounced state. + // + ui32Delta ^= (ui8SwitchClockA | ui8SwitchClockB); + + // + // Store the bit mask for the buttons that have changed for return to + // caller. + // + if(pui8Delta) + { + *pui8Delta = (uint8_t)ui32Delta; + } + + // + // Return the debounced buttons states to the caller. Invert the bit + // sense so that a '1' indicates the button is pressed, which is a + // sensible way to interpret the return value. + // + return(~g_ui8ButtonStates); +} + +//***************************************************************************** +// +//! Initializes the GPIO pins used by the board pushbuttons. +//! +//! \param ui8Buttons is the logical OR of the buttons to initialize. +//! +//! This function must be called during application initialization to +//! configure the GPIO pins to which the pushbuttons are attached. It enables +//! the port used by the buttons and configures each button GPIO as an input +//! with a weak pull-up. The \e ui8Buttons value must be a logical OR +//! combination of the following three buttons on the board: \b UP_BUTTON, +//! \b DOWN_BUTTON, or \b SELECT_BUTTON. +//! +//! \return None. +// +//***************************************************************************** +void +ButtonsInit(uint8_t ui8Buttons) +{ + // + // Initialize the button state. + // + g_ui8ButtonStates = 0; + + // + // Save the buttons in use. + // + g_uiButtonsEnabled = ui8Buttons; + + if(ui8Buttons & UP_BUTTON) + { + // + // Enable the GPIO port to which the up button is connected. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); + + // + // Set the up button's GPIO pins as an input with a pull-up. + // + ROM_GPIODirModeSet(GPIO_PORTN_BASE, UP_BUTTON, GPIO_DIR_MODE_IN); + MAP_GPIOPadConfigSet(GPIO_PORTN_BASE, UP_BUTTON, + GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU); + + // + // Initialize the debounced button state with the current state read + // from the GPIO bank. + // + g_ui8ButtonStates = ROM_GPIOPinRead(GPIO_PORTN_BASE, UP_BUTTON); + } + + if(ui8Buttons & DOWN_BUTTON) + { + // + // Enable the GPIO port to which the down button is connected. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); + + // + // Set the down button's GPIO pins as an input with a pull-up. + // + ROM_GPIODirModeSet(GPIO_PORTE_BASE, DOWN_BUTTON, GPIO_DIR_MODE_IN); + MAP_GPIOPadConfigSet(GPIO_PORTE_BASE, DOWN_BUTTON, + GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU); + + // + // Initialize the debounced button state with the current state read + // from the GPIO bank. + // + g_ui8ButtonStates |= ROM_GPIOPinRead(GPIO_PORTE_BASE, DOWN_BUTTON); + } + + if(ui8Buttons & SELECT_BUTTON) + { + // + // Enable the GPIO port to which the select button is connected. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); + + // + // Set the select button's GPIO pins as an input with a pull-up. + // + ROM_GPIODirModeSet(GPIO_PORTP_BASE, SELECT_BUTTON, GPIO_DIR_MODE_IN); + MAP_GPIOPadConfigSet(GPIO_PORTP_BASE, SELECT_BUTTON, + GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU); + + // + // Initialize the debounced button state with the current state read + // from the GPIO bank. + // + g_ui8ButtonStates |= ROM_GPIOPinRead(GPIO_PORTP_BASE, SELECT_BUTTON); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/buttons.h b/boards/dk-tm4c129x/drivers/buttons.h new file mode 100644 index 0000000..23ccd8a --- /dev/null +++ b/boards/dk-tm4c129x/drivers/buttons.h @@ -0,0 +1,105 @@ +//***************************************************************************** +// +// buttons.h - Prototypes for the DK-TM4C129X development board buttons driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __BUTTONS_H__ +#define __BUTTONS_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Defines for the hardware resources used by the pushbuttons. +// +// The switches are on the following ports/pins: +// +// PN3 - Up Button (UP_BUTTON) +// PE5 - Down Button (DOWN_BUTTON) +// PP1 - Select Button (SELECT_BUTTON) +// +// The switches tie the GPIO to ground, so the GPIOs need to be configured +// with pull-ups, and a value of 0 means the switch is pressed. +// +//***************************************************************************** +#define NUM_BUTTONS 3 +#define UP_BUTTON GPIO_PIN_3 +#define DOWN_BUTTON GPIO_PIN_5 +#define SELECT_BUTTON GPIO_PIN_1 + +#define ALL_BUTTONS (UP_BUTTON | DOWN_BUTTON | SELECT_BUTTON) + +//***************************************************************************** +// +// Useful macros for detecting button events. +// +//***************************************************************************** +#define BUTTON_PRESSED(button, buttons, changed) \ + (((button) & (changed)) && ((button) & (buttons))) + +#define BUTTON_RELEASED(button, buttons, changed) \ + (((button) & (changed)) && !((button) & (buttons))) + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Functions exported from buttons.c +// +//***************************************************************************** +extern void ButtonsInit(uint8_t ui8Buttons); +extern uint8_t ButtonsPoll(uint8_t *pui8Delta, uint8_t *pui8Raw); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +//***************************************************************************** +// +// Prototypes for the globals exported by this driver. +// +//***************************************************************************** + +#endif // __BUTTONS_H__ diff --git a/boards/dk-tm4c129x/drivers/frame.c b/boards/dk-tm4c129x/drivers/frame.c new file mode 100644 index 0000000..625d10d --- /dev/null +++ b/boards/dk-tm4c129x/drivers/frame.c @@ -0,0 +1,1539 @@ +//***************************************************************************** +// +// frame.c - Draws a standard application frame on the LCD. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "grlib/grlib.h" +#include "drivers/frame.h" + +//***************************************************************************** +// +//! \addtogroup frame_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The top left corner of the border. +// +//***************************************************************************** +static const uint8_t g_pui8TopLeft[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 10, 0, + 26, 0, + + 37, + 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, + 0x0a, 0x00, 0x00, + 0x0b, 0x00, 0x00, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x40, 0x00, 0x00, + 0x44, 0x00, 0x00, + 0x46, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x4a, 0x00, 0x00, + 0x4c, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x52, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5c, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x15, 0x24, 0x1b, 0x1d, 0x23, 0x1c, 0x1f, 0x00, 0x13, + 0x1a, 0x1b, 0x10, 0x0a, 0x0b, 0x0e, 0x0e, 0x17, 0x00, 0x1c, 0x17, 0x0e, + 0x17, 0x14, 0x10, 0x0d, 0x18, 0x0a, 0x0b, 0x20, 0x0d, 0x0b, 0x14, 0x10, + 0x10, 0x0c, 0x16, 0x0b, 0x1c, 0x0f, 0x0e, 0x12, 0x0a, 0x10, 0x13, 0x16, + 0x0e, 0x18, 0x1e, 0x18, 0x12, 0x0a, 0x0f, 0x13, 0x17, 0x16, 0x12, 0x0f, + 0x24, 0x14, 0x16, 0x12, 0x12, 0x12, 0x18, 0x10, 0x0e, 0x0f, 0x25, 0x14, + 0x18, 0x10, 0x0d, 0x0e, 0x0a, 0x16, 0x0c, 0x11, 0x1c, 0x0d, 0x0d, 0x0c, + 0x0a, 0x16, 0x11, 0x0f, 0x17, 0x0c, 0x24, 0x0b, 0x0e, 0x0c, 0x0b, 0x17, + 0x17, 0x15, 0x10, 0x0b, 0x21, 0x15, 0x0f, 0x10, 0x10, 0x13, 0x09, 0x11, + 0x0f, 0x16, 0x1e, 0x09, 0x0a, 0x0c, 0x16, 0x16, 0x17, 0x14, 0x18, 0x16, + 0x1d, 0x13, 0x11, 0x0e, 0x11, 0x15, 0x10, 0x13, 0x12, 0x10, 0x20, 0x15, + 0x11, 0x10, 0x16, 0x18, 0x10, 0x15, 0x12, 0x10, 0x24, 0x0e, 0x0e, 0x16, + 0x10, 0x0f, 0x0a, 0x15, 0x18, 0x0c, 0x22, 0x0d, 0x0a, 0x0c, 0x0d, 0x0c, + 0x0d, 0x0d, 0x11, 0x11, 0x24, 0x11, 0x16, 0x0c, 0x0b, 0x0f, 0x0d, 0x18, + 0x0e, 0x14, 0x1a, 0x18, 0x17, 0x18, 0x0a, 0x0b, 0x15, 0x0a, 0x09, 0x15, + 0x19, 0x18, 0x14, 0x0d, 0x0c, 0x0e, 0x10, 0x0b, 0x18, 0x0d, 0x22, 0x10, + 0x0c, 0x0b, 0x14, 0x0c, 0x17, 0x14, 0x0e, 0x0d, 0x23, 0x0b, 0x0d, 0x0d, + 0x16, 0x0c, 0x17, 0x0a, 0x0c, 0x11, 0x1b, 0x14, 0x17, 0x0b, 0x0d, 0x10, + 0x0a, 0x0c, 0x13, 0x07, 0x1a, 0x16, 0x17, 0x0c, 0x09, 0x13, 0x16, 0x06, + 0x08, 0x03, 0x1f, 0x18, 0x15, 0x0b, 0x12, 0x11, 0x08, 0x02, 0x00, 0x00, + 0x1c, 0x10, 0x11, 0x0a, 0x0d, 0x15, 0x05, 0x00, 0x00, 0x00, 0x1e, 0x0d, + 0x10, 0x0e, 0x0e, 0x04, 0x01, 0x00, 0x00, 0x00, +}; + +//***************************************************************************** +// +// The top side of the border. +// +//***************************************************************************** +static const uint8_t g_pui8Top[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 44, 1, + 22, 0, + + 39, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x15, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x40, 0x00, 0x00, + 0x42, 0x00, 0x00, + 0x44, 0x00, 0x00, + 0x46, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x4a, 0x00, 0x00, + 0x4c, 0x00, 0x00, + 0x4e, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x52, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5a, 0x00, 0x00, + 0x5c, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x1f, 0x22, 0x1d, 0x20, 0x27, 0x26, 0x22, 0x23, 0x1a, 0x21, 0x18, 0x1b, + 0x1a, 0x24, 0x1a, 0x1e, 0x1a, 0x19, 0x27, 0x1b, 0x20, 0x25, 0x21, 0x1c, + 0x22, 0x20, 0x1f, 0x27, 0x1c, 0x24, 0x20, 0x24, 0x1e, 0x26, 0x1c, 0x1d, + 0x24, 0x26, 0x19, 0x27, 0x20, 0x19, 0x1b, 0x22, 0x26, 0x1d, 0x19, 0x18, + 0x1f, 0x19, 0x1b, 0x27, 0x26, 0x25, 0x1c, 0x20, 0x1e, 0x24, 0x20, 0x22, + 0x20, 0x18, 0x1f, 0x26, 0x26, 0x23, 0x1c, 0x23, 0x22, 0x1d, 0x23, 0x1a, + 0x1f, 0x26, 0x25, 0x1d, 0x1b, 0x26, 0x1d, 0x22, 0x27, 0x21, 0x22, 0x25, + 0x1f, 0x26, 0x1e, 0x25, 0x22, 0x26, 0x1f, 0x1b, 0x27, 0x26, 0x1a, 0x26, + 0x22, 0x1e, 0x21, 0x1c, 0x24, 0x1c, 0x1f, 0x1b, 0x1b, 0x1c, 0x20, 0x1e, + 0x1a, 0x26, 0x19, 0x1a, 0x1f, 0x24, 0x27, 0x26, 0x22, 0x1e, 0x23, 0x1d, + 0x1c, 0x1b, 0x21, 0x1b, 0x1a, 0x23, 0x1a, 0x24, 0x1a, 0x23, 0x19, 0x27, + 0x18, 0x20, 0x1a, 0x1b, 0x24, 0x23, 0x22, 0x27, 0x22, 0x24, 0x19, 0x1a, + 0x20, 0x19, 0x19, 0x1b, 0x1f, 0x25, 0x21, 0x24, 0x18, 0x1a, 0x27, 0x1b, + 0x26, 0x1a, 0x27, 0x18, 0x25, 0x19, 0x18, 0x26, 0x21, 0x1a, 0x1a, 0x1e, + 0x26, 0x25, 0x1d, 0x20, 0x21, 0x1f, 0x22, 0x19, 0x20, 0x24, 0x1c, 0x27, + 0x21, 0x26, 0x23, 0x22, 0x18, 0x23, 0x25, 0x26, 0x25, 0x25, 0x27, 0x23, + 0x26, 0x27, 0x22, 0x1f, 0x1a, 0x25, 0x26, 0x19, 0x22, 0x1b, 0x22, 0x1b, + 0x23, 0x1d, 0x1d, 0x1b, 0x19, 0x22, 0x1b, 0x22, 0x20, 0x27, 0x1c, 0x20, + 0x23, 0x19, 0x1f, 0x21, 0x27, 0x1f, 0x1d, 0x25, 0x1e, 0x18, 0x1d, 0x21, + 0x25, 0x1b, 0x22, 0x1f, 0x1f, 0x1c, 0x23, 0x1a, 0x21, 0x18, 0x1e, 0x23, + 0x22, 0x22, 0x1d, 0x1a, 0x21, 0x22, 0x23, 0x1d, 0x23, 0x1b, 0x26, 0x22, + 0x22, 0x1c, 0x20, 0x19, 0x1c, 0x26, 0x22, 0x19, 0x19, 0x1d, 0x21, 0x21, + 0x22, 0x1c, 0x24, 0x1c, 0x1d, 0x1b, 0x27, 0x18, 0x25, 0x1d, 0x1b, 0x1e, + 0x27, 0x26, 0x24, 0x23, 0x19, 0x22, 0x1e, 0x24, 0x27, 0x26, 0x25, 0x1b, + 0x24, 0x20, 0x1c, 0x26, 0x26, 0x25, 0x1f, 0x21, 0x1a, 0x1c, 0x25, 0x1f, + 0x16, 0x11, 0x15, 0x15, 0x0f, 0x0d, 0x0e, 0x12, 0x11, 0x0c, 0x0a, 0x09, + 0x09, 0x12, 0x0d, 0x0c, 0x0d, 0x09, 0x0e, 0x16, 0x11, 0x0c, 0x12, 0x14, + 0x0f, 0x0a, 0x16, 0x12, 0x10, 0x0b, 0x10, 0x0e, 0x15, 0x0e, 0x0b, 0x0d, + 0x13, 0x12, 0x17, 0x0d, 0x16, 0x0a, 0x0e, 0x08, 0x14, 0x14, 0x0c, 0x09, + 0x15, 0x13, 0x08, 0x0f, 0x17, 0x13, 0x0b, 0x0f, 0x15, 0x09, 0x09, 0x0e, + 0x0c, 0x12, 0x14, 0x0a, 0x08, 0x08, 0x0f, 0x14, 0x13, 0x0f, 0x09, 0x11, + 0x11, 0x10, 0x11, 0x0d, 0x0c, 0x16, 0x0f, 0x0a, 0x11, 0x10, 0x11, 0x11, + 0x0b, 0x15, 0x09, 0x09, 0x16, 0x0a, 0x0f, 0x0b, 0x15, 0x0c, 0x0d, 0x16, + 0x0d, 0x15, 0x12, 0x08, 0x0c, 0x14, 0x12, 0x15, 0x0c, 0x0b, 0x0b, 0x11, + 0x09, 0x12, 0x14, 0x13, 0x0b, 0x0e, 0x0d, 0x0e, 0x0b, 0x0e, 0x10, 0x0a, + 0x10, 0x08, 0x0e, 0x0e, 0x0c, 0x13, 0x0c, 0x12, 0x10, 0x16, 0x12, 0x14, + 0x13, 0x0c, 0x12, 0x08, 0x10, 0x15, 0x11, 0x12, 0x10, 0x0e, 0x0d, 0x13, + 0x14, 0x12, 0x0a, 0x08, 0x09, 0x12, 0x0b, 0x11, 0x13, 0x11, 0x08, 0x08, + 0x0c, 0x0c, 0x12, 0x15, 0x0a, 0x0d, 0x12, 0x16, 0x12, 0x0d, 0x16, 0x0a, + 0x0a, 0x10, 0x15, 0x12, 0x16, 0x0b, 0x0e, 0x13, 0x15, 0x10, 0x13, 0x16, + 0x0b, 0x16, 0x10, 0x16, 0x0f, 0x10, 0x17, 0x14, 0x15, 0x11, 0x12, 0x17, + 0x16, 0x0d, 0x15, 0x11, 0x12, 0x14, 0x14, 0x14, 0x0c, 0x11, 0x0f, 0x0a, + 0x14, 0x15, 0x15, 0x12, 0x0e, 0x11, 0x11, 0x12, 0x10, 0x0a, 0x11, 0x08, + 0x13, 0x10, 0x15, 0x10, 0x09, 0x0f, 0x10, 0x08, 0x15, 0x0e, 0x12, 0x0f, + 0x0a, 0x0e, 0x0b, 0x0e, 0x08, 0x13, 0x11, 0x15, 0x11, 0x0f, 0x0f, 0x17, + 0x08, 0x09, 0x12, 0x11, 0x0b, 0x0b, 0x12, 0x16, 0x13, 0x0f, 0x0f, 0x15, + 0x17, 0x17, 0x16, 0x14, 0x0d, 0x10, 0x0b, 0x0f, 0x17, 0x0f, 0x16, 0x17, + 0x0a, 0x0f, 0x14, 0x14, 0x16, 0x0c, 0x14, 0x17, 0x0d, 0x0e, 0x10, 0x10, + 0x11, 0x0b, 0x0f, 0x0d, 0x12, 0x16, 0x0b, 0x11, 0x15, 0x09, 0x0d, 0x0b, + 0x12, 0x11, 0x12, 0x11, 0x08, 0x10, 0x11, 0x0b, 0x08, 0x0d, 0x08, 0x16, + 0x15, 0x11, 0x13, 0x16, 0x0a, 0x0c, 0x0a, 0x0b, 0x12, 0x0a, 0x0a, 0x0b, + 0x17, 0x08, 0x0a, 0x09, 0x0f, 0x12, 0x16, 0x09, 0x11, 0x09, 0x0e, 0x0f, + 0x0e, 0x0c, 0x0b, 0x16, 0x11, 0x0b, 0x08, 0x0e, 0x15, 0x14, 0x0d, 0x17, + 0x08, 0x10, 0x0b, 0x12, 0x13, 0x0d, 0x16, 0x12, 0x0d, 0x08, 0x14, 0x14, + 0x13, 0x12, 0x16, 0x0d, 0x14, 0x0c, 0x14, 0x0b, 0x11, 0x08, 0x09, 0x0a, + 0x0b, 0x0a, 0x11, 0x08, 0x16, 0x17, 0x08, 0x16, 0x0f, 0x0c, 0x11, 0x0a, + 0x11, 0x0f, 0x15, 0x16, 0x10, 0x11, 0x13, 0x0b, 0x0c, 0x12, 0x10, 0x08, + 0x16, 0x0d, 0x0b, 0x10, 0x0e, 0x0c, 0x12, 0x12, 0x0f, 0x0c, 0x13, 0x0d, + 0x0b, 0x14, 0x0c, 0x12, 0x08, 0x15, 0x15, 0x11, 0x0d, 0x12, 0x10, 0x15, + 0x0c, 0x0c, 0x09, 0x10, 0x16, 0x11, 0x10, 0x15, 0x17, 0x13, 0x0d, 0x0d, + 0x08, 0x08, 0x08, 0x0f, 0x0c, 0x13, 0x15, 0x10, 0x0f, 0x09, 0x0b, 0x0f, + 0x16, 0x08, 0x09, 0x0b, 0x13, 0x11, 0x09, 0x17, 0x15, 0x0a, 0x0f, 0x14, + 0x14, 0x08, 0x11, 0x13, 0x13, 0x16, 0x09, 0x14, 0x17, 0x09, 0x0c, 0x0b, + 0x14, 0x09, 0x13, 0x0c, 0x0a, 0x17, 0x14, 0x09, 0x17, 0x15, 0x0d, 0x13, + 0x0f, 0x0e, 0x12, 0x0d, 0x11, 0x0a, 0x09, 0x0e, 0x0a, 0x12, 0x09, 0x16, + 0x11, 0x0b, 0x12, 0x10, 0x0c, 0x17, 0x14, 0x09, 0x08, 0x10, 0x0e, 0x0b, + 0x0f, 0x0a, 0x0c, 0x0e, 0x08, 0x12, 0x0a, 0x0f, 0x09, 0x14, 0x14, 0x12, + 0x16, 0x15, 0x09, 0x08, 0x10, 0x0a, 0x16, 0x09, 0x0e, 0x11, 0x12, 0x13, + 0x10, 0x0e, 0x15, 0x11, 0x16, 0x0b, 0x14, 0x0d, 0x0e, 0x09, 0x14, 0x0e, + 0x13, 0x16, 0x15, 0x15, 0x13, 0x12, 0x10, 0x11, 0x10, 0x11, 0x12, 0x08, + 0x14, 0x11, 0x0a, 0x0a, 0x0b, 0x14, 0x15, 0x13, 0x0a, 0x12, 0x0d, 0x09, + 0x16, 0x09, 0x0f, 0x0c, 0x0b, 0x0c, 0x12, 0x17, 0x0b, 0x10, 0x14, 0x16, + 0x0a, 0x0c, 0x10, 0x12, 0x15, 0x0b, 0x12, 0x12, 0x15, 0x15, 0x14, 0x08, + 0x11, 0x11, 0x14, 0x14, 0x0c, 0x09, 0x16, 0x0a, 0x0a, 0x0d, 0x0f, 0x0e, + 0x12, 0x09, 0x0d, 0x15, 0x11, 0x09, 0x14, 0x13, 0x0e, 0x0d, 0x0e, 0x0c, + 0x0c, 0x0a, 0x08, 0x16, 0x0c, 0x14, 0x12, 0x13, 0x0a, 0x08, 0x17, 0x14, + 0x09, 0x15, 0x0b, 0x17, 0x10, 0x12, 0x0f, 0x15, 0x16, 0x13, 0x0e, 0x0b, + 0x15, 0x0a, 0x12, 0x0d, 0x0d, 0x10, 0x0f, 0x12, 0x13, 0x0f, 0x10, 0x08, + 0x0c, 0x0b, 0x13, 0x0f, 0x0b, 0x12, 0x0b, 0x0d, 0x10, 0x0e, 0x0d, 0x08, + 0x09, 0x14, 0x16, 0x17, 0x10, 0x0c, 0x0a, 0x0d, 0x0f, 0x15, 0x12, 0x14, + 0x0e, 0x0a, 0x0e, 0x09, 0x11, 0x17, 0x09, 0x15, 0x0a, 0x14, 0x0d, 0x0e, + 0x0f, 0x10, 0x13, 0x17, 0x17, 0x09, 0x08, 0x08, 0x16, 0x16, 0x08, 0x0e, + 0x0a, 0x0b, 0x14, 0x11, 0x09, 0x0f, 0x0e, 0x0f, 0x11, 0x15, 0x11, 0x0b, + 0x14, 0x12, 0x09, 0x17, 0x0f, 0x0e, 0x0d, 0x16, 0x16, 0x09, 0x16, 0x16, + 0x0b, 0x16, 0x16, 0x09, 0x15, 0x17, 0x10, 0x08, 0x0b, 0x0c, 0x12, 0x0c, + 0x13, 0x08, 0x13, 0x0d, 0x15, 0x0c, 0x10, 0x12, 0x17, 0x11, 0x12, 0x0e, + 0x08, 0x17, 0x0d, 0x16, 0x09, 0x0c, 0x14, 0x0c, 0x0a, 0x13, 0x0e, 0x08, + 0x13, 0x16, 0x08, 0x16, 0x0a, 0x12, 0x0a, 0x16, 0x12, 0x15, 0x0c, 0x10, + 0x0a, 0x15, 0x0b, 0x09, 0x0f, 0x15, 0x10, 0x0f, 0x15, 0x16, 0x0e, 0x17, + 0x0a, 0x0b, 0x0b, 0x0d, 0x16, 0x12, 0x0d, 0x11, 0x10, 0x0e, 0x10, 0x13, + 0x08, 0x12, 0x11, 0x13, 0x10, 0x16, 0x0b, 0x12, 0x13, 0x0f, 0x14, 0x0a, + 0x0d, 0x0d, 0x12, 0x0a, 0x0b, 0x08, 0x0a, 0x0e, 0x0b, 0x0e, 0x14, 0x0a, + 0x08, 0x0a, 0x13, 0x10, 0x10, 0x0b, 0x0b, 0x10, 0x16, 0x15, 0x0b, 0x0e, + 0x13, 0x0f, 0x09, 0x0f, 0x17, 0x16, 0x12, 0x0c, 0x0b, 0x0c, 0x0f, 0x0f, + 0x0c, 0x11, 0x16, 0x10, 0x17, 0x12, 0x12, 0x17, 0x14, 0x0e, 0x10, 0x0d, + 0x12, 0x13, 0x15, 0x10, 0x11, 0x09, 0x17, 0x0d, 0x11, 0x08, 0x14, 0x10, + 0x16, 0x0e, 0x14, 0x0a, 0x13, 0x0b, 0x11, 0x08, 0x15, 0x0f, 0x10, 0x14, + 0x0a, 0x0a, 0x14, 0x16, 0x10, 0x0c, 0x0b, 0x0b, 0x08, 0x09, 0x13, 0x11, + 0x0b, 0x12, 0x17, 0x14, 0x13, 0x13, 0x0c, 0x12, 0x0a, 0x09, 0x14, 0x15, + 0x0d, 0x0e, 0x15, 0x0a, 0x15, 0x0e, 0x16, 0x17, 0x10, 0x13, 0x16, 0x09, + 0x0b, 0x0b, 0x0a, 0x09, 0x11, 0x08, 0x09, 0x0a, 0x14, 0x17, 0x0c, 0x14, + 0x0a, 0x11, 0x14, 0x0e, 0x11, 0x0f, 0x16, 0x0c, 0x08, 0x0a, 0x13, 0x0d, + 0x13, 0x15, 0x15, 0x0e, 0x13, 0x0a, 0x0e, 0x17, 0x0d, 0x10, 0x08, 0x16, + 0x11, 0x09, 0x09, 0x0d, 0x09, 0x0d, 0x09, 0x0c, 0x16, 0x16, 0x12, 0x0f, + 0x0d, 0x10, 0x14, 0x0e, 0x13, 0x10, 0x13, 0x0f, 0x0d, 0x10, 0x15, 0x09, + 0x13, 0x0b, 0x08, 0x08, 0x13, 0x08, 0x17, 0x0c, 0x0a, 0x08, 0x12, 0x0c, + 0x0d, 0x13, 0x10, 0x0b, 0x12, 0x0b, 0x13, 0x08, 0x14, 0x10, 0x0e, 0x0f, + 0x09, 0x0a, 0x16, 0x0f, 0x13, 0x14, 0x10, 0x0e, 0x17, 0x10, 0x0f, 0x13, + 0x11, 0x0e, 0x08, 0x13, 0x0f, 0x12, 0x08, 0x14, 0x0e, 0x11, 0x08, 0x08, + 0x14, 0x14, 0x08, 0x10, 0x0d, 0x0e, 0x08, 0x0e, 0x11, 0x17, 0x15, 0x0c, + 0x13, 0x0e, 0x12, 0x13, 0x16, 0x09, 0x0e, 0x10, 0x0f, 0x0f, 0x0c, 0x17, + 0x09, 0x0c, 0x13, 0x0f, 0x15, 0x14, 0x10, 0x12, 0x11, 0x10, 0x0a, 0x16, + 0x17, 0x0b, 0x0d, 0x10, 0x0a, 0x0b, 0x14, 0x15, 0x11, 0x0f, 0x11, 0x10, + 0x10, 0x17, 0x08, 0x08, 0x0e, 0x0d, 0x17, 0x10, 0x11, 0x13, 0x17, 0x0f, + 0x10, 0x10, 0x09, 0x09, 0x08, 0x0c, 0x08, 0x08, 0x0f, 0x0e, 0x10, 0x11, + 0x11, 0x0d, 0x0f, 0x0b, 0x14, 0x08, 0x14, 0x0d, 0x08, 0x15, 0x0d, 0x0f, + 0x0a, 0x0d, 0x17, 0x14, 0x08, 0x17, 0x0b, 0x11, 0x0f, 0x0d, 0x13, 0x10, + 0x11, 0x14, 0x10, 0x09, 0x0a, 0x09, 0x13, 0x13, 0x0f, 0x0b, 0x17, 0x0c, + 0x0c, 0x13, 0x11, 0x0d, 0x10, 0x17, 0x14, 0x13, 0x0c, 0x14, 0x0f, 0x0d, + 0x14, 0x12, 0x16, 0x0c, 0x08, 0x11, 0x15, 0x12, 0x0d, 0x0e, 0x13, 0x10, + 0x10, 0x0f, 0x0c, 0x17, 0x12, 0x0b, 0x0b, 0x17, 0x17, 0x15, 0x0c, 0x0f, + 0x14, 0x08, 0x0a, 0x08, 0x15, 0x12, 0x0e, 0x12, 0x0c, 0x0c, 0x16, 0x0d, + 0x16, 0x13, 0x17, 0x0c, 0x09, 0x13, 0x14, 0x11, 0x0a, 0x08, 0x11, 0x15, + 0x0b, 0x15, 0x14, 0x0a, 0x12, 0x08, 0x12, 0x0e, 0x09, 0x15, 0x0f, 0x17, + 0x0f, 0x15, 0x11, 0x14, 0x09, 0x0f, 0x09, 0x08, 0x0b, 0x08, 0x0c, 0x0d, + 0x12, 0x0b, 0x0a, 0x14, 0x12, 0x0b, 0x15, 0x16, 0x0c, 0x09, 0x0b, 0x08, + 0x09, 0x0a, 0x16, 0x0a, 0x12, 0x12, 0x0e, 0x17, 0x0a, 0x15, 0x17, 0x14, + 0x17, 0x0d, 0x0f, 0x16, 0x0a, 0x08, 0x0c, 0x15, 0x0c, 0x0e, 0x12, 0x16, + 0x12, 0x0f, 0x15, 0x16, 0x11, 0x08, 0x16, 0x13, 0x0b, 0x15, 0x15, 0x15, + 0x0f, 0x0c, 0x15, 0x12, 0x0a, 0x14, 0x0e, 0x09, 0x09, 0x15, 0x17, 0x0c, + 0x16, 0x0c, 0x0a, 0x0a, 0x12, 0x15, 0x09, 0x0d, 0x0d, 0x16, 0x0b, 0x16, + 0x17, 0x0a, 0x11, 0x0a, 0x17, 0x0f, 0x08, 0x0f, 0x13, 0x15, 0x09, 0x16, + 0x12, 0x10, 0x17, 0x13, 0x0d, 0x17, 0x08, 0x0c, 0x0b, 0x0b, 0x0e, 0x16, + 0x08, 0x10, 0x0b, 0x0d, 0x0f, 0x0f, 0x0b, 0x0e, 0x11, 0x15, 0x11, 0x11, + 0x0c, 0x11, 0x08, 0x08, 0x0f, 0x0a, 0x16, 0x09, 0x12, 0x16, 0x15, 0x17, + 0x16, 0x16, 0x0c, 0x0a, 0x09, 0x13, 0x08, 0x09, 0x0b, 0x0c, 0x0f, 0x12, + 0x13, 0x13, 0x09, 0x0d, 0x10, 0x13, 0x16, 0x15, 0x0d, 0x17, 0x16, 0x14, + 0x09, 0x15, 0x16, 0x13, 0x13, 0x13, 0x13, 0x12, 0x11, 0x17, 0x14, 0x13, + 0x12, 0x15, 0x15, 0x16, 0x09, 0x0c, 0x11, 0x15, 0x08, 0x12, 0x0a, 0x10, + 0x0e, 0x09, 0x0e, 0x13, 0x09, 0x0c, 0x10, 0x0a, 0x09, 0x0e, 0x16, 0x15, + 0x0a, 0x12, 0x0f, 0x14, 0x12, 0x0c, 0x0f, 0x0c, 0x0a, 0x0c, 0x0b, 0x0c, + 0x11, 0x14, 0x09, 0x11, 0x0f, 0x0c, 0x0a, 0x15, 0x0e, 0x10, 0x11, 0x0f, + 0x15, 0x0a, 0x12, 0x16, 0x10, 0x10, 0x14, 0x13, 0x0b, 0x0c, 0x0f, 0x15, + 0x10, 0x16, 0x09, 0x13, 0x0b, 0x0d, 0x17, 0x14, 0x09, 0x08, 0x0d, 0x10, + 0x0d, 0x0f, 0x0e, 0x13, 0x08, 0x08, 0x0b, 0x15, 0x0a, 0x15, 0x14, 0x13, + 0x0e, 0x10, 0x0e, 0x11, 0x14, 0x15, 0x0e, 0x0d, 0x13, 0x10, 0x08, 0x17, + 0x15, 0x17, 0x13, 0x17, 0x08, 0x09, 0x0f, 0x0d, 0x10, 0x16, 0x09, 0x11, + 0x16, 0x0c, 0x0e, 0x09, 0x09, 0x0a, 0x14, 0x10, 0x12, 0x0a, 0x09, 0x0f, + 0x17, 0x10, 0x14, 0x13, 0x08, 0x14, 0x12, 0x16, 0x14, 0x0e, 0x15, 0x14, + 0x0f, 0x0d, 0x09, 0x17, 0x0b, 0x0a, 0x11, 0x0a, 0x0e, 0x17, 0x0b, 0x10, + 0x14, 0x0f, 0x0e, 0x08, 0x11, 0x17, 0x0a, 0x08, 0x16, 0x0e, 0x11, 0x09, + 0x0f, 0x12, 0x16, 0x11, 0x15, 0x0a, 0x14, 0x10, 0x0b, 0x12, 0x0b, 0x08, + 0x0b, 0x15, 0x12, 0x0b, 0x0c, 0x08, 0x11, 0x09, 0x0f, 0x17, 0x09, 0x09, + 0x17, 0x0c, 0x0a, 0x16, 0x12, 0x13, 0x17, 0x0a, 0x0e, 0x15, 0x13, 0x0b, + 0x17, 0x10, 0x13, 0x0b, 0x0b, 0x17, 0x0b, 0x0f, 0x15, 0x16, 0x12, 0x09, + 0x16, 0x0b, 0x0a, 0x0e, 0x0b, 0x0b, 0x10, 0x0b, 0x10, 0x12, 0x09, 0x0a, + 0x0e, 0x08, 0x0c, 0x15, 0x16, 0x08, 0x08, 0x16, 0x11, 0x14, 0x09, 0x14, + 0x13, 0x0c, 0x0b, 0x11, 0x0b, 0x16, 0x12, 0x09, 0x09, 0x15, 0x10, 0x0d, + 0x09, 0x08, 0x10, 0x11, 0x13, 0x12, 0x14, 0x0a, 0x12, 0x09, 0x17, 0x11, + 0x0a, 0x08, 0x0f, 0x13, 0x15, 0x10, 0x10, 0x11, 0x15, 0x13, 0x0a, 0x08, + 0x12, 0x14, 0x0a, 0x14, 0x12, 0x12, 0x09, 0x13, 0x13, 0x12, 0x0d, 0x0f, + 0x0c, 0x09, 0x11, 0x17, 0x0b, 0x11, 0x10, 0x0d, 0x11, 0x08, 0x08, 0x0e, + 0x10, 0x10, 0x17, 0x0d, 0x0c, 0x09, 0x0d, 0x16, 0x16, 0x0f, 0x12, 0x11, + 0x0a, 0x14, 0x0d, 0x16, 0x0f, 0x12, 0x0d, 0x13, 0x14, 0x16, 0x13, 0x17, + 0x0f, 0x0c, 0x0c, 0x09, 0x0c, 0x0d, 0x10, 0x14, 0x16, 0x10, 0x0a, 0x0b, + 0x12, 0x10, 0x0a, 0x10, 0x08, 0x14, 0x0a, 0x0a, 0x11, 0x0f, 0x08, 0x08, + 0x09, 0x0e, 0x14, 0x15, 0x0c, 0x0f, 0x15, 0x14, 0x14, 0x0a, 0x16, 0x09, + 0x0f, 0x0e, 0x16, 0x0e, 0x17, 0x08, 0x11, 0x11, 0x10, 0x13, 0x0a, 0x10, + 0x10, 0x0c, 0x13, 0x09, 0x13, 0x14, 0x0a, 0x15, 0x0a, 0x16, 0x13, 0x0f, + 0x0e, 0x10, 0x0c, 0x0b, 0x12, 0x0b, 0x0c, 0x0a, 0x12, 0x0a, 0x10, 0x11, + 0x0a, 0x0a, 0x0a, 0x13, 0x16, 0x0c, 0x0c, 0x0e, 0x11, 0x08, 0x10, 0x0c, + 0x15, 0x12, 0x09, 0x08, 0x11, 0x14, 0x0f, 0x17, 0x0d, 0x14, 0x0a, 0x17, + 0x17, 0x0e, 0x0a, 0x12, 0x11, 0x13, 0x0b, 0x13, 0x15, 0x0d, 0x0f, 0x13, + 0x12, 0x13, 0x0a, 0x0b, 0x14, 0x12, 0x10, 0x11, 0x0d, 0x11, 0x11, 0x16, + 0x0e, 0x09, 0x15, 0x13, 0x15, 0x08, 0x13, 0x15, 0x0f, 0x15, 0x0f, 0x08, + 0x16, 0x09, 0x0b, 0x14, 0x09, 0x16, 0x11, 0x11, 0x14, 0x09, 0x11, 0x0d, + 0x14, 0x0d, 0x14, 0x15, 0x11, 0x17, 0x11, 0x10, 0x0c, 0x10, 0x0b, 0x0c, + 0x08, 0x0f, 0x11, 0x0a, 0x0c, 0x14, 0x12, 0x0b, 0x15, 0x15, 0x17, 0x17, + 0x14, 0x11, 0x10, 0x11, 0x12, 0x0a, 0x16, 0x0e, 0x0f, 0x13, 0x0c, 0x08, + 0x12, 0x15, 0x10, 0x16, 0x0e, 0x14, 0x0a, 0x0e, 0x0b, 0x13, 0x11, 0x10, + 0x0f, 0x0b, 0x14, 0x0d, 0x08, 0x13, 0x0d, 0x15, 0x0c, 0x15, 0x0e, 0x17, + 0x17, 0x0d, 0x0d, 0x0f, 0x08, 0x12, 0x10, 0x12, 0x10, 0x09, 0x10, 0x16, + 0x15, 0x12, 0x0d, 0x09, 0x0e, 0x16, 0x12, 0x16, 0x09, 0x0e, 0x0b, 0x0a, + 0x0a, 0x10, 0x08, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x14, 0x16, 0x14, + 0x0e, 0x0e, 0x0e, 0x16, 0x10, 0x17, 0x14, 0x0d, 0x12, 0x0a, 0x0f, 0x08, + 0x08, 0x09, 0x17, 0x0a, 0x10, 0x0a, 0x0c, 0x13, 0x13, 0x0c, 0x0a, 0x0a, + 0x13, 0x10, 0x11, 0x0f, 0x0c, 0x0f, 0x0b, 0x12, 0x16, 0x12, 0x11, 0x0e, + 0x12, 0x0e, 0x13, 0x0c, 0x10, 0x0b, 0x0d, 0x10, 0x0d, 0x0c, 0x12, 0x15, + 0x0f, 0x17, 0x10, 0x0b, 0x0b, 0x12, 0x0d, 0x16, 0x0a, 0x17, 0x0e, 0x0e, + 0x0e, 0x12, 0x09, 0x0d, 0x0c, 0x12, 0x13, 0x17, 0x08, 0x0f, 0x0b, 0x10, + 0x12, 0x11, 0x09, 0x17, 0x16, 0x14, 0x15, 0x0e, 0x13, 0x0d, 0x11, 0x17, + 0x08, 0x17, 0x16, 0x0b, 0x16, 0x0c, 0x12, 0x0d, 0x16, 0x13, 0x12, 0x0b, + 0x0e, 0x0d, 0x0a, 0x0e, 0x15, 0x0e, 0x17, 0x0f, 0x08, 0x09, 0x0f, 0x16, + 0x15, 0x0c, 0x0c, 0x11, 0x12, 0x16, 0x10, 0x13, 0x15, 0x0f, 0x16, 0x13, + 0x14, 0x10, 0x09, 0x12, 0x0c, 0x13, 0x16, 0x12, 0x08, 0x09, 0x08, 0x15, + 0x0f, 0x08, 0x0d, 0x10, 0x09, 0x14, 0x0f, 0x17, 0x09, 0x13, 0x10, 0x13, + 0x12, 0x09, 0x0e, 0x0f, 0x10, 0x0d, 0x0b, 0x0c, 0x15, 0x0c, 0x17, 0x09, + 0x17, 0x16, 0x14, 0x08, 0x17, 0x14, 0x16, 0x0f, 0x15, 0x0c, 0x17, 0x17, + 0x09, 0x0e, 0x16, 0x0a, 0x0a, 0x0e, 0x16, 0x14, 0x10, 0x0d, 0x0c, 0x09, + 0x12, 0x10, 0x0e, 0x10, 0x14, 0x0e, 0x12, 0x14, 0x0c, 0x0e, 0x15, 0x0c, + 0x16, 0x0c, 0x13, 0x12, 0x12, 0x0e, 0x0f, 0x17, 0x14, 0x0d, 0x0b, 0x17, + 0x09, 0x17, 0x08, 0x0a, 0x12, 0x08, 0x0c, 0x14, 0x15, 0x10, 0x09, 0x0a, + 0x14, 0x0a, 0x17, 0x0c, 0x10, 0x16, 0x10, 0x0f, 0x0a, 0x0c, 0x0a, 0x15, + 0x12, 0x11, 0x14, 0x0f, 0x17, 0x17, 0x0f, 0x08, 0x17, 0x0f, 0x0b, 0x11, + 0x0f, 0x0f, 0x0e, 0x0d, 0x08, 0x0f, 0x10, 0x14, 0x12, 0x10, 0x09, 0x0b, + 0x0e, 0x11, 0x12, 0x11, 0x16, 0x14, 0x0e, 0x11, 0x0e, 0x0a, 0x08, 0x0d, + 0x0a, 0x0f, 0x0e, 0x09, 0x17, 0x11, 0x13, 0x0f, 0x09, 0x09, 0x15, 0x09, + 0x11, 0x0d, 0x16, 0x0c, 0x15, 0x17, 0x0f, 0x0c, 0x11, 0x0a, 0x15, 0x10, + 0x17, 0x0b, 0x09, 0x0e, 0x0e, 0x09, 0x13, 0x11, 0x11, 0x0a, 0x13, 0x10, + 0x14, 0x0e, 0x08, 0x15, 0x10, 0x15, 0x17, 0x09, 0x0a, 0x15, 0x0e, 0x08, + 0x15, 0x15, 0x0c, 0x0f, 0x08, 0x0a, 0x17, 0x17, 0x0d, 0x09, 0x0d, 0x14, + 0x0b, 0x09, 0x0d, 0x14, 0x0c, 0x08, 0x0d, 0x08, 0x0f, 0x0d, 0x16, 0x17, + 0x0a, 0x15, 0x09, 0x0d, 0x13, 0x0f, 0x0e, 0x11, 0x0d, 0x12, 0x09, 0x0d, + 0x14, 0x09, 0x0d, 0x0a, 0x0a, 0x13, 0x17, 0x0d, 0x15, 0x0c, 0x0a, 0x09, + 0x0d, 0x10, 0x0a, 0x14, 0x15, 0x08, 0x13, 0x08, 0x16, 0x15, 0x0e, 0x12, + 0x0c, 0x14, 0x0b, 0x11, 0x0f, 0x0c, 0x17, 0x0c, 0x0d, 0x0c, 0x0f, 0x10, + 0x08, 0x0e, 0x15, 0x15, 0x12, 0x08, 0x16, 0x17, 0x10, 0x09, 0x14, 0x0e, + 0x0a, 0x0f, 0x0f, 0x08, 0x0c, 0x15, 0x13, 0x11, 0x12, 0x16, 0x0a, 0x0a, + 0x0b, 0x0a, 0x0e, 0x11, 0x0f, 0x16, 0x09, 0x0f, 0x0c, 0x17, 0x0c, 0x17, + 0x17, 0x0b, 0x17, 0x10, 0x0c, 0x13, 0x16, 0x0e, 0x0a, 0x0e, 0x0f, 0x0f, + 0x0c, 0x0a, 0x08, 0x16, 0x09, 0x0b, 0x09, 0x0d, 0x0e, 0x0f, 0x16, 0x15, + 0x0e, 0x08, 0x0c, 0x12, 0x08, 0x11, 0x11, 0x08, 0x15, 0x10, 0x10, 0x09, + 0x0b, 0x0f, 0x10, 0x0e, 0x15, 0x08, 0x16, 0x09, 0x0a, 0x16, 0x08, 0x0c, + 0x0a, 0x09, 0x11, 0x10, 0x11, 0x10, 0x0d, 0x17, 0x10, 0x12, 0x11, 0x11, + 0x0c, 0x0b, 0x11, 0x09, 0x14, 0x09, 0x0b, 0x08, 0x10, 0x14, 0x0e, 0x0e, + 0x17, 0x08, 0x0c, 0x13, 0x0a, 0x0f, 0x14, 0x13, 0x0c, 0x0b, 0x09, 0x08, + 0x10, 0x11, 0x17, 0x13, 0x09, 0x0a, 0x09, 0x12, 0x17, 0x17, 0x15, 0x0d, + 0x0b, 0x17, 0x0b, 0x09, 0x13, 0x13, 0x0c, 0x13, 0x13, 0x11, 0x0f, 0x16, + 0x08, 0x0b, 0x11, 0x0d, 0x0e, 0x12, 0x0d, 0x16, 0x0b, 0x0d, 0x12, 0x0c, + 0x0f, 0x13, 0x17, 0x0f, 0x13, 0x14, 0x14, 0x17, 0x13, 0x08, 0x09, 0x0f, + 0x13, 0x0e, 0x0a, 0x0f, 0x17, 0x11, 0x0d, 0x08, 0x14, 0x16, 0x0d, 0x0b, + 0x10, 0x12, 0x09, 0x14, 0x17, 0x13, 0x09, 0x0f, 0x0f, 0x08, 0x17, 0x0b, + 0x14, 0x14, 0x0a, 0x10, 0x15, 0x0c, 0x17, 0x10, 0x12, 0x0a, 0x17, 0x11, + 0x13, 0x0d, 0x11, 0x10, 0x0b, 0x16, 0x13, 0x14, 0x11, 0x15, 0x10, 0x11, + 0x10, 0x11, 0x08, 0x08, 0x11, 0x08, 0x0b, 0x0e, 0x15, 0x0e, 0x16, 0x12, + 0x12, 0x16, 0x0a, 0x0c, 0x08, 0x0a, 0x15, 0x14, 0x0f, 0x0f, 0x0d, 0x13, + 0x0d, 0x08, 0x0f, 0x16, 0x15, 0x08, 0x0f, 0x0e, 0x12, 0x10, 0x0e, 0x0c, + 0x11, 0x12, 0x12, 0x0e, 0x08, 0x11, 0x08, 0x12, 0x0f, 0x0b, 0x17, 0x10, + 0x0e, 0x15, 0x0d, 0x16, 0x0c, 0x12, 0x11, 0x11, 0x13, 0x09, 0x10, 0x11, + 0x09, 0x08, 0x17, 0x13, 0x10, 0x0e, 0x17, 0x0a, 0x08, 0x12, 0x10, 0x09, + 0x0c, 0x11, 0x14, 0x14, 0x15, 0x13, 0x0c, 0x0b, 0x11, 0x12, 0x0a, 0x15, + 0x0c, 0x14, 0x0f, 0x08, 0x15, 0x08, 0x11, 0x16, 0x08, 0x11, 0x12, 0x11, + 0x08, 0x12, 0x13, 0x08, 0x0d, 0x0b, 0x0a, 0x11, 0x15, 0x16, 0x0d, 0x12, + 0x12, 0x12, 0x16, 0x0b, 0x0c, 0x08, 0x09, 0x11, 0x14, 0x11, 0x11, 0x12, + 0x11, 0x0b, 0x11, 0x11, 0x14, 0x0b, 0x0b, 0x14, 0x16, 0x16, 0x15, 0x0b, + 0x0a, 0x08, 0x15, 0x17, 0x16, 0x0a, 0x12, 0x11, 0x14, 0x10, 0x15, 0x09, + 0x11, 0x16, 0x12, 0x0e, 0x10, 0x0c, 0x08, 0x09, 0x10, 0x11, 0x13, 0x0c, + 0x15, 0x16, 0x09, 0x13, 0x14, 0x17, 0x17, 0x17, 0x17, 0x14, 0x16, 0x16, + 0x17, 0x10, 0x0f, 0x14, 0x09, 0x0d, 0x15, 0x12, 0x0b, 0x10, 0x08, 0x14, + 0x14, 0x09, 0x15, 0x0d, 0x12, 0x11, 0x12, 0x0f, 0x0f, 0x13, 0x0b, 0x0c, + 0x11, 0x0c, 0x0a, 0x0b, 0x15, 0x14, 0x13, 0x0d, 0x10, 0x16, 0x12, 0x0b, + 0x08, 0x16, 0x16, 0x17, 0x08, 0x10, 0x16, 0x14, 0x11, 0x10, 0x11, 0x08, + 0x08, 0x08, 0x12, 0x08, 0x11, 0x09, 0x15, 0x0a, 0x0d, 0x17, 0x0e, 0x0a, + 0x14, 0x0a, 0x10, 0x0c, 0x08, 0x0a, 0x10, 0x09, 0x08, 0x0e, 0x09, 0x09, + 0x17, 0x17, 0x15, 0x10, 0x10, 0x0f, 0x11, 0x10, 0x10, 0x0b, 0x11, 0x09, + 0x0c, 0x0f, 0x0c, 0x11, 0x0f, 0x12, 0x14, 0x0b, 0x14, 0x0c, 0x0f, 0x15, + 0x0e, 0x17, 0x17, 0x0f, 0x0e, 0x08, 0x10, 0x0d, 0x08, 0x0e, 0x16, 0x10, + 0x15, 0x0f, 0x09, 0x0d, 0x13, 0x12, 0x0f, 0x08, 0x0a, 0x13, 0x11, 0x11, + 0x0e, 0x0e, 0x14, 0x0a, 0x13, 0x0c, 0x08, 0x09, 0x0c, 0x17, 0x10, 0x12, + 0x08, 0x09, 0x08, 0x08, 0x0f, 0x17, 0x11, 0x0d, 0x0e, 0x13, 0x13, 0x0a, + 0x0e, 0x0a, 0x0a, 0x10, 0x15, 0x14, 0x09, 0x0b, 0x0a, 0x15, 0x0e, 0x15, + 0x0a, 0x0f, 0x17, 0x0e, 0x0e, 0x10, 0x09, 0x0f, 0x12, 0x09, 0x0f, 0x09, + 0x08, 0x09, 0x0f, 0x0f, 0x14, 0x0a, 0x11, 0x0a, 0x0d, 0x14, 0x12, 0x0a, + 0x10, 0x13, 0x0e, 0x12, 0x11, 0x15, 0x10, 0x13, 0x0c, 0x10, 0x0a, 0x13, + 0x08, 0x0b, 0x0a, 0x13, 0x0c, 0x12, 0x14, 0x0d, 0x13, 0x0c, 0x15, 0x0f, + 0x0f, 0x0f, 0x11, 0x14, 0x0b, 0x0c, 0x16, 0x13, 0x17, 0x0d, 0x0e, 0x11, + 0x0a, 0x17, 0x0d, 0x0f, 0x0f, 0x0f, 0x0a, 0x10, 0x12, 0x0d, 0x0b, 0x17, + 0x17, 0x08, 0x0d, 0x13, 0x0c, 0x0a, 0x0a, 0x14, 0x11, 0x14, 0x10, 0x14, + 0x09, 0x0f, 0x0f, 0x08, 0x14, 0x16, 0x12, 0x17, 0x15, 0x17, 0x0e, 0x0d, + 0x0f, 0x11, 0x15, 0x09, 0x17, 0x09, 0x09, 0x17, 0x09, 0x0e, 0x12, 0x0e, + 0x10, 0x15, 0x0a, 0x0a, 0x12, 0x12, 0x16, 0x13, 0x09, 0x0e, 0x14, 0x16, + 0x0c, 0x0e, 0x15, 0x0a, 0x0e, 0x0c, 0x0f, 0x15, 0x16, 0x0d, 0x17, 0x15, + 0x0e, 0x08, 0x14, 0x10, 0x0f, 0x0f, 0x16, 0x17, 0x0c, 0x09, 0x0a, 0x16, + 0x14, 0x08, 0x11, 0x16, 0x0f, 0x0d, 0x14, 0x14, 0x14, 0x12, 0x16, 0x0a, + 0x17, 0x0e, 0x17, 0x16, 0x14, 0x16, 0x13, 0x0a, 0x17, 0x10, 0x13, 0x0e, + 0x0a, 0x17, 0x13, 0x16, 0x16, 0x0f, 0x09, 0x15, 0x08, 0x14, 0x0c, 0x08, + 0x0e, 0x12, 0x0c, 0x09, 0x0b, 0x0e, 0x11, 0x14, 0x0a, 0x08, 0x15, 0x0b, + 0x0b, 0x12, 0x09, 0x09, 0x0e, 0x09, 0x17, 0x10, 0x08, 0x13, 0x0f, 0x17, + 0x0a, 0x10, 0x14, 0x0b, 0x0d, 0x09, 0x0b, 0x13, 0x13, 0x10, 0x15, 0x17, + 0x17, 0x0f, 0x13, 0x09, 0x0f, 0x11, 0x0d, 0x13, 0x0b, 0x0e, 0x14, 0x11, + 0x0f, 0x14, 0x0a, 0x10, 0x0f, 0x12, 0x0f, 0x12, 0x0a, 0x0c, 0x15, 0x10, + 0x0d, 0x09, 0x0b, 0x09, 0x12, 0x09, 0x08, 0x11, 0x11, 0x14, 0x13, 0x08, + 0x0d, 0x08, 0x14, 0x10, 0x0f, 0x11, 0x0a, 0x17, 0x0d, 0x0c, 0x10, 0x14, + 0x16, 0x17, 0x0f, 0x09, 0x0c, 0x0d, 0x11, 0x11, 0x0f, 0x15, 0x12, 0x09, + 0x17, 0x13, 0x12, 0x10, 0x0f, 0x0e, 0x11, 0x14, 0x0e, 0x0d, 0x0c, 0x16, + 0x16, 0x0f, 0x16, 0x0c, 0x13, 0x0e, 0x09, 0x12, 0x0e, 0x10, 0x14, 0x12, + 0x15, 0x0e, 0x0c, 0x0c, 0x0c, 0x17, 0x0d, 0x0b, 0x12, 0x08, 0x13, 0x09, + 0x0e, 0x0c, 0x16, 0x15, 0x12, 0x0b, 0x14, 0x10, 0x12, 0x12, 0x15, 0x0e, + 0x08, 0x16, 0x09, 0x0f, 0x0e, 0x15, 0x09, 0x0c, 0x0c, 0x0e, 0x10, 0x10, + 0x0d, 0x16, 0x13, 0x08, 0x17, 0x0f, 0x0a, 0x0e, 0x14, 0x08, 0x0b, 0x0e, + 0x0b, 0x17, 0x17, 0x16, 0x12, 0x14, 0x0c, 0x13, 0x13, 0x0e, 0x0a, 0x09, + 0x0c, 0x0c, 0x0e, 0x10, 0x12, 0x17, 0x08, 0x08, 0x15, 0x14, 0x08, 0x15, + 0x0c, 0x0a, 0x0b, 0x08, 0x0b, 0x0f, 0x0f, 0x0e, 0x0f, 0x0f, 0x0d, 0x09, + 0x0b, 0x12, 0x14, 0x17, 0x08, 0x17, 0x09, 0x0c, 0x0b, 0x0f, 0x15, 0x16, + 0x0e, 0x15, 0x17, 0x0c, 0x12, 0x17, 0x09, 0x17, 0x0a, 0x0c, 0x17, 0x0d, + 0x13, 0x0f, 0x14, 0x0a, 0x16, 0x09, 0x0c, 0x0a, 0x14, 0x08, 0x09, 0x14, + 0x08, 0x0a, 0x09, 0x0c, 0x12, 0x16, 0x0a, 0x08, 0x14, 0x09, 0x0c, 0x0f, + 0x09, 0x0d, 0x0e, 0x0b, 0x12, 0x0e, 0x11, 0x0d, 0x15, 0x0d, 0x10, 0x14, + 0x0f, 0x14, 0x16, 0x0b, 0x15, 0x08, 0x08, 0x15, 0x0b, 0x09, 0x09, 0x15, + 0x17, 0x0c, 0x15, 0x14, 0x0e, 0x0a, 0x0b, 0x0f, 0x10, 0x11, 0x13, 0x0a, + 0x16, 0x0f, 0x0b, 0x0d, 0x12, 0x0e, 0x14, 0x0a, 0x17, 0x10, 0x0d, 0x17, + 0x14, 0x15, 0x14, 0x0f, 0x16, 0x0d, 0x11, 0x14, 0x16, 0x16, 0x0e, 0x0f, + 0x0c, 0x17, 0x0b, 0x13, 0x11, 0x15, 0x0a, 0x10, 0x0d, 0x0e, 0x15, 0x17, + 0x14, 0x12, 0x0a, 0x14, 0x0a, 0x0f, 0x13, 0x17, 0x0d, 0x0f, 0x0e, 0x0b, + 0x15, 0x17, 0x17, 0x13, 0x16, 0x0e, 0x0a, 0x0a, 0x0e, 0x0e, 0x16, 0x17, + 0x0b, 0x09, 0x10, 0x11, 0x0f, 0x0d, 0x10, 0x0b, 0x08, 0x13, 0x08, 0x0a, + 0x0b, 0x13, 0x0a, 0x10, 0x0b, 0x10, 0x14, 0x09, 0x10, 0x14, 0x15, 0x0f, + 0x0b, 0x08, 0x11, 0x11, 0x0e, 0x10, 0x11, 0x12, 0x11, 0x09, 0x0b, 0x08, + 0x0f, 0x14, 0x0c, 0x0f, 0x0f, 0x0c, 0x11, 0x12, 0x08, 0x14, 0x0b, 0x0c, + 0x0c, 0x17, 0x0e, 0x15, 0x14, 0x0b, 0x0c, 0x17, 0x0b, 0x16, 0x10, 0x12, + 0x0e, 0x0a, 0x0c, 0x17, 0x0b, 0x0f, 0x08, 0x12, 0x0c, 0x0c, 0x0a, 0x14, + 0x11, 0x14, 0x0e, 0x12, 0x10, 0x12, 0x17, 0x15, 0x12, 0x0d, 0x12, 0x0e, + 0x11, 0x17, 0x0e, 0x14, 0x15, 0x16, 0x0f, 0x0b, 0x09, 0x13, 0x0b, 0x0c, + 0x0b, 0x0b, 0x17, 0x10, 0x10, 0x09, 0x0c, 0x09, 0x16, 0x12, 0x13, 0x0e, + 0x0d, 0x12, 0x0b, 0x17, 0x08, 0x16, 0x0e, 0x11, 0x15, 0x14, 0x0e, 0x13, + 0x13, 0x15, 0x17, 0x14, 0x11, 0x0a, 0x09, 0x15, 0x0e, 0x09, 0x0d, 0x16, + 0x0b, 0x11, 0x17, 0x09, 0x0c, 0x13, 0x0f, 0x11, 0x0e, 0x12, 0x11, 0x0e, + 0x11, 0x08, 0x08, 0x0e, 0x14, 0x0e, 0x0a, 0x10, 0x0c, 0x09, 0x0c, 0x15, + 0x0c, 0x0e, 0x12, 0x12, 0x0f, 0x17, 0x10, 0x12, 0x11, 0x10, 0x13, 0x15, + 0x0c, 0x0b, 0x0f, 0x13, 0x16, 0x08, 0x0a, 0x0f, 0x08, 0x0a, 0x16, 0x15, + 0x10, 0x08, 0x0d, 0x14, 0x09, 0x12, 0x12, 0x0d, 0x09, 0x0d, 0x08, 0x10, + 0x0d, 0x11, 0x0b, 0x16, 0x0a, 0x17, 0x13, 0x0e, 0x0a, 0x0b, 0x0a, 0x08, + 0x0c, 0x0c, 0x0f, 0x0c, 0x0e, 0x0d, 0x0a, 0x17, 0x0d, 0x10, 0x14, 0x0f, + 0x0b, 0x0e, 0x15, 0x0c, 0x14, 0x15, 0x15, 0x09, 0x0f, 0x08, 0x17, 0x11, + 0x08, 0x13, 0x08, 0x0a, 0x16, 0x0a, 0x0a, 0x0a, 0x0e, 0x12, 0x0f, 0x15, + 0x0f, 0x11, 0x12, 0x0e, 0x13, 0x15, 0x10, 0x0a, 0x0f, 0x08, 0x17, 0x10, + 0x12, 0x14, 0x16, 0x14, 0x0d, 0x13, 0x0a, 0x0d, 0x0e, 0x13, 0x0a, 0x17, + 0x0a, 0x17, 0x17, 0x12, 0x14, 0x10, 0x0a, 0x0c, 0x0a, 0x14, 0x12, 0x16, + 0x12, 0x0b, 0x08, 0x0a, 0x0b, 0x08, 0x12, 0x16, 0x14, 0x10, 0x12, 0x0a, + 0x0c, 0x14, 0x10, 0x13, 0x10, 0x12, 0x12, 0x13, 0x11, 0x12, 0x0e, 0x0d, + 0x0b, 0x10, 0x11, 0x0d, 0x0d, 0x0c, 0x0b, 0x08, 0x0f, 0x0b, 0x0a, 0x13, + 0x0b, 0x14, 0x11, 0x08, 0x0d, 0x0c, 0x0a, 0x11, 0x09, 0x13, 0x0d, 0x12, + 0x0d, 0x08, 0x0d, 0x16, 0x12, 0x14, 0x0c, 0x15, 0x0d, 0x16, 0x0a, 0x13, + 0x0a, 0x0e, 0x13, 0x12, 0x11, 0x15, 0x0d, 0x15, 0x12, 0x17, 0x16, 0x17, + 0x0c, 0x09, 0x11, 0x0d, 0x14, 0x16, 0x08, 0x09, 0x17, 0x0e, 0x08, 0x11, + 0x0a, 0x0d, 0x0f, 0x0f, 0x0b, 0x11, 0x0a, 0x0d, 0x08, 0x16, 0x17, 0x11, + 0x13, 0x0d, 0x0f, 0x0e, 0x0d, 0x0e, 0x0d, 0x11, 0x0f, 0x17, 0x16, 0x0b, + 0x16, 0x16, 0x0d, 0x15, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, 0x15, 0x16, 0x15, + 0x0f, 0x09, 0x0b, 0x0f, 0x17, 0x0b, 0x09, 0x13, 0x11, 0x11, 0x09, 0x16, + 0x17, 0x0f, 0x0f, 0x0e, 0x0f, 0x0e, 0x12, 0x0d, 0x0d, 0x17, 0x0a, 0x11, + 0x0d, 0x11, 0x09, 0x17, 0x0e, 0x08, 0x15, 0x16, 0x09, 0x09, 0x0e, 0x09, + 0x0d, 0x0f, 0x15, 0x16, 0x09, 0x17, 0x14, 0x08, 0x0f, 0x0b, 0x0f, 0x16, + 0x12, 0x0a, 0x0b, 0x17, 0x09, 0x0d, 0x11, 0x0f, 0x17, 0x12, 0x0e, 0x0e, + 0x12, 0x0c, 0x0c, 0x14, 0x0e, 0x13, 0x16, 0x13, 0x0b, 0x13, 0x11, 0x0c, + 0x13, 0x0e, 0x0d, 0x0a, 0x11, 0x15, 0x08, 0x0b, 0x17, 0x0c, 0x0b, 0x09, + 0x12, 0x14, 0x10, 0x11, 0x0e, 0x17, 0x17, 0x08, 0x0b, 0x0c, 0x15, 0x11, + 0x17, 0x13, 0x0c, 0x0a, 0x0f, 0x16, 0x0e, 0x0a, 0x0c, 0x14, 0x0d, 0x16, + 0x11, 0x0d, 0x0a, 0x10, 0x12, 0x0d, 0x12, 0x0c, 0x09, 0x0a, 0x16, 0x0f, + 0x09, 0x16, 0x10, 0x0d, 0x0a, 0x0e, 0x17, 0x0a, 0x09, 0x0c, 0x0c, 0x10, + 0x0a, 0x13, 0x13, 0x0e, 0x0f, 0x08, 0x0d, 0x09, 0x0e, 0x0f, 0x12, 0x08, + 0x0f, 0x12, 0x12, 0x17, 0x12, 0x17, 0x08, 0x09, 0x0f, 0x12, 0x0a, 0x0b, + 0x17, 0x0f, 0x09, 0x0e, 0x14, 0x0f, 0x17, 0x16, 0x0e, 0x15, 0x0b, 0x13, + 0x13, 0x13, 0x0a, 0x14, 0x0f, 0x09, 0x08, 0x16, 0x14, 0x13, 0x16, 0x0f, + 0x12, 0x16, 0x10, 0x09, 0x11, 0x12, 0x0d, 0x11, 0x0a, 0x0f, 0x08, 0x16, + 0x17, 0x17, 0x15, 0x0d, 0x15, 0x08, 0x09, 0x10, 0x13, 0x0b, 0x0d, 0x0b, + 0x0d, 0x0d, 0x09, 0x0a, 0x08, 0x17, 0x11, 0x13, 0x16, 0x0a, 0x15, 0x10, + 0x14, 0x0b, 0x09, 0x17, 0x12, 0x09, 0x16, 0x12, 0x09, 0x13, 0x17, 0x16, + 0x13, 0x09, 0x0f, 0x0f, 0x0d, 0x14, 0x12, 0x13, 0x0a, 0x14, 0x15, 0x0a, + 0x14, 0x0e, 0x16, 0x13, 0x11, 0x14, 0x0b, 0x0e, 0x17, 0x0d, 0x0d, 0x12, + 0x0f, 0x0b, 0x0c, 0x10, 0x16, 0x0c, 0x0f, 0x12, 0x0e, 0x17, 0x0a, 0x13, + 0x13, 0x15, 0x0e, 0x15, 0x11, 0x0c, 0x08, 0x0e, 0x13, 0x17, 0x09, 0x0c, + 0x13, 0x0d, 0x12, 0x13, 0x12, 0x17, 0x0d, 0x0a, 0x0b, 0x12, 0x13, 0x0a, + 0x16, 0x0a, 0x14, 0x0c, 0x09, 0x17, 0x08, 0x15, 0x14, 0x0f, 0x12, 0x0e, + 0x13, 0x13, 0x14, 0x0f, 0x12, 0x15, 0x13, 0x0e, 0x0a, 0x0d, 0x09, 0x15, + 0x0d, 0x0f, 0x17, 0x11, 0x09, 0x13, 0x13, 0x08, 0x15, 0x10, 0x0d, 0x17, + 0x0f, 0x0e, 0x15, 0x0b, 0x15, 0x10, 0x11, 0x11, 0x0b, 0x0e, 0x08, 0x16, + 0x0c, 0x14, 0x0c, 0x0e, 0x0a, 0x0d, 0x0c, 0x0f, 0x14, 0x0c, 0x09, 0x16, + 0x17, 0x15, 0x16, 0x15, 0x0d, 0x0c, 0x15, 0x14, 0x12, 0x12, 0x08, 0x0f, + 0x0a, 0x12, 0x09, 0x0e, 0x08, 0x09, 0x0c, 0x0c, 0x15, 0x11, 0x13, 0x17, + 0x16, 0x08, 0x0f, 0x13, 0x0c, 0x11, 0x11, 0x0c, 0x0e, 0x10, 0x0a, 0x13, + 0x14, 0x17, 0x10, 0x0e, 0x12, 0x10, 0x16, 0x15, 0x0b, 0x17, 0x0b, 0x0b, + 0x08, 0x10, 0x0f, 0x16, 0x09, 0x0b, 0x16, 0x08, 0x0b, 0x0e, 0x14, 0x10, + 0x17, 0x0e, 0x14, 0x0d, 0x16, 0x16, 0x09, 0x13, 0x16, 0x11, 0x0a, 0x10, + 0x0a, 0x08, 0x0d, 0x0d, 0x17, 0x11, 0x10, 0x08, 0x0a, 0x08, 0x17, 0x0c, + 0x0c, 0x15, 0x0d, 0x0f, 0x0b, 0x09, 0x17, 0x0a, 0x0f, 0x14, 0x10, 0x0e, + 0x09, 0x15, 0x08, 0x0d, 0x17, 0x08, 0x0f, 0x0f, 0x14, 0x08, 0x15, 0x0f, + 0x11, 0x08, 0x08, 0x14, 0x0c, 0x0a, 0x0a, 0x11, 0x11, 0x15, 0x15, 0x12, + 0x09, 0x0a, 0x16, 0x0e, 0x0e, 0x0e, 0x17, 0x0f, 0x0b, 0x17, 0x14, 0x0a, + 0x08, 0x0c, 0x11, 0x14, 0x0c, 0x0f, 0x0c, 0x16, 0x0f, 0x0d, 0x13, 0x14, + 0x0f, 0x15, 0x0d, 0x09, 0x13, 0x0a, 0x14, 0x14, 0x0d, 0x12, 0x0a, 0x13, + 0x08, 0x09, 0x0b, 0x0c, 0x09, 0x08, 0x0f, 0x09, 0x0c, 0x09, 0x16, 0x11, + 0x10, 0x0a, 0x10, 0x08, 0x10, 0x0b, 0x15, 0x17, 0x09, 0x0a, 0x09, 0x15, + 0x0d, 0x15, 0x11, 0x12, 0x0f, 0x14, 0x0d, 0x10, 0x16, 0x11, 0x14, 0x08, + 0x11, 0x0b, 0x09, 0x16, 0x0c, 0x08, 0x10, 0x15, 0x0b, 0x08, 0x16, 0x13, + 0x0c, 0x13, 0x13, 0x0e, 0x15, 0x14, 0x0b, 0x0b, 0x11, 0x15, 0x15, 0x08, + 0x11, 0x0b, 0x11, 0x10, 0x14, 0x0d, 0x10, 0x0e, 0x11, 0x12, 0x0c, 0x16, + 0x12, 0x14, 0x13, 0x15, 0x15, 0x12, 0x10, 0x0a, 0x0d, 0x0b, 0x11, 0x0b, + 0x08, 0x14, 0x0e, 0x11, 0x12, 0x0c, 0x12, 0x0c, 0x10, 0x0b, 0x14, 0x0d, + 0x10, 0x0c, 0x13, 0x0a, 0x16, 0x17, 0x08, 0x11, 0x14, 0x14, 0x0e, 0x11, + 0x0e, 0x16, 0x14, 0x14, 0x0a, 0x0d, 0x08, 0x0a, 0x0a, 0x0e, 0x14, 0x14, + 0x13, 0x0e, 0x08, 0x0b, 0x11, 0x14, 0x10, 0x0a, 0x09, 0x0c, 0x0d, 0x08, + 0x0b, 0x0d, 0x11, 0x08, 0x0a, 0x17, 0x12, 0x10, 0x16, 0x0e, 0x0d, 0x08, + 0x13, 0x0d, 0x0b, 0x15, 0x14, 0x17, 0x12, 0x0f, 0x0e, 0x12, 0x13, 0x17, + 0x0f, 0x0c, 0x0a, 0x10, 0x10, 0x0f, 0x10, 0x14, 0x15, 0x0a, 0x14, 0x17, + 0x09, 0x0e, 0x10, 0x08, 0x15, 0x15, 0x09, 0x10, 0x0a, 0x0c, 0x0e, 0x16, + 0x0c, 0x09, 0x0e, 0x12, 0x13, 0x09, 0x12, 0x0a, 0x0e, 0x15, 0x13, 0x16, + 0x0d, 0x0c, 0x12, 0x0a, 0x0e, 0x0f, 0x0a, 0x10, 0x15, 0x12, 0x10, 0x12, + 0x10, 0x12, 0x0b, 0x12, 0x16, 0x12, 0x11, 0x0b, 0x13, 0x17, 0x15, 0x0e, + 0x09, 0x10, 0x11, 0x0f, 0x0d, 0x0c, 0x0d, 0x12, 0x10, 0x08, 0x15, 0x17, + 0x0f, 0x17, 0x0f, 0x0c, 0x12, 0x08, 0x17, 0x0a, 0x12, 0x0a, 0x14, 0x11, + 0x17, 0x15, 0x08, 0x11, 0x15, 0x17, 0x13, 0x0f, 0x0a, 0x10, 0x08, 0x17, + 0x17, 0x14, 0x10, 0x0c, 0x0f, 0x10, 0x13, 0x11, 0x09, 0x11, 0x0a, 0x16, + 0x15, 0x0c, 0x0d, 0x09, 0x0c, 0x12, 0x14, 0x0c, 0x0f, 0x15, 0x15, 0x0d, + 0x14, 0x11, 0x14, 0x17, 0x0a, 0x15, 0x16, 0x09, 0x12, 0x0f, 0x0e, 0x09, + 0x17, 0x0a, 0x13, 0x08, 0x14, 0x15, 0x17, 0x12, 0x0a, 0x0c, 0x14, 0x0f, + 0x17, 0x11, 0x13, 0x0f, 0x0e, 0x11, 0x14, 0x0a, 0x0a, 0x10, 0x09, 0x0d, + 0x0d, 0x08, 0x0f, 0x17, 0x0f, 0x16, 0x09, 0x0e, 0x08, 0x14, 0x0e, 0x15, + 0x12, 0x0d, 0x10, 0x14, 0x12, 0x0c, 0x0b, 0x11, 0x15, 0x16, 0x08, 0x0b, + 0x0f, 0x15, 0x0e, 0x12, 0x0d, 0x0f, 0x17, 0x13, 0x10, 0x0f, 0x13, 0x17, + 0x0d, 0x14, 0x0e, 0x0e, 0x11, 0x15, 0x0b, 0x0b, 0x0b, 0x13, 0x17, 0x15, + 0x08, 0x0b, 0x0e, 0x15, 0x09, 0x0f, 0x08, 0x11, 0x0c, 0x0e, 0x0b, 0x12, + 0x16, 0x0b, 0x0e, 0x0f, 0x12, 0x09, 0x0e, 0x08, 0x16, 0x15, 0x0e, 0x10, + 0x12, 0x12, 0x13, 0x15, 0x0e, 0x13, 0x13, 0x0e, 0x17, 0x0a, 0x0b, 0x09, + 0x12, 0x0c, 0x12, 0x16, 0x13, 0x16, 0x11, 0x11, 0x0a, 0x17, 0x08, 0x15, + 0x09, 0x0f, 0x15, 0x08, 0x0d, 0x0c, 0x10, 0x17, 0x16, 0x0c, 0x15, 0x0d, + 0x08, 0x11, 0x13, 0x08, 0x13, 0x17, 0x09, 0x0d, 0x0c, 0x13, 0x0c, 0x17, + 0x12, 0x15, 0x10, 0x14, 0x15, 0x11, 0x12, 0x17, 0x09, 0x0f, 0x17, 0x0e, + 0x13, 0x10, 0x0e, 0x12, 0x15, 0x0c, 0x08, 0x16, 0x15, 0x14, 0x16, 0x11, + 0x13, 0x17, 0x16, 0x17, 0x13, 0x0b, 0x16, 0x0d, 0x09, 0x0f, 0x0a, 0x16, + 0x09, 0x14, 0x16, 0x0a, 0x0b, 0x15, 0x10, 0x17, 0x0e, 0x16, 0x12, 0x0b, + 0x0a, 0x12, 0x09, 0x08, 0x0e, 0x08, 0x11, 0x0a, 0x17, 0x0f, 0x0a, 0x12, + 0x13, 0x09, 0x08, 0x14, 0x10, 0x0a, 0x13, 0x11, 0x16, 0x11, 0x14, 0x0a, + 0x0f, 0x0c, 0x0a, 0x15, 0x0b, 0x15, 0x09, 0x0e, 0x10, 0x0a, 0x0e, 0x16, + 0x0a, 0x17, 0x09, 0x0a, 0x0f, 0x0b, 0x14, 0x0a, 0x0c, 0x15, 0x17, 0x15, + 0x17, 0x13, 0x0f, 0x16, 0x0d, 0x0b, 0x09, 0x14, 0x10, 0x0c, 0x11, 0x14, + 0x14, 0x10, 0x13, 0x09, 0x14, 0x14, 0x16, 0x0c, 0x09, 0x10, 0x09, 0x0b, + 0x0b, 0x0b, 0x15, 0x09, 0x14, 0x0e, 0x09, 0x0b, 0x08, 0x0c, 0x0b, 0x16, + 0x0c, 0x0d, 0x09, 0x09, 0x0e, 0x0a, 0x16, 0x0b, 0x12, 0x11, 0x0d, 0x0e, + 0x0e, 0x0b, 0x13, 0x0f, 0x14, 0x14, 0x12, 0x17, 0x17, 0x10, 0x09, 0x13, + 0x16, 0x0a, 0x17, 0x16, 0x0f, 0x0a, 0x15, 0x14, 0x0f, 0x16, 0x15, 0x16, + 0x08, 0x14, 0x09, 0x12, 0x0d, 0x0f, 0x09, 0x14, 0x12, 0x14, 0x0b, 0x0f, + 0x10, 0x16, 0x0e, 0x10, 0x0e, 0x10, 0x0c, 0x0d, 0x12, 0x0c, 0x0b, 0x0a, + 0x0e, 0x08, 0x17, 0x16, 0x16, 0x15, 0x15, 0x17, 0x11, 0x16, 0x12, 0x16, + 0x0e, 0x13, 0x12, 0x09, 0x10, 0x16, 0x10, 0x09, 0x15, 0x17, 0x12, 0x0c, + 0x0f, 0x16, 0x11, 0x0a, 0x0a, 0x15, 0x0c, 0x11, 0x15, 0x0c, 0x10, 0x14, + 0x09, 0x0d, 0x14, 0x12, 0x0c, 0x0e, 0x10, 0x12, 0x0a, 0x0b, 0x13, 0x13, + 0x0a, 0x0c, 0x14, 0x08, 0x0b, 0x0e, 0x0d, 0x12, 0x0d, 0x16, 0x14, 0x0f, + 0x14, 0x09, 0x09, 0x11, 0x0d, 0x12, 0x0e, 0x0f, 0x17, 0x0a, 0x09, 0x0c, + 0x11, 0x12, 0x17, 0x14, 0x15, 0x13, 0x0f, 0x08, 0x17, 0x0c, 0x08, 0x0a, + 0x12, 0x0e, 0x15, 0x17, 0x0c, 0x11, 0x0f, 0x09, 0x13, 0x11, 0x13, 0x09, + 0x0b, 0x09, 0x10, 0x0b, 0x0c, 0x11, 0x0f, 0x16, 0x0b, 0x0f, 0x13, 0x09, + 0x0a, 0x0a, 0x0a, 0x09, 0x0e, 0x0b, 0x0c, 0x09, 0x11, 0x09, 0x09, 0x16, + 0x12, 0x10, 0x17, 0x0e, 0x09, 0x12, 0x0f, 0x0d, 0x14, 0x17, 0x10, 0x09, + 0x11, 0x08, 0x17, 0x15, 0x0f, 0x12, 0x16, 0x11, 0x15, 0x09, 0x13, 0x0c, + 0x0c, 0x17, 0x0d, 0x15, 0x08, 0x0e, 0x13, 0x13, 0x17, 0x13, 0x09, 0x08, + 0x0d, 0x11, 0x0e, 0x0a, 0x11, 0x16, 0x0b, 0x0a, 0x16, 0x0a, 0x17, 0x0d, + 0x15, 0x16, 0x17, 0x12, 0x17, 0x12, 0x17, 0x0c, 0x11, 0x0c, 0x09, 0x11, + 0x12, 0x15, 0x0d, 0x12, 0x10, 0x0e, 0x12, 0x16, 0x17, 0x08, 0x08, 0x10, + 0x17, 0x0b, 0x13, 0x15, 0x0e, 0x13, 0x0b, 0x0c, 0x11, 0x0a, 0x16, 0x11, + 0x15, 0x16, 0x16, 0x0f, 0x0a, 0x08, 0x09, 0x15, 0x15, 0x0e, 0x0f, 0x0e, + 0x08, 0x16, 0x13, 0x0b, 0x16, 0x14, 0x08, 0x13, 0x0a, 0x10, 0x0a, 0x17, + 0x12, 0x0f, 0x14, 0x15, 0x14, 0x09, 0x08, 0x0d, 0x0a, 0x09, 0x0d, 0x16, + 0x0d, 0x11, 0x0c, 0x14, 0x13, 0x0b, 0x09, 0x14, 0x09, 0x14, 0x17, 0x08, + 0x11, 0x17, 0x13, 0x14, 0x0f, 0x15, 0x14, 0x0a, 0x0d, 0x10, 0x08, 0x09, + 0x12, 0x09, 0x0f, 0x14, 0x0a, 0x14, 0x12, 0x0f, 0x0d, 0x16, 0x0c, 0x09, + 0x0a, 0x0d, 0x15, 0x0c, 0x0a, 0x15, 0x0c, 0x13, 0x14, 0x08, 0x0f, 0x0c, + 0x16, 0x0b, 0x0f, 0x0b, 0x14, 0x0f, 0x0d, 0x0e, 0x11, 0x14, 0x0a, 0x13, + 0x11, 0x15, 0x0b, 0x17, 0x14, 0x0f, 0x09, 0x16, 0x15, 0x16, 0x0b, 0x17, + 0x14, 0x10, 0x13, 0x11, 0x11, 0x0b, 0x15, 0x0f, 0x0f, 0x0d, 0x13, 0x0b, + 0x15, 0x08, 0x11, 0x0e, 0x15, 0x14, 0x09, 0x0f, 0x11, 0x0d, 0x0f, 0x0d, + 0x15, 0x10, 0x0c, 0x12, 0x0f, 0x10, 0x12, 0x0b, 0x09, 0x0e, 0x14, 0x12, + 0x11, 0x12, 0x09, 0x08, 0x17, 0x15, 0x0c, 0x14, 0x15, 0x16, 0x0b, 0x13, + 0x12, 0x0d, 0x0a, 0x0c, 0x12, 0x11, 0x12, 0x0f, 0x0a, 0x17, 0x0a, 0x11, + 0x10, 0x14, 0x15, 0x11, 0x0a, 0x11, 0x0b, 0x14, 0x0b, 0x0d, 0x15, 0x0b, + 0x0a, 0x09, 0x08, 0x08, 0x17, 0x0b, 0x13, 0x12, 0x10, 0x16, 0x17, 0x0b, + 0x10, 0x12, 0x12, 0x12, 0x11, 0x14, 0x0c, 0x09, 0x11, 0x09, 0x12, 0x14, + 0x13, 0x16, 0x10, 0x17, 0x0b, 0x0d, 0x0b, 0x0d, 0x0f, 0x0b, 0x0d, 0x0f, + 0x0f, 0x09, 0x0a, 0x08, 0x08, 0x09, 0x0b, 0x10, 0x13, 0x16, 0x0b, 0x0d, + 0x13, 0x10, 0x0f, 0x0c, 0x12, 0x09, 0x09, 0x0d, 0x17, 0x12, 0x0c, 0x0b, + 0x17, 0x0f, 0x10, 0x0f, 0x13, 0x16, 0x16, 0x0b, 0x08, 0x08, 0x0b, 0x08, + 0x0a, 0x0f, 0x11, 0x16, 0x0d, 0x15, 0x0b, 0x09, 0x0d, 0x12, 0x0e, 0x17, + 0x14, 0x0f, 0x0d, 0x14, 0x09, 0x12, 0x17, 0x09, 0x09, 0x10, 0x10, 0x15, + 0x0f, 0x0f, 0x08, 0x10, 0x10, 0x0c, 0x11, 0x13, 0x13, 0x0b, 0x11, 0x09, + 0x08, 0x15, 0x0a, 0x0e, 0x0f, 0x11, 0x0e, 0x0c, 0x08, 0x13, 0x08, 0x0a, + 0x0e, 0x08, 0x0b, 0x0f, 0x10, 0x14, 0x0d, 0x08, 0x0c, 0x0d, 0x10, 0x15, + 0x14, 0x11, 0x14, 0x0d, 0x0d, 0x09, 0x0d, 0x12, 0x0f, 0x15, 0x0f, 0x09, + 0x17, 0x17, 0x0e, 0x0c, 0x09, 0x16, 0x11, 0x08, 0x10, 0x0d, 0x0f, 0x13, + 0x0f, 0x0b, 0x17, 0x0d, 0x17, 0x0c, 0x11, 0x13, 0x16, 0x0d, 0x08, 0x0b, + 0x0f, 0x0d, 0x16, 0x16, 0x0b, 0x0d, 0x17, 0x0b, 0x0d, 0x0e, 0x0f, 0x0e, + 0x0c, 0x08, 0x0f, 0x15, 0x0e, 0x17, 0x10, 0x15, 0x0a, 0x0f, 0x0b, 0x09, + 0x14, 0x14, 0x14, 0x12, 0x0a, 0x15, 0x16, 0x11, 0x0a, 0x14, 0x0f, 0x0e, + 0x0a, 0x0f, 0x11, 0x0f, 0x15, 0x08, 0x15, 0x0a, 0x09, 0x0d, 0x17, 0x0f, + 0x0c, 0x10, 0x0d, 0x0e, 0x08, 0x10, 0x10, 0x14, 0x0d, 0x0d, 0x0f, 0x0f, + 0x0a, 0x0d, 0x09, 0x0d, 0x0a, 0x10, 0x13, 0x0c, 0x17, 0x0c, 0x13, 0x15, + 0x0d, 0x11, 0x08, 0x0f, 0x16, 0x08, 0x17, 0x0a, 0x10, 0x0c, 0x11, 0x10, + 0x15, 0x09, 0x0d, 0x0b, 0x0f, 0x14, 0x12, 0x11, 0x0a, 0x14, 0x16, 0x0c, + 0x0c, 0x11, 0x11, 0x0c, 0x16, 0x0c, 0x0a, 0x0c, 0x15, 0x0a, 0x13, 0x13, + 0x0b, 0x12, 0x16, 0x13, 0x17, 0x10, 0x0c, 0x15, 0x11, 0x11, 0x08, 0x08, + 0x0e, 0x13, 0x12, 0x10, 0x0f, 0x10, 0x15, 0x14, 0x0a, 0x0e, 0x08, 0x09, + 0x12, 0x0b, 0x0d, 0x10, 0x0e, 0x09, 0x0c, 0x11, 0x14, 0x0b, 0x0d, 0x14, + 0x13, 0x11, 0x11, 0x0d, 0x0b, 0x11, 0x0e, 0x12, 0x0d, 0x08, 0x0a, 0x14, + 0x11, 0x08, 0x10, 0x13, 0x0e, 0x11, 0x14, 0x09, 0x15, 0x0a, 0x12, 0x0b, + 0x0b, 0x16, 0x15, 0x17, 0x09, 0x0a, 0x14, 0x15, 0x14, 0x0d, 0x0a, 0x08, + 0x17, 0x10, 0x12, 0x0c, 0x10, 0x15, 0x09, 0x09, 0x15, 0x11, 0x15, 0x0c, + 0x0b, 0x11, 0x0d, 0x08, 0x14, 0x17, 0x0c, 0x17, 0x16, 0x09, 0x17, 0x08, + 0x0c, 0x13, 0x15, 0x09, 0x09, 0x17, 0x0a, 0x08, 0x10, 0x15, 0x0d, 0x08, + 0x12, 0x0e, 0x0a, 0x10, 0x08, 0x17, 0x14, 0x0b, 0x11, 0x0a, 0x0c, 0x0d, + 0x0a, 0x11, 0x0d, 0x08, 0x13, 0x0d, 0x09, 0x17, 0x09, 0x17, 0x09, 0x0a, + 0x17, 0x0b, 0x0b, 0x0f, 0x08, 0x10, 0x0f, 0x13, 0x17, 0x12, 0x0b, 0x17, + 0x11, 0x08, 0x0b, 0x0b, 0x0a, 0x10, 0x10, 0x0c, 0x09, 0x16, 0x0d, 0x14, + 0x09, 0x0e, 0x13, 0x0c, 0x17, 0x0c, 0x10, 0x08, 0x0b, 0x16, 0x15, 0x0f, + 0x0d, 0x11, 0x15, 0x13, 0x0f, 0x0d, 0x08, 0x10, 0x09, 0x14, 0x12, 0x0e, + 0x08, 0x10, 0x12, 0x16, 0x11, 0x15, 0x0f, 0x13, 0x0c, 0x0a, 0x17, 0x0b, + 0x0f, 0x10, 0x0b, 0x12, 0x0f, 0x08, 0x0a, 0x14, 0x12, 0x17, 0x0f, 0x09, + 0x0c, 0x0f, 0x11, 0x0e, 0x0c, 0x0c, 0x14, 0x0c, 0x15, 0x0e, 0x0b, 0x0e, + 0x0b, 0x12, 0x0a, 0x0f, 0x14, 0x0a, 0x13, 0x0c, 0x13, 0x16, 0x16, 0x0a, + 0x17, 0x09, 0x17, 0x11, 0x08, 0x0f, 0x12, 0x0c, 0x16, 0x0c, 0x12, 0x0b, + 0x11, 0x0f, 0x0f, 0x0e, 0x15, 0x12, 0x15, 0x09, 0x0c, 0x17, 0x11, 0x09, + 0x0a, 0x0c, 0x0d, 0x15, 0x0a, 0x0c, 0x08, 0x0a, 0x0d, 0x17, 0x13, 0x0d, + 0x0e, 0x0e, 0x12, 0x0d, 0x13, 0x0d, 0x10, 0x0c, 0x14, 0x17, 0x12, 0x12, + 0x12, 0x0f, 0x13, 0x16, 0x0f, 0x0c, 0x08, 0x11, 0x10, 0x0d, 0x0f, 0x13, + 0x12, 0x0f, 0x15, 0x08, 0x0e, 0x11, 0x0d, 0x15, 0x17, 0x08, 0x0a, 0x12, + 0x0d, 0x13, 0x17, 0x0a, 0x12, 0x11, 0x15, 0x0d, 0x09, 0x10, 0x0b, 0x11, + 0x15, 0x0b, 0x0a, 0x0e, 0x11, 0x11, 0x09, 0x0c, 0x09, 0x17, 0x0c, 0x0f, + 0x10, 0x11, 0x0d, 0x10, 0x12, 0x0f, 0x0b, 0x08, 0x0a, 0x0a, 0x0b, 0x15, + 0x14, 0x08, 0x0b, 0x15, 0x11, 0x0e, 0x0e, 0x0e, 0x12, 0x11, 0x14, 0x0c, + 0x0b, 0x16, 0x10, 0x0c, 0x15, 0x15, 0x14, 0x0e, 0x0f, 0x09, 0x16, 0x09, + 0x11, 0x0a, 0x09, 0x14, 0x0c, 0x0d, 0x12, 0x08, 0x0d, 0x15, 0x16, 0x16, + 0x0c, 0x0d, 0x0d, 0x17, 0x17, 0x0a, 0x0c, 0x0a, 0x08, 0x15, 0x0f, 0x16, + 0x12, 0x0c, 0x0c, 0x09, 0x0e, 0x0b, 0x0a, 0x08, 0x0d, 0x0c, 0x14, 0x12, + 0x11, 0x0e, 0x13, 0x16, 0x0c, 0x11, 0x15, 0x11, 0x16, 0x0a, 0x10, 0x15, + 0x0d, 0x14, 0x08, 0x0d, 0x11, 0x10, 0x0c, 0x0b, 0x14, 0x11, 0x0c, 0x0b, + 0x14, 0x0f, 0x0b, 0x0a, 0x13, 0x17, 0x15, 0x0c, 0x0e, 0x10, 0x0b, 0x13, + 0x09, 0x08, 0x0c, 0x08, 0x0b, 0x14, 0x16, 0x11, 0x11, 0x17, 0x17, 0x0b, + 0x0f, 0x0b, 0x0e, 0x0c, 0x14, 0x13, 0x0f, 0x11, 0x0a, 0x13, 0x14, 0x16, + 0x03, 0x00, 0x06, 0x02, 0x06, 0x02, 0x06, 0x00, 0x00, 0x05, 0x07, 0x05, + 0x01, 0x01, 0x06, 0x02, 0x04, 0x04, 0x03, 0x00, 0x05, 0x05, 0x06, 0x04, + 0x06, 0x00, 0x00, 0x07, 0x02, 0x05, 0x04, 0x06, 0x06, 0x02, 0x00, 0x05, + 0x05, 0x07, 0x05, 0x05, 0x04, 0x05, 0x03, 0x06, 0x06, 0x01, 0x00, 0x02, + 0x06, 0x04, 0x03, 0x04, 0x02, 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x04, + 0x07, 0x04, 0x03, 0x05, 0x07, 0x03, 0x03, 0x05, 0x03, 0x00, 0x02, 0x07, + 0x05, 0x06, 0x05, 0x04, 0x07, 0x06, 0x06, 0x06, 0x03, 0x01, 0x02, 0x05, + 0x03, 0x02, 0x06, 0x05, 0x04, 0x07, 0x01, 0x03, 0x04, 0x04, 0x00, 0x04, + 0x00, 0x04, 0x01, 0x03, 0x04, 0x04, 0x03, 0x02, 0x02, 0x01, 0x07, 0x02, + 0x07, 0x05, 0x00, 0x02, 0x07, 0x02, 0x00, 0x03, 0x05, 0x07, 0x00, 0x01, + 0x07, 0x02, 0x04, 0x04, 0x07, 0x05, 0x00, 0x07, 0x01, 0x02, 0x03, 0x06, + 0x06, 0x06, 0x01, 0x00, 0x07, 0x00, 0x03, 0x07, 0x06, 0x03, 0x02, 0x06, + 0x06, 0x03, 0x01, 0x04, 0x02, 0x02, 0x05, 0x02, 0x04, 0x02, 0x06, 0x03, + 0x00, 0x07, 0x03, 0x02, 0x01, 0x06, 0x01, 0x07, 0x05, 0x03, 0x00, 0x05, + 0x04, 0x03, 0x04, 0x03, 0x07, 0x07, 0x01, 0x05, 0x02, 0x03, 0x01, 0x05, + 0x05, 0x07, 0x00, 0x01, 0x02, 0x06, 0x05, 0x03, 0x05, 0x00, 0x05, 0x07, + 0x07, 0x06, 0x06, 0x04, 0x02, 0x07, 0x02, 0x06, 0x03, 0x06, 0x01, 0x03, + 0x06, 0x02, 0x01, 0x01, 0x06, 0x02, 0x06, 0x03, 0x02, 0x06, 0x05, 0x05, + 0x05, 0x02, 0x00, 0x03, 0x03, 0x05, 0x02, 0x02, 0x04, 0x01, 0x07, 0x06, + 0x01, 0x01, 0x04, 0x05, 0x00, 0x06, 0x00, 0x07, 0x01, 0x01, 0x00, 0x07, + 0x04, 0x07, 0x03, 0x07, 0x05, 0x00, 0x04, 0x03, 0x03, 0x04, 0x06, 0x07, + 0x01, 0x01, 0x02, 0x06, 0x03, 0x02, 0x05, 0x04, 0x04, 0x01, 0x01, 0x05, + 0x00, 0x02, 0x04, 0x01, 0x03, 0x04, 0x00, 0x07, 0x03, 0x03, 0x06, 0x01, + 0x04, 0x03, 0x05, 0x00, 0x07, 0x04, 0x00, 0x01, 0x05, 0x02, 0x07, 0x01, + 0x04, 0x04, 0x05, 0x01, 0x06, 0x07, 0x06, 0x06, 0x01, 0x02, 0x07, 0x05, +}; + +//*******************************************************************v********** +// +// The top right corner of the border. +// +//***************************************************************************** +static const uint8_t g_pui8TopRight[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 10, 0, + 26, 0, + + 34, + 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x15, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x44, 0x00, 0x00, + 0x46, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x4e, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5a, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x1d, 0x21, 0x1d, 0x1c, 0x1a, 0x1e, 0x14, 0x00, 0x00, 0x00, 0x13, 0x16, + 0x18, 0x18, 0x0c, 0x11, 0x1d, 0x20, 0x14, 0x00, 0x13, 0x0b, 0x18, 0x10, + 0x18, 0x14, 0x11, 0x11, 0x04, 0x00, 0x0a, 0x0c, 0x0e, 0x0a, 0x0e, 0x0a, + 0x14, 0x11, 0x07, 0x01, 0x15, 0x0a, 0x18, 0x18, 0x0a, 0x12, 0x15, 0x0e, + 0x0f, 0x06, 0x0c, 0x0a, 0x0a, 0x16, 0x0c, 0x0c, 0x0e, 0x0c, 0x14, 0x02, + 0x12, 0x15, 0x16, 0x10, 0x0b, 0x0d, 0x0c, 0x15, 0x19, 0x04, 0x0d, 0x16, + 0x15, 0x0a, 0x0a, 0x15, 0x19, 0x0b, 0x0c, 0x08, 0x16, 0x0f, 0x11, 0x19, + 0x0d, 0x12, 0x0d, 0x0f, 0x13, 0x08, 0x15, 0x0c, 0x0e, 0x15, 0x19, 0x0c, + 0x13, 0x18, 0x15, 0x02, 0x19, 0x13, 0x10, 0x0e, 0x15, 0x12, 0x0c, 0x11, + 0x13, 0x07, 0x19, 0x0e, 0x12, 0x17, 0x14, 0x0a, 0x13, 0x0b, 0x17, 0x06, + 0x0a, 0x13, 0x16, 0x10, 0x0c, 0x13, 0x17, 0x0f, 0x0a, 0x07, 0x16, 0x0e, + 0x0f, 0x18, 0x11, 0x0e, 0x10, 0x12, 0x0c, 0x09, 0x14, 0x13, 0x0c, 0x13, + 0x0d, 0x0e, 0x0b, 0x0f, 0x0e, 0x05, 0x17, 0x10, 0x16, 0x12, 0x0f, 0x14, + 0x19, 0x10, 0x0c, 0x06, 0x0b, 0x15, 0x0c, 0x13, 0x17, 0x12, 0x12, 0x0a, + 0x11, 0x07, 0x16, 0x0c, 0x0e, 0x16, 0x0d, 0x0f, 0x0f, 0x0c, 0x13, 0x02, + 0x14, 0x0b, 0x12, 0x0f, 0x0e, 0x0b, 0x11, 0x0f, 0x19, 0x07, 0x0e, 0x10, + 0x16, 0x0f, 0x0f, 0x17, 0x12, 0x0e, 0x0b, 0x07, 0x14, 0x13, 0x0d, 0x0b, + 0x0b, 0x10, 0x16, 0x0d, 0x11, 0x02, 0x09, 0x0a, 0x14, 0x11, 0x12, 0x12, + 0x14, 0x0b, 0x18, 0x04, 0x01, 0x03, 0x06, 0x11, 0x19, 0x18, 0x10, 0x14, + 0x17, 0x08, 0x00, 0x00, 0x14, 0x22, 0x0c, 0x15, 0x15, 0x17, 0x0e, 0x02, + 0x00, 0x00, 0x00, 0x1b, 0x13, 0x14, 0x11, 0x0a, 0x15, 0x04, 0x00, 0x00, + 0x00, 0x12, 0x1f, 0x11, 0x0c, 0x0a, 0x13, 0x04, +}; + +//***************************************************************************** +// +// The left side of the border. +// +//***************************************************************************** +static const uint8_t g_pui8Left[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 6, 0, + 204, 0, + + 39, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x15, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x40, 0x00, 0x00, + 0x42, 0x00, 0x00, + 0x44, 0x00, 0x00, + 0x46, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x4a, 0x00, 0x00, + 0x4c, 0x00, 0x00, + 0x4e, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x52, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5a, 0x00, 0x00, + 0x5c, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x24, 0x15, 0x12, 0x0f, 0x16, 0x04, 0x25, 0x09, 0x0e, 0x13, 0x0c, 0x03, + 0x1d, 0x15, 0x0e, 0x0a, 0x17, 0x00, 0x22, 0x0c, 0x0f, 0x0a, 0x0d, 0x06, + 0x27, 0x14, 0x09, 0x0e, 0x09, 0x03, 0x20, 0x16, 0x0b, 0x0a, 0x0e, 0x01, + 0x23, 0x0c, 0x0c, 0x0a, 0x17, 0x04, 0x21, 0x0d, 0x0e, 0x08, 0x0f, 0x03, + 0x19, 0x0a, 0x13, 0x11, 0x0d, 0x00, 0x1d, 0x0c, 0x15, 0x0e, 0x12, 0x07, + 0x25, 0x0a, 0x15, 0x09, 0x0c, 0x02, 0x1c, 0x08, 0x10, 0x10, 0x0b, 0x04, + 0x19, 0x15, 0x15, 0x10, 0x16, 0x02, 0x27, 0x17, 0x0e, 0x12, 0x10, 0x05, + 0x23, 0x16, 0x17, 0x10, 0x0c, 0x05, 0x1f, 0x0a, 0x14, 0x0d, 0x0b, 0x00, + 0x21, 0x0f, 0x09, 0x0a, 0x08, 0x02, 0x22, 0x09, 0x0a, 0x0f, 0x12, 0x00, + 0x24, 0x11, 0x08, 0x0a, 0x0b, 0x04, 0x26, 0x16, 0x0e, 0x16, 0x0f, 0x05, + 0x20, 0x16, 0x15, 0x0c, 0x0b, 0x00, 0x1d, 0x14, 0x11, 0x0f, 0x16, 0x04, + 0x25, 0x10, 0x13, 0x17, 0x08, 0x03, 0x18, 0x14, 0x17, 0x08, 0x17, 0x01, + 0x21, 0x16, 0x0a, 0x17, 0x14, 0x04, 0x22, 0x0d, 0x0f, 0x10, 0x12, 0x05, + 0x22, 0x08, 0x0f, 0x0c, 0x10, 0x03, 0x26, 0x0d, 0x17, 0x11, 0x0d, 0x07, + 0x27, 0x0d, 0x14, 0x17, 0x0e, 0x05, 0x1a, 0x17, 0x11, 0x0c, 0x16, 0x03, + 0x26, 0x11, 0x14, 0x0d, 0x0a, 0x03, 0x18, 0x14, 0x0e, 0x0f, 0x08, 0x07, + 0x26, 0x16, 0x0b, 0x16, 0x10, 0x04, 0x26, 0x10, 0x16, 0x12, 0x10, 0x02, + 0x1e, 0x13, 0x0c, 0x17, 0x17, 0x01, 0x1e, 0x16, 0x14, 0x0a, 0x0b, 0x07, + 0x21, 0x0b, 0x13, 0x17, 0x13, 0x06, 0x26, 0x12, 0x13, 0x0a, 0x10, 0x02, + 0x22, 0x0e, 0x15, 0x11, 0x08, 0x02, 0x26, 0x0e, 0x08, 0x0a, 0x0e, 0x00, + 0x1c, 0x15, 0x16, 0x09, 0x08, 0x01, 0x18, 0x11, 0x0d, 0x13, 0x10, 0x00, + 0x20, 0x0f, 0x13, 0x0b, 0x11, 0x02, 0x1f, 0x0c, 0x12, 0x0c, 0x15, 0x05, + 0x22, 0x13, 0x0a, 0x12, 0x16, 0x04, 0x23, 0x0a, 0x0e, 0x11, 0x0c, 0x03, + 0x24, 0x0c, 0x08, 0x09, 0x17, 0x04, 0x1b, 0x0f, 0x08, 0x17, 0x13, 0x05, + 0x1b, 0x0b, 0x16, 0x16, 0x10, 0x06, 0x22, 0x0a, 0x10, 0x14, 0x15, 0x03, + 0x1d, 0x10, 0x11, 0x14, 0x0a, 0x06, 0x1b, 0x16, 0x09, 0x0b, 0x08, 0x00, + 0x25, 0x0c, 0x11, 0x15, 0x0b, 0x02, 0x20, 0x0f, 0x10, 0x0e, 0x0d, 0x00, + 0x1a, 0x17, 0x0a, 0x13, 0x14, 0x00, 0x19, 0x0a, 0x11, 0x12, 0x16, 0x05, + 0x20, 0x0a, 0x12, 0x11, 0x0e, 0x05, 0x23, 0x0b, 0x17, 0x0c, 0x09, 0x01, + 0x21, 0x11, 0x12, 0x09, 0x08, 0x00, 0x1a, 0x0b, 0x08, 0x0c, 0x16, 0x06, + 0x1d, 0x17, 0x16, 0x16, 0x12, 0x06, 0x22, 0x0a, 0x17, 0x0c, 0x14, 0x02, + 0x18, 0x0f, 0x11, 0x08, 0x14, 0x05, 0x1b, 0x0e, 0x0c, 0x15, 0x10, 0x02, + 0x25, 0x12, 0x0f, 0x15, 0x17, 0x03, 0x22, 0x0c, 0x0d, 0x10, 0x0a, 0x00, + 0x1d, 0x14, 0x0a, 0x0c, 0x09, 0x07, 0x22, 0x0a, 0x0e, 0x0c, 0x0a, 0x01, + 0x26, 0x0d, 0x11, 0x0b, 0x0a, 0x00, 0x20, 0x08, 0x13, 0x17, 0x16, 0x05, + 0x1e, 0x10, 0x17, 0x13, 0x08, 0x00, 0x23, 0x0e, 0x16, 0x16, 0x13, 0x00, + 0x25, 0x0d, 0x0a, 0x0b, 0x11, 0x02, 0x1e, 0x10, 0x12, 0x08, 0x14, 0x06, + 0x19, 0x0c, 0x16, 0x15, 0x0c, 0x06, 0x20, 0x12, 0x0c, 0x0f, 0x0e, 0x02, + 0x21, 0x0a, 0x14, 0x10, 0x08, 0x03, 0x21, 0x15, 0x15, 0x14, 0x09, 0x03, + 0x19, 0x10, 0x17, 0x14, 0x10, 0x06, 0x21, 0x12, 0x08, 0x10, 0x0f, 0x02, + 0x1c, 0x08, 0x17, 0x11, 0x10, 0x02, 0x27, 0x0a, 0x0f, 0x13, 0x12, 0x04, + 0x1a, 0x0c, 0x0d, 0x17, 0x08, 0x03, 0x1e, 0x09, 0x17, 0x0e, 0x16, 0x03, + 0x1b, 0x0f, 0x09, 0x0b, 0x17, 0x04, 0x20, 0x0c, 0x11, 0x10, 0x15, 0x01, + 0x25, 0x15, 0x0c, 0x0d, 0x10, 0x07, 0x25, 0x12, 0x0a, 0x0b, 0x12, 0x01, + 0x21, 0x09, 0x0d, 0x11, 0x10, 0x01, 0x18, 0x13, 0x12, 0x09, 0x17, 0x05, + 0x23, 0x10, 0x17, 0x0d, 0x08, 0x06, 0x1f, 0x16, 0x12, 0x13, 0x0b, 0x01, + 0x22, 0x08, 0x15, 0x15, 0x0b, 0x04, 0x18, 0x15, 0x11, 0x0d, 0x0e, 0x01, + 0x20, 0x0f, 0x15, 0x0b, 0x11, 0x06, 0x26, 0x0c, 0x0d, 0x15, 0x11, 0x03, + 0x22, 0x08, 0x0c, 0x0c, 0x13, 0x03, 0x1f, 0x0e, 0x10, 0x0c, 0x0b, 0x06, + 0x24, 0x0b, 0x12, 0x0e, 0x10, 0x00, 0x20, 0x09, 0x10, 0x0e, 0x0d, 0x01, + 0x1c, 0x0b, 0x0e, 0x11, 0x09, 0x00, 0x27, 0x13, 0x09, 0x0c, 0x08, 0x06, + 0x23, 0x0f, 0x0b, 0x0c, 0x14, 0x03, 0x19, 0x11, 0x11, 0x13, 0x17, 0x01, + 0x24, 0x10, 0x0c, 0x0d, 0x17, 0x04, 0x20, 0x0b, 0x15, 0x17, 0x15, 0x07, + 0x27, 0x15, 0x12, 0x09, 0x09, 0x05, 0x26, 0x15, 0x0a, 0x0a, 0x09, 0x07, + 0x20, 0x0a, 0x10, 0x0a, 0x16, 0x04, 0x1d, 0x13, 0x09, 0x11, 0x08, 0x00, + 0x1b, 0x10, 0x0c, 0x08, 0x10, 0x00, 0x27, 0x0f, 0x17, 0x12, 0x11, 0x00, + 0x1c, 0x0f, 0x15, 0x0f, 0x11, 0x07, 0x1e, 0x0a, 0x09, 0x17, 0x0c, 0x07, + 0x1f, 0x12, 0x12, 0x10, 0x0c, 0x05, 0x21, 0x0f, 0x0c, 0x15, 0x10, 0x06, + 0x27, 0x10, 0x0c, 0x16, 0x0a, 0x06, 0x26, 0x0f, 0x0d, 0x14, 0x16, 0x07, + 0x23, 0x0d, 0x09, 0x15, 0x0c, 0x03, 0x25, 0x13, 0x09, 0x0f, 0x0c, 0x02, + 0x1b, 0x15, 0x14, 0x10, 0x12, 0x02, 0x1c, 0x12, 0x15, 0x11, 0x10, 0x07, + 0x1e, 0x0f, 0x0f, 0x14, 0x0b, 0x02, 0x23, 0x17, 0x13, 0x15, 0x14, 0x07, + 0x1c, 0x11, 0x13, 0x0d, 0x09, 0x00, 0x22, 0x0c, 0x15, 0x0e, 0x14, 0x04, + 0x24, 0x09, 0x0a, 0x11, 0x12, 0x05, 0x21, 0x09, 0x0a, 0x08, 0x15, 0x02, + 0x1e, 0x11, 0x0d, 0x09, 0x0e, 0x00, 0x19, 0x12, 0x13, 0x15, 0x17, 0x06, + 0x25, 0x12, 0x09, 0x13, 0x09, 0x07, 0x1b, 0x15, 0x17, 0x0d, 0x0f, 0x05, + 0x18, 0x08, 0x14, 0x0a, 0x09, 0x04, 0x20, 0x10, 0x0b, 0x15, 0x12, 0x05, + 0x27, 0x13, 0x0c, 0x12, 0x11, 0x02, 0x1f, 0x0f, 0x17, 0x10, 0x0a, 0x00, + 0x1f, 0x0d, 0x15, 0x0f, 0x13, 0x02, 0x19, 0x14, 0x0d, 0x15, 0x17, 0x03, + 0x1f, 0x0f, 0x16, 0x12, 0x0d, 0x04, 0x1c, 0x0c, 0x0c, 0x11, 0x17, 0x07, + 0x26, 0x0e, 0x0d, 0x15, 0x17, 0x03, 0x25, 0x0f, 0x15, 0x13, 0x16, 0x04, + 0x27, 0x08, 0x0d, 0x0c, 0x15, 0x02, 0x23, 0x0d, 0x14, 0x12, 0x08, 0x01, + 0x1b, 0x0d, 0x0e, 0x10, 0x17, 0x03, 0x1e, 0x15, 0x15, 0x13, 0x13, 0x06, + 0x1b, 0x11, 0x0c, 0x08, 0x0c, 0x01, 0x21, 0x0c, 0x0a, 0x17, 0x10, 0x00, + 0x1b, 0x0c, 0x0e, 0x08, 0x17, 0x03, 0x1a, 0x0a, 0x13, 0x11, 0x12, 0x05, + 0x27, 0x08, 0x10, 0x15, 0x14, 0x02, 0x22, 0x17, 0x15, 0x17, 0x17, 0x01, + 0x19, 0x11, 0x0e, 0x0c, 0x10, 0x07, 0x1d, 0x14, 0x0b, 0x13, 0x15, 0x01, + 0x1a, 0x17, 0x0d, 0x16, 0x11, 0x07, 0x21, 0x11, 0x08, 0x0a, 0x0e, 0x06, + 0x1e, 0x09, 0x14, 0x0c, 0x08, 0x06, 0x1e, 0x09, 0x0e, 0x15, 0x0e, 0x07, + 0x24, 0x14, 0x13, 0x08, 0x0f, 0x04, 0x1a, 0x12, 0x0f, 0x10, 0x10, 0x00, + 0x20, 0x09, 0x12, 0x11, 0x0b, 0x00, 0x1e, 0x12, 0x09, 0x0b, 0x17, 0x00, + 0x27, 0x0d, 0x0b, 0x0d, 0x0b, 0x05, 0x1c, 0x17, 0x0e, 0x17, 0x17, 0x07, + 0x1f, 0x0a, 0x10, 0x17, 0x12, 0x00, 0x18, 0x0b, 0x09, 0x12, 0x14, 0x02, + 0x23, 0x0a, 0x17, 0x14, 0x0d, 0x07, 0x26, 0x0d, 0x0d, 0x09, 0x13, 0x04, + 0x23, 0x17, 0x0f, 0x0a, 0x16, 0x03, 0x18, 0x0e, 0x11, 0x10, 0x0d, 0x02, + 0x20, 0x0e, 0x10, 0x12, 0x08, 0x02, 0x18, 0x13, 0x0f, 0x08, 0x10, 0x06, + 0x27, 0x0e, 0x0a, 0x0c, 0x0f, 0x06, 0x24, 0x0b, 0x14, 0x0c, 0x0d, 0x05, + 0x23, 0x0e, 0x09, 0x0d, 0x16, 0x03, 0x22, 0x0f, 0x15, 0x0a, 0x0a, 0x06, + 0x1e, 0x0a, 0x11, 0x15, 0x0b, 0x00, 0x23, 0x0a, 0x0f, 0x15, 0x0e, 0x07, + 0x23, 0x0b, 0x0b, 0x10, 0x0f, 0x04, 0x1b, 0x0a, 0x17, 0x0d, 0x0f, 0x07, + 0x24, 0x09, 0x0e, 0x12, 0x0b, 0x04, 0x20, 0x12, 0x14, 0x09, 0x10, 0x07, + 0x1a, 0x0b, 0x09, 0x12, 0x09, 0x04, 0x22, 0x14, 0x13, 0x15, 0x0d, 0x01, + 0x1e, 0x11, 0x0d, 0x0e, 0x17, 0x06, 0x1c, 0x13, 0x16, 0x13, 0x0e, 0x01, + 0x1c, 0x16, 0x15, 0x08, 0x17, 0x02, 0x27, 0x0a, 0x11, 0x09, 0x15, 0x05, + 0x21, 0x0f, 0x0f, 0x0d, 0x0d, 0x06, 0x1f, 0x14, 0x0e, 0x14, 0x0a, 0x02, + 0x21, 0x0f, 0x09, 0x10, 0x0a, 0x03, 0x22, 0x0f, 0x0d, 0x10, 0x0f, 0x02, + 0x25, 0x0f, 0x10, 0x0f, 0x11, 0x02, 0x1a, 0x0b, 0x15, 0x12, 0x10, 0x01, + 0x1f, 0x08, 0x16, 0x15, 0x15, 0x00, 0x1b, 0x0e, 0x10, 0x0d, 0x17, 0x05, + 0x24, 0x11, 0x0a, 0x0a, 0x0a, 0x05, 0x20, 0x17, 0x0a, 0x08, 0x0f, 0x05, + 0x1e, 0x11, 0x17, 0x0b, 0x0b, 0x04, 0x1d, 0x12, 0x10, 0x0c, 0x10, 0x02, + 0x1d, 0x14, 0x14, 0x15, 0x09, 0x05, 0x20, 0x16, 0x0d, 0x13, 0x08, 0x03, + 0x1d, 0x11, 0x0f, 0x0f, 0x11, 0x07, 0x1b, 0x17, 0x10, 0x0a, 0x0b, 0x05, +}; + +//***************************************************************************** +// +// The right side of the border. +// +//***************************************************************************** +static const uint8_t g_pui8Right[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 6, 0, + 204, 0, + + 39, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x15, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x40, 0x00, 0x00, + 0x42, 0x00, 0x00, + 0x44, 0x00, 0x00, + 0x46, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x4a, 0x00, 0x00, + 0x4c, 0x00, 0x00, + 0x4e, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x52, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5a, 0x00, 0x00, + 0x5c, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x1f, 0x10, 0x15, 0x0b, 0x0f, 0x01, 0x20, 0x0e, 0x09, 0x16, 0x08, 0x07, + 0x23, 0x0a, 0x12, 0x0f, 0x08, 0x07, 0x20, 0x12, 0x11, 0x17, 0x12, 0x02, + 0x1d, 0x0d, 0x14, 0x0f, 0x0e, 0x02, 0x25, 0x16, 0x16, 0x12, 0x0a, 0x02, + 0x26, 0x12, 0x13, 0x08, 0x10, 0x06, 0x27, 0x0c, 0x17, 0x11, 0x13, 0x00, + 0x20, 0x0b, 0x12, 0x09, 0x0b, 0x02, 0x1d, 0x10, 0x13, 0x0a, 0x08, 0x00, + 0x1f, 0x15, 0x08, 0x0d, 0x10, 0x01, 0x22, 0x0f, 0x14, 0x0e, 0x0f, 0x02, + 0x1b, 0x0e, 0x11, 0x0b, 0x08, 0x02, 0x1b, 0x10, 0x11, 0x16, 0x11, 0x06, + 0x1b, 0x17, 0x0e, 0x17, 0x09, 0x03, 0x19, 0x11, 0x0c, 0x09, 0x16, 0x06, + 0x1b, 0x11, 0x0b, 0x08, 0x08, 0x05, 0x1e, 0x0c, 0x09, 0x08, 0x0f, 0x00, + 0x1d, 0x13, 0x12, 0x17, 0x11, 0x02, 0x24, 0x15, 0x0b, 0x0a, 0x14, 0x02, + 0x20, 0x15, 0x17, 0x14, 0x16, 0x07, 0x21, 0x0a, 0x10, 0x14, 0x0a, 0x04, + 0x1f, 0x10, 0x15, 0x11, 0x10, 0x02, 0x23, 0x16, 0x08, 0x0d, 0x15, 0x05, + 0x21, 0x11, 0x0f, 0x15, 0x13, 0x01, 0x1b, 0x0c, 0x08, 0x0a, 0x09, 0x07, + 0x18, 0x12, 0x08, 0x10, 0x0f, 0x01, 0x19, 0x17, 0x14, 0x17, 0x10, 0x02, + 0x1c, 0x0c, 0x0b, 0x0d, 0x11, 0x00, 0x27, 0x0b, 0x11, 0x0e, 0x08, 0x02, + 0x21, 0x0c, 0x11, 0x11, 0x0e, 0x05, 0x20, 0x0f, 0x0d, 0x11, 0x17, 0x06, + 0x24, 0x09, 0x14, 0x10, 0x08, 0x02, 0x25, 0x0d, 0x11, 0x08, 0x12, 0x01, + 0x19, 0x11, 0x0d, 0x12, 0x08, 0x03, 0x18, 0x11, 0x12, 0x12, 0x0b, 0x00, + 0x1d, 0x14, 0x10, 0x12, 0x0d, 0x04, 0x1f, 0x0a, 0x12, 0x0b, 0x13, 0x05, + 0x20, 0x11, 0x08, 0x0a, 0x11, 0x05, 0x1c, 0x12, 0x0d, 0x12, 0x0d, 0x02, + 0x19, 0x0d, 0x16, 0x14, 0x17, 0x01, 0x25, 0x0d, 0x16, 0x0e, 0x17, 0x01, + 0x27, 0x0f, 0x0e, 0x11, 0x12, 0x00, 0x1c, 0x0b, 0x12, 0x0d, 0x0d, 0x02, + 0x18, 0x12, 0x17, 0x0d, 0x0d, 0x02, 0x23, 0x0e, 0x12, 0x11, 0x0a, 0x05, + 0x24, 0x08, 0x17, 0x12, 0x0f, 0x07, 0x25, 0x0e, 0x0e, 0x0c, 0x08, 0x00, + 0x1d, 0x0c, 0x0c, 0x08, 0x12, 0x05, 0x1c, 0x13, 0x0c, 0x0b, 0x09, 0x04, + 0x20, 0x14, 0x08, 0x0b, 0x0e, 0x01, 0x25, 0x0a, 0x0c, 0x15, 0x14, 0x05, + 0x25, 0x12, 0x09, 0x0b, 0x16, 0x00, 0x1c, 0x0c, 0x0e, 0x11, 0x0c, 0x00, + 0x1b, 0x10, 0x14, 0x10, 0x13, 0x06, 0x1a, 0x0c, 0x11, 0x0a, 0x0f, 0x07, + 0x1e, 0x0d, 0x09, 0x12, 0x0b, 0x07, 0x1d, 0x08, 0x10, 0x0f, 0x0b, 0x03, + 0x20, 0x10, 0x13, 0x17, 0x09, 0x07, 0x18, 0x0d, 0x0f, 0x14, 0x15, 0x01, + 0x21, 0x17, 0x0f, 0x0b, 0x0a, 0x07, 0x1a, 0x10, 0x0c, 0x0c, 0x0a, 0x03, + 0x1a, 0x10, 0x10, 0x13, 0x17, 0x05, 0x1a, 0x10, 0x0c, 0x15, 0x0f, 0x02, + 0x24, 0x10, 0x13, 0x0b, 0x0c, 0x04, 0x1f, 0x16, 0x10, 0x16, 0x09, 0x05, + 0x25, 0x0c, 0x0c, 0x0a, 0x11, 0x03, 0x21, 0x13, 0x17, 0x0a, 0x0f, 0x07, + 0x25, 0x11, 0x0e, 0x0a, 0x0e, 0x07, 0x1f, 0x0b, 0x0e, 0x0b, 0x0f, 0x05, + 0x23, 0x16, 0x11, 0x0c, 0x15, 0x05, 0x18, 0x13, 0x08, 0x0c, 0x15, 0x04, + 0x23, 0x0f, 0x0d, 0x12, 0x11, 0x06, 0x21, 0x0f, 0x0e, 0x17, 0x11, 0x06, + 0x26, 0x09, 0x08, 0x0d, 0x0c, 0x04, 0x18, 0x08, 0x0e, 0x12, 0x0d, 0x02, + 0x1d, 0x0d, 0x17, 0x0e, 0x11, 0x06, 0x27, 0x0c, 0x0d, 0x0d, 0x17, 0x07, + 0x19, 0x10, 0x0e, 0x0f, 0x0f, 0x00, 0x1d, 0x0e, 0x09, 0x0d, 0x13, 0x03, + 0x26, 0x13, 0x0f, 0x0d, 0x0d, 0x06, 0x21, 0x13, 0x09, 0x11, 0x09, 0x05, + 0x1e, 0x09, 0x08, 0x14, 0x0e, 0x07, 0x23, 0x0f, 0x0f, 0x09, 0x17, 0x07, + 0x1a, 0x0c, 0x0d, 0x0b, 0x12, 0x00, 0x22, 0x10, 0x14, 0x09, 0x15, 0x01, + 0x26, 0x0f, 0x15, 0x08, 0x08, 0x07, 0x23, 0x0f, 0x08, 0x13, 0x0c, 0x03, + 0x22, 0x17, 0x16, 0x09, 0x09, 0x07, 0x19, 0x0b, 0x0b, 0x0e, 0x0f, 0x07, + 0x1f, 0x09, 0x0f, 0x0b, 0x0b, 0x02, 0x1e, 0x09, 0x14, 0x0c, 0x09, 0x06, + 0x1b, 0x14, 0x0d, 0x0c, 0x10, 0x04, 0x22, 0x0b, 0x10, 0x11, 0x0d, 0x05, + 0x1f, 0x0e, 0x15, 0x13, 0x14, 0x02, 0x21, 0x0b, 0x0d, 0x08, 0x0f, 0x04, + 0x1e, 0x15, 0x12, 0x0a, 0x09, 0x05, 0x18, 0x0d, 0x10, 0x0d, 0x11, 0x00, + 0x26, 0x0c, 0x0c, 0x0f, 0x15, 0x04, 0x19, 0x0d, 0x17, 0x17, 0x09, 0x05, + 0x1b, 0x12, 0x17, 0x11, 0x13, 0x03, 0x1a, 0x09, 0x0d, 0x14, 0x0c, 0x03, + 0x1f, 0x0c, 0x14, 0x17, 0x11, 0x03, 0x18, 0x10, 0x12, 0x0c, 0x08, 0x04, + 0x25, 0x0a, 0x15, 0x15, 0x09, 0x07, 0x20, 0x0d, 0x11, 0x10, 0x16, 0x02, + 0x18, 0x08, 0x0e, 0x0d, 0x14, 0x05, 0x24, 0x0c, 0x17, 0x11, 0x0c, 0x04, + 0x27, 0x0d, 0x09, 0x11, 0x11, 0x01, 0x19, 0x0f, 0x0c, 0x17, 0x0c, 0x03, + 0x26, 0x15, 0x13, 0x10, 0x0e, 0x05, 0x25, 0x0e, 0x12, 0x0c, 0x13, 0x03, + 0x27, 0x10, 0x14, 0x16, 0x09, 0x00, 0x1f, 0x08, 0x0d, 0x11, 0x12, 0x07, + 0x23, 0x14, 0x0f, 0x17, 0x14, 0x05, 0x1e, 0x13, 0x11, 0x09, 0x0c, 0x07, + 0x23, 0x09, 0x0d, 0x0e, 0x0e, 0x00, 0x26, 0x0d, 0x11, 0x12, 0x0c, 0x05, + 0x23, 0x13, 0x14, 0x08, 0x0c, 0x03, 0x18, 0x08, 0x0b, 0x0f, 0x08, 0x00, + 0x1b, 0x0e, 0x13, 0x14, 0x10, 0x07, 0x23, 0x0c, 0x09, 0x09, 0x13, 0x04, + 0x1b, 0x11, 0x15, 0x15, 0x0c, 0x01, 0x20, 0x17, 0x15, 0x0c, 0x08, 0x01, + 0x23, 0x08, 0x0a, 0x17, 0x10, 0x01, 0x27, 0x13, 0x11, 0x13, 0x0f, 0x00, + 0x22, 0x0b, 0x0d, 0x14, 0x0d, 0x00, 0x1c, 0x10, 0x12, 0x0a, 0x0d, 0x07, + 0x1c, 0x16, 0x16, 0x0a, 0x0a, 0x07, 0x1d, 0x16, 0x08, 0x10, 0x16, 0x04, + 0x23, 0x15, 0x0b, 0x0c, 0x10, 0x05, 0x1e, 0x0b, 0x16, 0x14, 0x08, 0x01, + 0x25, 0x0d, 0x14, 0x0f, 0x0f, 0x01, 0x1e, 0x14, 0x08, 0x0d, 0x17, 0x01, + 0x1c, 0x0c, 0x09, 0x0c, 0x15, 0x07, 0x25, 0x10, 0x15, 0x08, 0x15, 0x03, + 0x23, 0x0c, 0x12, 0x12, 0x08, 0x05, 0x26, 0x16, 0x08, 0x12, 0x0d, 0x03, + 0x25, 0x14, 0x0c, 0x15, 0x0a, 0x01, 0x18, 0x0f, 0x0f, 0x0a, 0x14, 0x02, + 0x1a, 0x11, 0x15, 0x17, 0x12, 0x05, 0x1e, 0x0d, 0x17, 0x08, 0x08, 0x00, + 0x23, 0x16, 0x16, 0x14, 0x11, 0x02, 0x1b, 0x0e, 0x08, 0x0f, 0x0b, 0x01, + 0x22, 0x0c, 0x12, 0x0a, 0x0e, 0x03, 0x1f, 0x11, 0x17, 0x0d, 0x10, 0x04, + 0x18, 0x17, 0x17, 0x17, 0x08, 0x07, 0x18, 0x14, 0x16, 0x16, 0x10, 0x03, + 0x1a, 0x13, 0x16, 0x0b, 0x0b, 0x01, 0x1e, 0x16, 0x0e, 0x08, 0x08, 0x06, + 0x1f, 0x10, 0x0e, 0x0e, 0x15, 0x07, 0x18, 0x15, 0x16, 0x08, 0x15, 0x07, + 0x27, 0x15, 0x13, 0x16, 0x13, 0x01, 0x1d, 0x16, 0x17, 0x0b, 0x09, 0x01, + 0x1e, 0x0f, 0x09, 0x14, 0x10, 0x01, 0x22, 0x17, 0x12, 0x09, 0x0e, 0x04, + 0x18, 0x0f, 0x0e, 0x17, 0x0f, 0x01, 0x26, 0x0f, 0x09, 0x12, 0x0e, 0x06, + 0x25, 0x13, 0x13, 0x15, 0x17, 0x06, 0x18, 0x0d, 0x0d, 0x0a, 0x0a, 0x06, + 0x1c, 0x15, 0x15, 0x17, 0x16, 0x02, 0x20, 0x17, 0x14, 0x16, 0x16, 0x01, + 0x1a, 0x15, 0x13, 0x0c, 0x0f, 0x00, 0x19, 0x0d, 0x15, 0x15, 0x0a, 0x06, + 0x22, 0x0b, 0x0b, 0x08, 0x0d, 0x03, 0x25, 0x12, 0x0b, 0x13, 0x12, 0x00, + 0x18, 0x0b, 0x08, 0x14, 0x09, 0x07, 0x18, 0x0c, 0x14, 0x13, 0x10, 0x02, + 0x25, 0x12, 0x11, 0x13, 0x10, 0x06, 0x20, 0x0b, 0x08, 0x14, 0x0b, 0x02, + 0x1a, 0x09, 0x08, 0x0d, 0x14, 0x05, 0x1f, 0x14, 0x16, 0x10, 0x11, 0x00, + 0x1f, 0x11, 0x0d, 0x0c, 0x0d, 0x06, 0x21, 0x0a, 0x10, 0x0a, 0x16, 0x00, + 0x27, 0x0e, 0x0b, 0x17, 0x0a, 0x03, 0x1d, 0x0c, 0x10, 0x0e, 0x12, 0x02, + 0x19, 0x09, 0x0a, 0x08, 0x12, 0x05, 0x19, 0x09, 0x0c, 0x0e, 0x0e, 0x04, + 0x1b, 0x17, 0x14, 0x14, 0x0a, 0x05, 0x24, 0x09, 0x08, 0x08, 0x09, 0x01, + 0x20, 0x0e, 0x10, 0x08, 0x14, 0x01, 0x1d, 0x16, 0x0c, 0x10, 0x17, 0x07, + 0x1b, 0x08, 0x09, 0x0f, 0x0e, 0x03, 0x18, 0x12, 0x0f, 0x14, 0x0e, 0x04, + 0x1f, 0x0b, 0x13, 0x0f, 0x0c, 0x06, 0x23, 0x14, 0x0b, 0x0c, 0x15, 0x00, + 0x1f, 0x0b, 0x16, 0x14, 0x13, 0x07, 0x23, 0x16, 0x16, 0x14, 0x0e, 0x02, + 0x1c, 0x0f, 0x17, 0x13, 0x0b, 0x03, 0x1d, 0x12, 0x12, 0x09, 0x0a, 0x07, + 0x26, 0x16, 0x14, 0x09, 0x0a, 0x05, 0x19, 0x11, 0x15, 0x08, 0x0d, 0x04, + 0x26, 0x08, 0x0f, 0x15, 0x15, 0x07, 0x1a, 0x09, 0x0d, 0x0a, 0x14, 0x04, + 0x21, 0x0a, 0x0c, 0x0b, 0x0b, 0x03, 0x1b, 0x09, 0x0d, 0x17, 0x0a, 0x03, + 0x22, 0x0c, 0x09, 0x0f, 0x0c, 0x03, 0x18, 0x0b, 0x0f, 0x10, 0x08, 0x02, + 0x1e, 0x0b, 0x0d, 0x14, 0x0d, 0x01, 0x1d, 0x16, 0x0c, 0x11, 0x0a, 0x03, + 0x18, 0x0e, 0x10, 0x0d, 0x0e, 0x05, 0x25, 0x08, 0x17, 0x16, 0x10, 0x02, + 0x1d, 0x10, 0x10, 0x14, 0x09, 0x04, 0x19, 0x10, 0x14, 0x0e, 0x0c, 0x00, +}; + +//***************************************************************************** +// +// The bottom left corner of the border. +// +//***************************************************************************** +static const uint8_t g_pui8BottomLeft[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 10, 0, + 10, 0, + + 33, + 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, + 0x10, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x42, 0x00, 0x00, + 0x4a, 0x00, 0x00, + 0x4c, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x52, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5c, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x1d, 0x11, 0x0e, 0x0b, 0x15, 0x07, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x0b, + 0x13, 0x0d, 0x09, 0x14, 0x03, 0x00, 0x00, 0x00, 0x18, 0x11, 0x12, 0x0f, + 0x0c, 0x13, 0x06, 0x01, 0x00, 0x00, 0x20, 0x12, 0x0c, 0x0e, 0x09, 0x16, + 0x17, 0x1b, 0x1f, 0x16, 0x19, 0x0d, 0x16, 0x15, 0x0f, 0x09, 0x09, 0x0d, + 0x09, 0x1e, 0x1b, 0x0a, 0x12, 0x16, 0x0e, 0x10, 0x0b, 0x0e, 0x11, 0x10, + 0x14, 0x21, 0x13, 0x11, 0x0d, 0x14, 0x0f, 0x0a, 0x09, 0x0f, 0x00, 0x1a, + 0x0e, 0x08, 0x15, 0x13, 0x0f, 0x11, 0x08, 0x16, 0x00, 0x14, 0x03, 0x02, + 0x0b, 0x0f, 0x09, 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, + 0x05, 0x06, 0x07, 0x04, +}; + +//***************************************************************************** +// +// The bottom side of the border. +// +//***************************************************************************** +static const uint8_t g_pui8Bottom[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 44, 1, + 6, 0, + + 39, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x15, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x40, 0x00, 0x00, + 0x42, 0x00, 0x00, + 0x44, 0x00, 0x00, + 0x46, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x4a, 0x00, 0x00, + 0x4c, 0x00, 0x00, + 0x4e, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x52, 0x00, 0x00, + 0x54, 0x00, 0x00, + 0x56, 0x00, 0x00, + 0x58, 0x00, 0x00, + 0x5a, 0x00, 0x00, + 0x5c, 0x00, 0x00, + 0x5e, 0x00, 0x00, + + 0x1a, 0x1d, 0x21, 0x1b, 0x26, 0x22, 0x25, 0x1d, 0x1c, 0x1f, 0x1e, 0x1c, + 0x19, 0x27, 0x21, 0x1a, 0x1f, 0x1f, 0x1d, 0x1c, 0x24, 0x23, 0x19, 0x20, + 0x24, 0x22, 0x1a, 0x25, 0x27, 0x1c, 0x20, 0x1a, 0x22, 0x1a, 0x1e, 0x21, + 0x24, 0x1b, 0x26, 0x18, 0x22, 0x1d, 0x1d, 0x24, 0x1c, 0x26, 0x26, 0x23, + 0x1e, 0x1c, 0x18, 0x1a, 0x27, 0x1a, 0x22, 0x23, 0x24, 0x25, 0x20, 0x24, + 0x1a, 0x19, 0x27, 0x24, 0x1b, 0x1d, 0x1d, 0x18, 0x20, 0x1c, 0x19, 0x1b, + 0x21, 0x1e, 0x27, 0x25, 0x1c, 0x26, 0x21, 0x22, 0x1a, 0x21, 0x25, 0x1a, + 0x24, 0x20, 0x25, 0x21, 0x1d, 0x1e, 0x1d, 0x1f, 0x20, 0x1c, 0x1c, 0x24, + 0x22, 0x21, 0x24, 0x1a, 0x26, 0x25, 0x1e, 0x1f, 0x1b, 0x1e, 0x1d, 0x20, + 0x1c, 0x26, 0x1b, 0x1f, 0x20, 0x18, 0x21, 0x1c, 0x20, 0x1f, 0x26, 0x26, + 0x26, 0x1b, 0x1e, 0x1e, 0x20, 0x22, 0x1a, 0x1a, 0x1c, 0x27, 0x1d, 0x1a, + 0x24, 0x23, 0x21, 0x18, 0x1a, 0x27, 0x20, 0x1e, 0x25, 0x24, 0x26, 0x1e, + 0x24, 0x20, 0x23, 0x1d, 0x18, 0x21, 0x1c, 0x26, 0x25, 0x22, 0x1d, 0x1e, + 0x1d, 0x20, 0x20, 0x21, 0x1f, 0x26, 0x23, 0x1c, 0x22, 0x1d, 0x1c, 0x24, + 0x1c, 0x25, 0x1b, 0x1a, 0x21, 0x19, 0x20, 0x1e, 0x21, 0x1c, 0x24, 0x21, + 0x26, 0x18, 0x20, 0x23, 0x22, 0x25, 0x19, 0x27, 0x1e, 0x22, 0x21, 0x25, + 0x21, 0x1c, 0x19, 0x1b, 0x22, 0x1e, 0x18, 0x26, 0x1b, 0x1b, 0x19, 0x25, + 0x1c, 0x21, 0x1c, 0x26, 0x26, 0x18, 0x20, 0x24, 0x18, 0x19, 0x20, 0x23, + 0x27, 0x22, 0x23, 0x1d, 0x1d, 0x1c, 0x1a, 0x26, 0x21, 0x1c, 0x1a, 0x1b, + 0x23, 0x1a, 0x1a, 0x27, 0x1d, 0x1b, 0x24, 0x22, 0x25, 0x19, 0x20, 0x23, + 0x19, 0x19, 0x20, 0x1a, 0x1a, 0x18, 0x26, 0x19, 0x23, 0x21, 0x1f, 0x18, + 0x26, 0x22, 0x26, 0x20, 0x26, 0x19, 0x23, 0x22, 0x1b, 0x26, 0x21, 0x20, + 0x19, 0x1d, 0x1b, 0x27, 0x1f, 0x24, 0x22, 0x20, 0x25, 0x1b, 0x23, 0x18, + 0x1c, 0x22, 0x1a, 0x27, 0x1b, 0x21, 0x18, 0x1a, 0x1b, 0x27, 0x22, 0x1a, + 0x18, 0x1e, 0x24, 0x1b, 0x1c, 0x1d, 0x24, 0x1e, 0x23, 0x27, 0x1d, 0x1a, + 0x08, 0x13, 0x0f, 0x0c, 0x0d, 0x0f, 0x0f, 0x10, 0x0e, 0x0a, 0x12, 0x0f, + 0x10, 0x0f, 0x12, 0x15, 0x15, 0x0e, 0x0c, 0x10, 0x0e, 0x11, 0x13, 0x0a, + 0x12, 0x0e, 0x13, 0x15, 0x15, 0x0c, 0x0d, 0x16, 0x08, 0x15, 0x0b, 0x0d, + 0x0d, 0x12, 0x16, 0x14, 0x15, 0x11, 0x0b, 0x0e, 0x08, 0x16, 0x0b, 0x15, + 0x0d, 0x10, 0x0e, 0x13, 0x09, 0x09, 0x15, 0x13, 0x0f, 0x11, 0x11, 0x0c, + 0x16, 0x17, 0x0a, 0x16, 0x15, 0x0e, 0x0c, 0x0a, 0x08, 0x0a, 0x17, 0x16, + 0x13, 0x0a, 0x0c, 0x14, 0x08, 0x0f, 0x12, 0x0d, 0x08, 0x08, 0x09, 0x09, + 0x09, 0x17, 0x15, 0x10, 0x10, 0x0f, 0x15, 0x0e, 0x0f, 0x08, 0x0d, 0x0c, + 0x0e, 0x12, 0x0f, 0x0f, 0x15, 0x0e, 0x0d, 0x11, 0x11, 0x11, 0x0d, 0x12, + 0x09, 0x17, 0x08, 0x09, 0x17, 0x09, 0x0b, 0x08, 0x09, 0x08, 0x11, 0x11, + 0x10, 0x0e, 0x08, 0x17, 0x0f, 0x0e, 0x0b, 0x15, 0x09, 0x13, 0x0c, 0x16, + 0x09, 0x11, 0x0f, 0x13, 0x0b, 0x15, 0x0d, 0x0c, 0x14, 0x0d, 0x0d, 0x14, + 0x0f, 0x10, 0x15, 0x10, 0x11, 0x0e, 0x0a, 0x09, 0x15, 0x0b, 0x08, 0x0c, + 0x12, 0x0c, 0x0a, 0x13, 0x17, 0x0e, 0x12, 0x09, 0x08, 0x09, 0x14, 0x0b, + 0x16, 0x0a, 0x10, 0x13, 0x10, 0x15, 0x10, 0x08, 0x0e, 0x0d, 0x11, 0x17, + 0x14, 0x13, 0x09, 0x12, 0x17, 0x0a, 0x17, 0x12, 0x0e, 0x09, 0x0d, 0x0e, + 0x10, 0x17, 0x10, 0x11, 0x09, 0x0d, 0x14, 0x08, 0x0f, 0x0c, 0x13, 0x17, + 0x0a, 0x0b, 0x17, 0x10, 0x11, 0x11, 0x10, 0x0d, 0x0c, 0x11, 0x17, 0x0c, + 0x14, 0x16, 0x16, 0x0b, 0x08, 0x0c, 0x11, 0x10, 0x0c, 0x0a, 0x09, 0x0d, + 0x0f, 0x16, 0x0d, 0x16, 0x0b, 0x09, 0x16, 0x0d, 0x0d, 0x16, 0x16, 0x16, + 0x0f, 0x0f, 0x0b, 0x14, 0x09, 0x0b, 0x09, 0x15, 0x0a, 0x17, 0x08, 0x0b, + 0x0c, 0x12, 0x14, 0x10, 0x14, 0x15, 0x16, 0x0b, 0x14, 0x0b, 0x0a, 0x08, + 0x0d, 0x08, 0x0e, 0x12, 0x17, 0x0c, 0x10, 0x0e, 0x14, 0x14, 0x0b, 0x15, + 0x08, 0x0c, 0x12, 0x0b, 0x0b, 0x12, 0x0e, 0x10, 0x0d, 0x0a, 0x08, 0x09, + 0x08, 0x16, 0x0d, 0x14, 0x0a, 0x10, 0x14, 0x0f, 0x11, 0x0b, 0x0a, 0x10, + 0x0e, 0x13, 0x12, 0x11, 0x0e, 0x08, 0x0a, 0x13, 0x0a, 0x0a, 0x15, 0x0b, + 0x09, 0x0b, 0x17, 0x0c, 0x13, 0x14, 0x14, 0x0c, 0x17, 0x16, 0x14, 0x0f, + 0x10, 0x13, 0x13, 0x08, 0x15, 0x15, 0x0f, 0x0b, 0x10, 0x0a, 0x15, 0x17, + 0x0b, 0x17, 0x12, 0x0d, 0x0a, 0x10, 0x11, 0x0c, 0x13, 0x10, 0x10, 0x0f, + 0x0d, 0x0c, 0x13, 0x0d, 0x0a, 0x10, 0x15, 0x13, 0x0c, 0x11, 0x13, 0x09, + 0x0e, 0x0b, 0x0d, 0x16, 0x0d, 0x0b, 0x16, 0x11, 0x0b, 0x10, 0x17, 0x0e, + 0x09, 0x10, 0x12, 0x14, 0x08, 0x0b, 0x0c, 0x0e, 0x10, 0x17, 0x13, 0x12, + 0x0f, 0x11, 0x0e, 0x13, 0x0a, 0x0a, 0x15, 0x10, 0x0e, 0x0b, 0x0f, 0x14, + 0x0f, 0x0d, 0x0d, 0x12, 0x16, 0x0c, 0x09, 0x17, 0x14, 0x13, 0x14, 0x15, + 0x17, 0x08, 0x0b, 0x0f, 0x08, 0x17, 0x0a, 0x10, 0x10, 0x10, 0x0c, 0x12, + 0x13, 0x09, 0x0b, 0x09, 0x0d, 0x12, 0x16, 0x14, 0x08, 0x0b, 0x0f, 0x16, + 0x0f, 0x10, 0x16, 0x0c, 0x0c, 0x12, 0x09, 0x0b, 0x13, 0x0d, 0x12, 0x14, + 0x0c, 0x15, 0x0c, 0x15, 0x0e, 0x10, 0x0f, 0x09, 0x12, 0x13, 0x0b, 0x17, + 0x0d, 0x09, 0x13, 0x0e, 0x0d, 0x0b, 0x0c, 0x15, 0x13, 0x0b, 0x09, 0x17, + 0x16, 0x0b, 0x0b, 0x11, 0x10, 0x16, 0x0d, 0x15, 0x13, 0x11, 0x12, 0x09, + 0x0a, 0x0a, 0x0b, 0x14, 0x15, 0x0f, 0x13, 0x0b, 0x11, 0x0f, 0x11, 0x16, + 0x12, 0x16, 0x14, 0x0e, 0x09, 0x16, 0x0e, 0x17, 0x09, 0x11, 0x10, 0x12, + 0x10, 0x16, 0x0f, 0x0b, 0x10, 0x0a, 0x0d, 0x12, 0x0d, 0x10, 0x0f, 0x0a, + 0x17, 0x0a, 0x0e, 0x10, 0x12, 0x17, 0x0f, 0x0d, 0x15, 0x0b, 0x13, 0x16, + 0x0a, 0x0a, 0x16, 0x0b, 0x14, 0x0f, 0x16, 0x0c, 0x0d, 0x0e, 0x10, 0x16, + 0x10, 0x15, 0x11, 0x15, 0x0d, 0x08, 0x08, 0x0d, 0x0b, 0x0e, 0x16, 0x16, + 0x0e, 0x0e, 0x0b, 0x0b, 0x12, 0x17, 0x0a, 0x14, 0x0a, 0x09, 0x17, 0x16, + 0x10, 0x16, 0x0a, 0x15, 0x0c, 0x12, 0x14, 0x15, 0x0f, 0x0d, 0x12, 0x15, + 0x0e, 0x13, 0x0b, 0x12, 0x09, 0x0a, 0x10, 0x0f, 0x10, 0x14, 0x13, 0x0a, + 0x14, 0x16, 0x16, 0x16, 0x17, 0x16, 0x14, 0x0f, 0x15, 0x17, 0x0d, 0x09, + 0x0c, 0x0b, 0x10, 0x0d, 0x0e, 0x09, 0x15, 0x17, 0x16, 0x10, 0x09, 0x12, + 0x0e, 0x08, 0x10, 0x0e, 0x17, 0x0d, 0x15, 0x14, 0x0c, 0x0b, 0x16, 0x17, + 0x0c, 0x14, 0x09, 0x14, 0x0d, 0x09, 0x13, 0x12, 0x0d, 0x0c, 0x17, 0x13, + 0x0e, 0x15, 0x12, 0x0c, 0x0d, 0x14, 0x16, 0x14, 0x15, 0x0f, 0x0a, 0x14, + 0x14, 0x08, 0x11, 0x09, 0x0b, 0x10, 0x08, 0x10, 0x0c, 0x0a, 0x0d, 0x12, + 0x0b, 0x08, 0x0d, 0x10, 0x0d, 0x0c, 0x0b, 0x13, 0x0a, 0x16, 0x17, 0x0f, + 0x12, 0x16, 0x0c, 0x0f, 0x0d, 0x0f, 0x0c, 0x0a, 0x10, 0x15, 0x0c, 0x13, + 0x0d, 0x0d, 0x0c, 0x12, 0x0f, 0x12, 0x0d, 0x12, 0x13, 0x12, 0x0a, 0x08, + 0x17, 0x0e, 0x13, 0x09, 0x0c, 0x13, 0x11, 0x16, 0x11, 0x15, 0x0e, 0x16, + 0x0d, 0x12, 0x09, 0x15, 0x10, 0x0d, 0x11, 0x15, 0x12, 0x16, 0x10, 0x0a, + 0x10, 0x15, 0x14, 0x0b, 0x10, 0x17, 0x0c, 0x0f, 0x0e, 0x08, 0x11, 0x12, + 0x13, 0x0a, 0x11, 0x0d, 0x08, 0x17, 0x0c, 0x0d, 0x12, 0x0d, 0x0b, 0x0a, + 0x12, 0x15, 0x17, 0x0d, 0x13, 0x10, 0x0f, 0x0c, 0x0e, 0x0c, 0x0f, 0x16, + 0x0b, 0x14, 0x0e, 0x11, 0x14, 0x17, 0x0c, 0x0f, 0x0a, 0x16, 0x14, 0x0a, + 0x16, 0x09, 0x10, 0x10, 0x0e, 0x14, 0x12, 0x09, 0x11, 0x12, 0x0f, 0x0d, + 0x0a, 0x16, 0x11, 0x10, 0x0b, 0x09, 0x0f, 0x0e, 0x15, 0x15, 0x08, 0x11, + 0x15, 0x0d, 0x09, 0x17, 0x0b, 0x16, 0x09, 0x09, 0x17, 0x12, 0x11, 0x0e, + 0x0e, 0x0b, 0x0f, 0x17, 0x16, 0x16, 0x0d, 0x08, 0x15, 0x16, 0x11, 0x08, + 0x17, 0x08, 0x0f, 0x15, 0x16, 0x10, 0x0f, 0x13, 0x15, 0x10, 0x12, 0x08, + 0x0f, 0x14, 0x0a, 0x0f, 0x0e, 0x13, 0x15, 0x15, 0x17, 0x0d, 0x15, 0x15, + 0x0b, 0x0a, 0x16, 0x09, 0x09, 0x0f, 0x0a, 0x08, 0x10, 0x12, 0x16, 0x0e, + 0x0a, 0x0d, 0x0a, 0x08, 0x16, 0x15, 0x09, 0x0d, 0x11, 0x0b, 0x15, 0x08, + 0x17, 0x12, 0x16, 0x17, 0x17, 0x13, 0x15, 0x0b, 0x16, 0x13, 0x0d, 0x17, + 0x0b, 0x0f, 0x08, 0x13, 0x0a, 0x16, 0x0a, 0x0c, 0x0b, 0x0d, 0x0d, 0x0a, + 0x0a, 0x0e, 0x10, 0x14, 0x12, 0x0d, 0x15, 0x11, 0x08, 0x13, 0x11, 0x08, + 0x09, 0x0c, 0x08, 0x0b, 0x0a, 0x0b, 0x10, 0x0e, 0x10, 0x15, 0x10, 0x13, + 0x0c, 0x08, 0x10, 0x16, 0x0e, 0x0d, 0x10, 0x0e, 0x09, 0x09, 0x0e, 0x10, + 0x0f, 0x12, 0x15, 0x10, 0x0b, 0x0a, 0x15, 0x0c, 0x0e, 0x16, 0x10, 0x11, + 0x0a, 0x08, 0x17, 0x13, 0x16, 0x10, 0x0f, 0x0a, 0x11, 0x17, 0x08, 0x17, + 0x0c, 0x10, 0x0d, 0x0e, 0x11, 0x13, 0x16, 0x09, 0x0e, 0x14, 0x12, 0x11, + 0x17, 0x0f, 0x16, 0x0d, 0x0e, 0x0f, 0x16, 0x11, 0x10, 0x16, 0x0c, 0x0e, + 0x0f, 0x13, 0x11, 0x08, 0x12, 0x11, 0x17, 0x17, 0x0a, 0x0d, 0x0e, 0x14, + 0x09, 0x0d, 0x15, 0x0f, 0x0a, 0x0f, 0x09, 0x09, 0x17, 0x17, 0x0e, 0x0e, + 0x0f, 0x0d, 0x17, 0x17, 0x0c, 0x0b, 0x0d, 0x13, 0x17, 0x16, 0x13, 0x12, + 0x10, 0x13, 0x12, 0x13, 0x09, 0x08, 0x0f, 0x0a, 0x0d, 0x0d, 0x11, 0x0f, + 0x14, 0x12, 0x10, 0x13, 0x12, 0x17, 0x09, 0x0a, 0x0d, 0x09, 0x09, 0x11, + 0x0c, 0x0f, 0x0d, 0x0c, 0x0e, 0x08, 0x16, 0x16, 0x14, 0x11, 0x12, 0x15, + 0x11, 0x09, 0x08, 0x17, 0x0e, 0x11, 0x0f, 0x0b, 0x0c, 0x08, 0x17, 0x17, + 0x08, 0x08, 0x09, 0x0d, 0x0a, 0x0b, 0x16, 0x0f, 0x12, 0x0b, 0x13, 0x08, + 0x0c, 0x12, 0x17, 0x09, 0x0b, 0x12, 0x17, 0x15, 0x13, 0x17, 0x14, 0x0a, + 0x11, 0x0c, 0x0d, 0x16, 0x0c, 0x0c, 0x15, 0x0c, 0x0d, 0x17, 0x12, 0x0f, + 0x0b, 0x10, 0x16, 0x16, 0x14, 0x12, 0x17, 0x09, 0x0c, 0x16, 0x0b, 0x10, + 0x10, 0x0a, 0x0d, 0x0c, 0x09, 0x0a, 0x0f, 0x12, 0x0e, 0x15, 0x11, 0x13, + 0x09, 0x0f, 0x17, 0x0f, 0x0f, 0x11, 0x17, 0x12, 0x0a, 0x16, 0x10, 0x17, + 0x10, 0x0f, 0x09, 0x15, 0x0e, 0x0c, 0x0d, 0x17, 0x0e, 0x13, 0x0b, 0x10, + 0x15, 0x13, 0x0b, 0x0b, 0x10, 0x14, 0x16, 0x12, 0x0b, 0x16, 0x09, 0x12, + 0x10, 0x09, 0x0c, 0x13, 0x17, 0x14, 0x13, 0x10, 0x0c, 0x14, 0x0e, 0x12, + 0x08, 0x14, 0x11, 0x0e, 0x0f, 0x15, 0x16, 0x0c, 0x11, 0x09, 0x0f, 0x09, + 0x16, 0x0e, 0x13, 0x09, 0x0d, 0x15, 0x13, 0x16, 0x16, 0x08, 0x11, 0x16, + 0x15, 0x0c, 0x0f, 0x09, 0x08, 0x15, 0x14, 0x09, 0x12, 0x0e, 0x0f, 0x09, + 0x01, 0x05, 0x04, 0x04, 0x03, 0x02, 0x03, 0x03, 0x02, 0x00, 0x02, 0x01, + 0x03, 0x06, 0x01, 0x03, 0x05, 0x00, 0x04, 0x02, 0x03, 0x00, 0x03, 0x05, + 0x03, 0x05, 0x03, 0x07, 0x04, 0x03, 0x03, 0x06, 0x00, 0x07, 0x03, 0x03, + 0x01, 0x06, 0x07, 0x04, 0x07, 0x01, 0x05, 0x02, 0x00, 0x07, 0x06, 0x05, + 0x07, 0x02, 0x00, 0x02, 0x02, 0x03, 0x00, 0x06, 0x00, 0x03, 0x06, 0x05, + 0x06, 0x01, 0x03, 0x07, 0x01, 0x06, 0x03, 0x03, 0x05, 0x02, 0x07, 0x05, + 0x04, 0x05, 0x07, 0x04, 0x04, 0x06, 0x02, 0x03, 0x00, 0x02, 0x06, 0x03, + 0x05, 0x06, 0x02, 0x06, 0x02, 0x00, 0x03, 0x01, 0x02, 0x07, 0x00, 0x03, + 0x06, 0x03, 0x07, 0x03, 0x05, 0x07, 0x00, 0x01, 0x04, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, 0x01, 0x06, 0x07, 0x03, + 0x06, 0x03, 0x05, 0x01, 0x02, 0x05, 0x05, 0x00, 0x01, 0x04, 0x04, 0x06, + 0x03, 0x05, 0x00, 0x07, 0x06, 0x06, 0x00, 0x05, 0x07, 0x04, 0x05, 0x02, + 0x07, 0x02, 0x02, 0x00, 0x00, 0x02, 0x04, 0x07, 0x05, 0x01, 0x00, 0x07, + 0x07, 0x05, 0x00, 0x00, 0x01, 0x05, 0x07, 0x05, 0x02, 0x00, 0x05, 0x01, + 0x07, 0x05, 0x06, 0x06, 0x01, 0x04, 0x01, 0x00, 0x06, 0x03, 0x01, 0x07, + 0x06, 0x05, 0x06, 0x03, 0x07, 0x06, 0x03, 0x07, 0x03, 0x04, 0x07, 0x05, + 0x01, 0x07, 0x03, 0x04, 0x00, 0x00, 0x05, 0x07, 0x05, 0x04, 0x06, 0x06, + 0x01, 0x07, 0x06, 0x00, 0x03, 0x00, 0x07, 0x01, 0x05, 0x05, 0x04, 0x05, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x03, 0x05, 0x05, 0x03, 0x01, 0x01, 0x03, + 0x01, 0x07, 0x03, 0x06, 0x03, 0x01, 0x04, 0x04, 0x01, 0x03, 0x04, 0x04, + 0x03, 0x04, 0x06, 0x01, 0x01, 0x02, 0x06, 0x06, 0x03, 0x02, 0x06, 0x07, + 0x06, 0x04, 0x04, 0x02, 0x05, 0x06, 0x05, 0x06, 0x05, 0x00, 0x04, 0x00, + 0x02, 0x01, 0x05, 0x03, 0x05, 0x02, 0x07, 0x01, 0x06, 0x05, 0x03, 0x00, + 0x00, 0x01, 0x06, 0x03, 0x04, 0x04, 0x03, 0x02, 0x01, 0x07, 0x05, 0x06, + 0x06, 0x02, 0x04, 0x03, 0x03, 0x01, 0x04, 0x05, 0x03, 0x02, 0x01, 0x01, +}; + +//***************************************************************************** +// +// The bottom right corner of the border. +// +//***************************************************************************** +static const uint8_t g_pui8BottomRight[] = +{ + IMAGE_FMT_8BPP_UNCOMP, + 10, 0, + 10, 0, + + 29, + 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, + 0x0b, 0x00, 0x00, + 0x10, 0x00, 0x00, + 0x11, 0x00, 0x00, + 0x12, 0x00, 0x00, + 0x13, 0x00, 0x00, + 0x14, 0x00, 0x00, + 0x16, 0x00, 0x00, + 0x17, 0x00, 0x00, + 0x20, 0x00, 0x00, + 0x21, 0x00, 0x00, + 0x22, 0x00, 0x00, + 0x23, 0x00, 0x00, + 0x24, 0x00, 0x00, + 0x25, 0x00, 0x00, + 0x26, 0x00, 0x00, + 0x27, 0x00, 0x00, + 0x28, 0x00, 0x00, + 0x29, 0x00, 0x00, + 0x2a, 0x00, 0x00, + 0x2b, 0x00, 0x00, + 0x2c, 0x00, 0x00, + 0x2d, 0x00, 0x00, + 0x2e, 0x00, 0x00, + 0x2f, 0x00, 0x00, + 0x40, 0x00, 0x00, + 0x48, 0x00, 0x00, + 0x50, 0x00, 0x00, + 0x56, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x14, 0x1c, 0x14, 0x0a, 0x17, 0x0d, 0x04, 0x00, 0x00, + 0x00, 0x1b, 0x0e, 0x0d, 0x13, 0x17, 0x12, 0x09, 0x00, 0x00, 0x16, 0x1b, + 0x13, 0x10, 0x19, 0x13, 0x0e, 0x07, 0x16, 0x1a, 0x1c, 0x14, 0x18, 0x13, + 0x0a, 0x10, 0x10, 0x04, 0x1d, 0x0a, 0x15, 0x13, 0x19, 0x11, 0x15, 0x15, + 0x18, 0x03, 0x12, 0x14, 0x19, 0x0e, 0x16, 0x11, 0x14, 0x17, 0x0e, 0x08, + 0x14, 0x0b, 0x18, 0x0c, 0x0a, 0x13, 0x0b, 0x14, 0x06, 0x01, 0x11, 0x10, + 0x0d, 0x0f, 0x13, 0x0a, 0x0a, 0x13, 0x07, 0x00, 0x0e, 0x10, 0x0f, 0x17, + 0x0b, 0x11, 0x09, 0x04, 0x02, 0x00, 0x07, 0x03, 0x05, 0x05, 0x05, 0x08, + 0x02, 0x00, 0x00, 0x00, +}; + +//***************************************************************************** +// +//! Draws a frame on the LCD with the application name in the title bar. +//! +//! \param psContext is a pointer to the graphics library context used to draw +//! the application frame. +//! \param pcAppName is a pointer to a string that contains the name of the +//! application. +//! +//! This function draws an application frame onto the LCD, using the supplied +//! graphics library context to access the LCD and the given name in the title +//! bar of the application frame. +//! +//! \return None. +// +//***************************************************************************** +void +FrameDraw(tContext *psContext, const char *pcAppName) +{ + tRectangle sRect; + + // + // See if the display is in a landscape or portrait configuration. + // + if(GrContextDpyWidthGet(psContext) == 320) + { + // + // Reset the clipping region to the entire LCD surface. + // + sRect.i16XMin = 0; + sRect.i16YMin = 0; + sRect.i16XMax = 319; + sRect.i16YMax = 239; + GrContextClipRegionSet(psContext, &sRect); + + // + // Draw the images of the border. + // + GrImageDraw(psContext, g_pui8TopLeft, 0, 0); + GrImageDraw(psContext, g_pui8Top, 10, 0); + GrImageDraw(psContext, g_pui8TopRight, 310, 0); + GrImageDraw(psContext, g_pui8Left, 0, 26); + GrImageDraw(psContext, g_pui8Right, 314, 26); + GrImageDraw(psContext, g_pui8BottomLeft, 0, 230); + GrImageDraw(psContext, g_pui8Bottom, 10, 234); + GrImageDraw(psContext, g_pui8BottomRight, 310, 230); + + // + // Select red test in the Computer Modern sans-serif 18pt bold font. + // + GrContextForegroundSet(psContext, ClrWhite); + GrContextFontSet(psContext, g_psFontCmss18b); + + // + // Draw the application name centered in the title bar. + // + GrStringDrawCentered(psContext, pcAppName, -1, 160, 8, false); + + // + // Set the clip region to the interior region of the border. + // + sRect.i16XMin = 8; + sRect.i16YMin = 24; + sRect.i16XMax = 311; + sRect.i16YMax = 231; + GrContextClipRegionSet(psContext, &sRect); + } + else + { + // + // Reset the clipping region to the entire LCD surface. + // + sRect.i16XMin = 0; + sRect.i16YMin = 0; + sRect.i16XMax = 239; + sRect.i16YMax = 319; + GrContextClipRegionSet(psContext, &sRect); + + // + // Draw the images of the border. + // + GrImageDraw(psContext, g_pui8TopLeft, 0, 0); + GrImageDraw(psContext, g_pui8Top, 10, 0); + GrImageDraw(psContext, g_pui8TopRight, 230, 0); + GrImageDraw(psContext, g_pui8Left, 0, 26); + GrImageDraw(psContext, g_pui8Left, 0, 106); + GrImageDraw(psContext, g_pui8Right, 234, 26); + GrImageDraw(psContext, g_pui8Right, 234, 106); + GrImageDraw(psContext, g_pui8BottomLeft, 0, 310); + GrImageDraw(psContext, g_pui8Bottom, 10, 314); + GrImageDraw(psContext, g_pui8BottomRight, 230, 310); + + // + // Select red test in the Computer Modern sans-serif 18pt bold font. + // + GrContextForegroundSet(psContext, ClrWhite); + GrContextFontSet(psContext, g_psFontCmss18b); + + // + // Draw the application name centered in the title bar. + // + GrStringDrawCentered(psContext, pcAppName, -1, 120, 8, false); + + // + // Set the clip region to the interior region of the border. + // + sRect.i16XMin = 8; + sRect.i16YMin = 24; + sRect.i16XMax = 231; + sRect.i16YMax = 311; + GrContextClipRegionSet(psContext, &sRect); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/frame.h b/boards/dk-tm4c129x/drivers/frame.h new file mode 100644 index 0000000..09461db --- /dev/null +++ b/boards/dk-tm4c129x/drivers/frame.h @@ -0,0 +1,55 @@ +//***************************************************************************** +// +// frame.h - Prototypes for the application frame function. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __DRIVERS_FRAME_H__ +#define __DRIVERS_FRAME_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void FrameDraw(tContext *psContext, const char *pcAppName); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_FRAME_H__ diff --git a/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.c b/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.c new file mode 100644 index 0000000..7fac8df --- /dev/null +++ b/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.c @@ -0,0 +1,1056 @@ +//***************************************************************************** +// +// kentec320x240x16_ssd2119.c - Display driver for the Kentec K350QVG-V2-F +// TFT display attached to the LCD controller via +// an 8-bit LIDD interface. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_gpio.h" +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "inc/hw_sysctl.h" +#include "driverlib/gpio.h" +#include "driverlib/interrupt.h" +#include "driverlib/sysctl.h" +#include "driverlib/timer.h" +#include "driverlib/rom.h" +#include "driverlib/lcd.h" +#include "grlib/grlib.h" +#include "drivers/kentec320x240x16_ssd2119.h" + +//***************************************************************************** +// +//! \addtogroup kentec320x240x16_ssd2119_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// This driver operates in four different screen orientations. They are: +// +// * Portrait - The screen is taller than it is wide, and the flex connector is +// on the left of the display. This is selected by defining +// PORTRAIT. +// +// * Landscape - The screen is wider than it is tall, and the flex connector is +// on the bottom of the display. This is selected by defining +// LANDSCAPE. +// +// * Portrait flip - The screen is taller than it is wide, and the flex +// connector is on the right of the display. This is +// selected by defining PORTRAIT_FLIP. +// +// * Landscape flip - The screen is wider than it is tall, and the flex +// connector is on the top of the display. This is +// selected by defining LANDSCAPE_FLIP. +// +// These can also be imagined in terms of screen rotation; if portrait mode is +// 0 degrees of screen rotation, landscape is 90 degrees of counter-clockwise +// rotation, portrait flip is 180 degrees of rotation, and landscape flip is +// 270 degress of counter-clockwise rotation. +// +// If no screen orientation is selected, landscape mode will be used. +// +//***************************************************************************** +#if ! defined(PORTRAIT) && ! defined(PORTRAIT_FLIP) && \ + ! defined(LANDSCAPE) && ! defined(LANDSCAPE_FLIP) +#define LANDSCAPE_FLIP +#endif + +//***************************************************************************** +// +// Various definitions controlling coordinate space mapping and drawing +// direction in the four supported orientations. +// +//***************************************************************************** +#ifdef PORTRAIT +#define HORIZ_DIRECTION 0x28 +#define VERT_DIRECTION 0x20 +#define MAPPED_X(x, y) (319 - (y)) +#define MAPPED_Y(x, y) (x) +#endif +#ifdef LANDSCAPE +#define HORIZ_DIRECTION 0x00 +#define VERT_DIRECTION 0x08 +#define MAPPED_X(x, y) (319 - (x)) +#define MAPPED_Y(x, y) (239 - (y)) +#endif +#ifdef PORTRAIT_FLIP +#define HORIZ_DIRECTION 0x18 +#define VERT_DIRECTION 0x10 +#define MAPPED_X(x, y) (y) +#define MAPPED_Y(x, y) (239 - (x)) +#endif +#ifdef LANDSCAPE_FLIP +#define HORIZ_DIRECTION 0x30 +#define VERT_DIRECTION 0x38 +#define MAPPED_X(x, y) (x) +#define MAPPED_Y(x, y) (y) +#endif + +//***************************************************************************** +// +// Various internal SD2119 registers name labels +// +//***************************************************************************** +#define SSD2119_DEVICE_CODE_READ_REG \ + 0x00 +#define SSD2119_OSC_START_REG 0x00 +#define SSD2119_OUTPUT_CTRL_REG 0x01 +#define SSD2119_LCD_DRIVE_AC_CTRL_REG \ + 0x02 +#define SSD2119_PWR_CTRL_1_REG 0x03 +#define SSD2119_DISPLAY_CTRL_REG \ + 0x07 +#define SSD2119_FRAME_CYCLE_CTRL_REG \ + 0x0b +#define SSD2119_PWR_CTRL_2_REG 0x0c +#define SSD2119_PWR_CTRL_3_REG 0x0d +#define SSD2119_PWR_CTRL_4_REG 0x0e +#define SSD2119_GATE_SCAN_START_REG \ + 0x0f +#define SSD2119_SLEEP_MODE_1_REG \ + 0x10 +#define SSD2119_ENTRY_MODE_REG 0x11 +#define SSD2119_SLEEP_MODE_2_REG \ + 0x12 +#define SSD2119_GEN_IF_CTRL_REG 0x15 +#define SSD2119_PWR_CTRL_5_REG 0x1e +#define SSD2119_RAM_DATA_REG 0x22 +#define SSD2119_FRAME_FREQ_REG 0x25 +#define SSD2119_ANALOG_SET_REG 0x26 +#define SSD2119_VCOM_OTP_1_REG 0x28 +#define SSD2119_VCOM_OTP_2_REG 0x29 +#define SSD2119_GAMMA_CTRL_1_REG \ + 0x30 +#define SSD2119_GAMMA_CTRL_2_REG \ + 0x31 +#define SSD2119_GAMMA_CTRL_3_REG \ + 0x32 +#define SSD2119_GAMMA_CTRL_4_REG \ + 0x33 +#define SSD2119_GAMMA_CTRL_5_REG \ + 0x34 +#define SSD2119_GAMMA_CTRL_6_REG \ + 0x35 +#define SSD2119_GAMMA_CTRL_7_REG \ + 0x36 +#define SSD2119_GAMMA_CTRL_8_REG \ + 0x37 +#define SSD2119_GAMMA_CTRL_9_REG \ + 0x3a +#define SSD2119_GAMMA_CTRL_10_REG \ + 0x3b +#define SSD2119_V_RAM_POS_REG 0x44 +#define SSD2119_H_RAM_START_REG 0x45 +#define SSD2119_H_RAM_END_REG 0x46 +#define SSD2119_X_RAM_ADDR_REG 0x4e +#define SSD2119_Y_RAM_ADDR_REG 0x4f + +#define ENTRY_MODE_DEFAULT 0x6830 +#define MAKE_ENTRY_MODE(x) ((ENTRY_MODE_DEFAULT & 0xff00) | (x)) + +//***************************************************************************** +// +// Read Access Timing +// ------------------ +// +// Direction OOOIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIOOOOOOOOOOOOO +// +// ~RD ----- -------------------------- +// \ / | +// ------------------ +// < Trdl >< Trdh > +// < Tcycle > +// < Tacc > +// /------------------| +// DATA ------------- ------------------ +// \------------------/ +// < Tdh > +// +// Delays < Trad >< Tdhd >< Trhd >< Trcd > +// +// This design keeps CS tied low so pulse width constraints relating to CS +// have been transfered to ~RD here. +// +// Tcycle Read Cycle Time 1000nS +// Tacc Data Access Time 100nS +// Trdl Read Data Low 500nS +// Trdh Read Data High 500nS +// Tdh Data Hold Time 100nS +// +// Trad (READ_DATA_ACCESS_DELAY) controls the delay between asserting ~RD and +// reading the data from the bus. +// Tdhd (READ_DATA_HOLD_DELAY) controls the delay after reading the data and +// before deasserting ~RD. +// Trhd (READ_HOLD_DELAY) controls the delay between deasserting ~RD and +// switching the data bus direction back to output. +// Trcd (READ_DATA_CYCLE_DELAY) controls the delay after switching the +// direction of the data bus. +// +//***************************************************************************** + +//***************************************************************************** +// +// The delay to impose after setting the state of the read/write line and +// before reading the data bus. This is expressed in terms of cycles of a +// tight loop whose body performs a single GPIO register access and needs to +// comply with the 500nS read cycle pulse width constraint. +// +//***************************************************************************** +#define READ_DATA_ACCESS_DELAY 5 + +//***************************************************************************** +// +// The delay to impose after reading the data and before resetting the state of +// the read/write line during a read operation. This is expressed in terms of +// cycles of a tight loop whose body performs a single GPIO register access and +// needs to comply with the 500nS read cycle pulse width constraint. +// +//***************************************************************************** +#define READ_DATA_HOLD_DELAY 5 + +//***************************************************************************** +// +// The delay to impose after deasserting ~RD and before setting the bus back to +// an output. This is expressed in terms of cycles of a tight loop whose body +// performs a single GPIO register access. +// +//***************************************************************************** +#define READ_HOLD_DELAY 5 + +//***************************************************************************** +// +// The delay to impose after completing a read cycle and before returning to +// the caller. This is expressed in terms of cycles of a tight loop whose body +// performs a single GPIO register access and needs to comply with the 1000nS +// read cycle pulse width constraint. +// +//***************************************************************************** +#define READ_DATA_CYCLE_DELAY 5 + +//***************************************************************************** +// +// The dimensions of the LCD panel. +// +//***************************************************************************** +#define LCD_HORIZONTAL_MAX 320 +#define LCD_VERTICAL_MAX 240 + +//***************************************************************************** +// +// Translates a 24-bit RGB color to a display driver-specific color. +// +// \param c is the 24-bit RGB color. The least-significant byte is the blue +// channel, the next byte is the green channel, and the third byte is the red +// channel. +// +// This macro translates a 24-bit RGB color into a value that can be written +// into the display's frame buffer in order to reproduce that color, or the +// closest possible approximation of that color. +// +// \return Returns the display-driver specific color. +// +//***************************************************************************** +#define DPYCOLORTRANSLATE(c) ((((c) & 0x00f80000) >> 8) | \ + (((c) & 0x0000fc00) >> 5) | \ + (((c) & 0x000000f8) >> 3)) + +//***************************************************************************** +// +// Writes a data word to the SSD2119. +// +//***************************************************************************** +static inline void +WriteData(uint16_t ui16Data) +{ + // + // Split the write into two bytes and pass them to the LCD controller. + // + LCDIDDDataWrite(LCD0_BASE, 0, ui16Data >> 8); + LCDIDDDataWrite(LCD0_BASE, 0, ui16Data & 0xff); +} + +//***************************************************************************** +// +// Writes a command to the SSD2119. +// +//***************************************************************************** +static inline void +WriteCommand(uint8_t ui8Data) +{ + // + // Pass the write on to the controller. + // + LCDIDDCommandWrite(LCD0_BASE, 0, (uint16_t)ui8Data); +} + +//***************************************************************************** +// +//! Draws a pixel on the screen. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! \param i32X is the X coordinate of the pixel. +//! \param i32Y is the Y coordinate of the pixel. +//! \param ui32Value is the color of the pixel. +//! +//! This function sets the given pixel to a particular color. The coordinates +//! of the pixel are assumed to be within the extents of the display. +//! +//! \return None. +// +//***************************************************************************** +static void +Kentec320x240x16_SSD2119PixelDraw(void *pvDisplayData, int32_t i32X, + int32_t i32Y, uint32_t ui32Value) +{ + // + // Set the X address of the display cursor. + // + WriteCommand(SSD2119_X_RAM_ADDR_REG); + WriteData(MAPPED_X(i32X, i32Y)); + + // + // Set the Y address of the display cursor. + // + WriteCommand(SSD2119_Y_RAM_ADDR_REG); + WriteData(MAPPED_Y(i32X, i32Y)); + + // + // Write the pixel value. + // + WriteCommand(SSD2119_RAM_DATA_REG); + WriteData(ui32Value); +} + +//***************************************************************************** +// +//! Draws a horizontal sequence of pixels on the screen. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! \param i32X is the X coordinate of the first pixel. +//! \param i32Y is the Y coordinate of the first pixel. +//! \param i32X0 is sub-pixel offset within the pixel data, which is valid for +//! 1 or 4 bit per pixel formats. +//! \param i32Count is the number of pixels to draw. +//! \param i32BPP is the number of bits per pixel; must be 1, 4, or 8. +//! \param pui8Data is a pointer to the pixel data. For 1 and 4 bit per pixel +//! formats, the most significant bit(s) represent the left-most pixel. +//! \param pui8Palette is a pointer to the palette used to draw the pixels. +//! +//! This function draws a horizontal sequence of pixels on the screen, using +//! the supplied palette. For 1 bit per pixel format, the palette contains +//! pre-translated colors; for 4 and 8 bit per pixel formats, the palette +//! contains 24-bit RGB values that must be translated before being written to +//! the display. +//! +//! \return None. +// +//***************************************************************************** +static void +Kentec320x240x16_SSD2119PixelDrawMultiple(void *pvDisplayData, int32_t i32X, + int32_t i32Y, int32_t i32X0, + int32_t i32Count, int32_t i32BPP, + const uint8_t *pui8Data, + const uint8_t *pui8Palette) +{ + uint32_t ui32Byte; + + // + // Set the cursor increment to left to right, followed by top to bottom. + // + WriteCommand(SSD2119_ENTRY_MODE_REG); + WriteData(MAKE_ENTRY_MODE(HORIZ_DIRECTION)); + + // + // Set the starting X address of the display cursor. + // + WriteCommand(SSD2119_X_RAM_ADDR_REG); + WriteData(MAPPED_X(i32X, i32Y)); + + // + // Set the Y address of the display cursor. + // + WriteCommand(SSD2119_Y_RAM_ADDR_REG); + WriteData(MAPPED_Y(i32X, i32Y)); + + // + // Write the data RAM write command. + // + WriteCommand(SSD2119_RAM_DATA_REG); + + // + // Determine how to interpret the pixel data based on the number of bits + // per pixel. + // + switch(i32BPP & ~GRLIB_DRIVER_FLAG_NEW_IMAGE) + { + // + // The pixel data is in 1 bit per pixel format. + // + case 1: + { + // + // Loop while there are more pixels to draw. + // + while(i32Count) + { + // + // Get the next byte of image data. + // + ui32Byte = *pui8Data++; + + // + // Loop through the pixels in this byte of image data. + // + for(; (i32X0 < 8) && i32Count; i32X0++, i32Count--) + { + // + // Draw this pixel in the appropriate color. + // + WriteData(((uint32_t *)pui8Palette)[(ui32Byte >> + (7 - i32X0)) & 1]); + } + + // + // Start at the beginning of the next byte of image data. + // + i32X0 = 0; + } + + // + // The image data has been drawn. + // + break; + } + + // + // The pixel data is in 4 bit per pixel format. + // + case 4: + { + // + // Loop while there are more pixels to draw. "Duff's device" is + // used to jump into the middle of the loop if the first nibble of + // the pixel data should not be used. Duff's device makes use of + // the fact that a case statement is legal anywhere within a + // sub-block of a switch statement. See + // http://en.wikipedia.org/wiki/Duff's_device for detailed + // information about Duff's device. + // + switch(i32X0 & 1) + { + case 0: + while(i32Count) + { + // + // Get the upper nibble of the next byte of pixel data + // and extract the corresponding entry from the + // palette. + // + ui32Byte = (*pui8Data >> 4) * 3; + ui32Byte = (*(uint32_t *)(pui8Palette + ui32Byte) & + 0x00ffffff); + + // + // Translate this palette entry and write it to the + // screen. + // + WriteData(DPYCOLORTRANSLATE(ui32Byte)); + + // + // Decrement the count of pixels to draw. + // + i32Count--; + + // + // See if there is another pixel to draw. + // + if(i32Count) + { + case 1: + // + // Get the lower nibble of the next byte of pixel + // data and extract the corresponding entry from + // the palette. + // + ui32Byte = (*pui8Data++ & 15) * 3; + ui32Byte = (*(uint32_t *)(pui8Palette + ui32Byte) & + 0x00ffffff); + + // + // Translate this palette entry and write it to the + // screen. + // + WriteData(DPYCOLORTRANSLATE(ui32Byte)); + + // + // Decrement the count of pixels to draw. + // + i32Count--; + } + } + } + + // + // The image data has been drawn. + // + break; + } + + // + // The pixel data is in 8 bit per pixel format. + // + case 8: + { + // + // Loop while there are more pixels to draw. + // + while(i32Count--) + { + // + // Get the next byte of pixel data and extract the + // corresponding entry from the palette. + // + ui32Byte = *pui8Data++ * 3; + ui32Byte = *(uint32_t *)(pui8Palette + ui32Byte) & 0x00ffffff; + + // + // Translate this palette entry and write it to the screen. + // + WriteData(DPYCOLORTRANSLATE(ui32Byte)); + } + + // + // The image data has been drawn. + // + break; + } + } +} + +//***************************************************************************** +// +//! Draws a horizontal line. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! \param i32X1 is the X coordinate of the start of the line. +//! \param i32X2 is the X coordinate of the end of the line. +//! \param i32Y is the Y coordinate of the line. +//! \param ui32Value is the color of the line. +//! +//! This function draws a horizontal line on the display. The coordinates of +//! the line are assumed to be within the extents of the display. +//! +//! \return None. +// +//***************************************************************************** +static void +Kentec320x240x16_SSD2119LineDrawH(void *pvDisplayData, int32_t i32X1, + int32_t i32X2, int32_t i32Y, + uint32_t ui32Value) +{ + // + // Set the cursor increment to left to right, followed by top to bottom. + // + WriteCommand(SSD2119_ENTRY_MODE_REG); + WriteData(MAKE_ENTRY_MODE(HORIZ_DIRECTION)); + + // + // Set the starting X address of the display cursor. + // + WriteCommand(SSD2119_X_RAM_ADDR_REG); + WriteData(MAPPED_X(i32X1, i32Y)); + + // + // Set the Y address of the display cursor. + // + WriteCommand(SSD2119_Y_RAM_ADDR_REG); + WriteData(MAPPED_Y(i32X1, i32Y)); + + // + // Write the data RAM write command. + // + WriteCommand(SSD2119_RAM_DATA_REG); + + // + // Loop through the pixels of this horizontal line. + // + while(i32X1++ <= i32X2) + { + // + // Write the pixel value. + // + WriteData(ui32Value); + } +} + +//***************************************************************************** +// +//! Draws a vertical line. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! \param i32X is the X coordinate of the line. +//! \param i32Y1 is the Y coordinate of the start of the line. +//! \param i32Y2 is the Y coordinate of the end of the line. +//! \param ui32Value is the color of the line. +//! +//! This function draws a vertical line on the display. The coordinates of the +//! line are assumed to be within the extents of the display. +//! +//! \return None. +// +//***************************************************************************** +static void +Kentec320x240x16_SSD2119LineDrawV(void *pvDisplayData, int32_t i32X, + int32_t i32Y1, int32_t i32Y2, + uint32_t ui32Value) +{ + // + // Set the cursor increment to top to bottom, followed by left to right. + // + WriteCommand(SSD2119_ENTRY_MODE_REG); + WriteData(MAKE_ENTRY_MODE(VERT_DIRECTION)); + + // + // Set the X address of the display cursor. + // + WriteCommand(SSD2119_X_RAM_ADDR_REG); + WriteData(MAPPED_X(i32X, i32Y1)); + + // + // Set the starting Y address of the display cursor. + // + WriteCommand(SSD2119_Y_RAM_ADDR_REG); + WriteData(MAPPED_Y(i32X, i32Y1)); + + // + // Write the data RAM write command. + // + WriteCommand(SSD2119_RAM_DATA_REG); + + // + // Loop through the pixels of this vertical line. + // + while(i32Y1++ <= i32Y2) + { + // + // Write the pixel value. + // + WriteData(ui32Value); + } +} + +//***************************************************************************** +// +//! Fills a rectangle. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! \param psRect is a pointer to the structure describing the rectangle. +//! \param ui32Value is the color of the rectangle. +//! +//! This function fills a rectangle on the display. The coordinates of the +//! rectangle are assumed to be within the extents of the display, and the +//! rectangle specification is fully inclusive (in other words, both i16XMin +//! and i16XMax are drawn, along with i16YMin and i16YMax). +//! +//! \return None. +// +//***************************************************************************** +static void +Kentec320x240x16_SSD2119RectFill(void *pvDisplayData, const tRectangle *psRect, + uint32_t ui32Value) +{ + int32_t i32Count; + + // + // Write the Y extents of the rectangle. + // + WriteCommand(SSD2119_ENTRY_MODE_REG); + WriteData(MAKE_ENTRY_MODE(HORIZ_DIRECTION)); + + // + // Write the X extents of the rectangle. + // + WriteCommand(SSD2119_H_RAM_START_REG); +#if (defined PORTRAIT) || (defined LANDSCAPE) + WriteData(MAPPED_X(psRect->i16XMax, psRect->i16YMax)); +#else + WriteData(MAPPED_X(psRect->i16XMin, psRect->i16YMin)); +#endif + + WriteCommand(SSD2119_H_RAM_END_REG); +#if (defined PORTRAIT) || (defined LANDSCAPE) + WriteData(MAPPED_X(psRect->i16XMin, psRect->i16YMin)); +#else + WriteData(MAPPED_X(psRect->i16XMax, psRect->i16YMax)); +#endif + + // + // Write the Y extents of the rectangle + // + WriteCommand(SSD2119_V_RAM_POS_REG); +#if (defined LANDSCAPE_FLIP) || (defined PORTRAIT) + WriteData(MAPPED_Y(psRect->i16XMin, psRect->i16YMin) | + (MAPPED_Y(psRect->i16XMax, psRect->i16YMax) << 8)); +#else + WriteData(MAPPED_Y(psRect->i16XMax, psRect->i16YMax) | + (MAPPED_Y(psRect->i16XMin, psRect->i16YMin) << 8)); +#endif + + // + // Set the display cursor to the upper left of the rectangle (in + // application coordinate space). + // + WriteCommand(SSD2119_X_RAM_ADDR_REG); + WriteData(MAPPED_X(psRect->i16XMin, psRect->i16YMin)); + WriteCommand(SSD2119_Y_RAM_ADDR_REG); + WriteData(MAPPED_Y(psRect->i16XMin, psRect->i16YMin)); + + // + // Tell the controller to write data into its RAM. + // + WriteCommand(SSD2119_RAM_DATA_REG); + + // + // Loop through the pixels of this filled rectangle. + // + for(i32Count = ((psRect->i16XMax - psRect->i16XMin + 1) * + (psRect->i16YMax - psRect->i16YMin + 1)); i32Count >= 0; + i32Count--) + { + // + // Write the pixel value. + // + WriteData(ui32Value); + } + + // + // Reset the X extents to the entire screen. + // + WriteCommand(SSD2119_H_RAM_START_REG); + WriteData(0x0000); + WriteCommand(SSD2119_H_RAM_END_REG); + WriteData(0x013f); + + // + // Reset the Y extent to the full screen + // + WriteCommand(SSD2119_V_RAM_POS_REG); + WriteData(0xef00); +} + +//***************************************************************************** +// +//! Translates a 24-bit RGB color to a display driver-specific color. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! \param ui32Value is the 24-bit RGB color. The least-significant byte is +//! the blue channel, the next byte is the green channel, and the third byte is +//! the red channel. +//! +//! This function translates a 24-bit RGB color into a value that can be +//! written into the display's frame buffer in order to reproduce that color, +//! or the closest possible approximation of that color. +//! +//! \return Returns the display-driver specific color. +// +//***************************************************************************** +static uint32_t +Kentec320x240x16_SSD2119ColorTranslate(void *pvDisplayData, uint32_t ui32Value) +{ + // + // Translate from a 24-bit RGB color to a 5-6-5 RGB color. + // + return(DPYCOLORTRANSLATE(ui32Value)); +} + +//***************************************************************************** +// +//! Flushes any cached drawing operations. +//! +//! \param pvDisplayData is a pointer to the driver-specific data for this +//! display driver. +//! +//! This functions flushes any cached drawing operations to the display. This +//! is useful when a local frame buffer is used for drawing operations, and the +//! flush would copy the local frame buffer to the display. For the SSD2119 +//! driver, the flush is a no operation. +//! +//! \return None. +// +//***************************************************************************** +static void +Kentec320x240x16_SSD2119Flush(void *pvDisplayData) +{ + // + // There is nothing to be done. + // +} + +//***************************************************************************** +// +//! The display structure that describes the driver for the Kentec K350QVG-V2-F +//! TFT panel with an SSD2119 controller. +// +//***************************************************************************** +const tDisplay g_sKentec320x240x16_SSD2119 = +{ + sizeof(tDisplay), + 0, +#if defined(PORTRAIT) || defined(PORTRAIT_FLIP) + 240, + 320, +#else + 320, + 240, +#endif + Kentec320x240x16_SSD2119PixelDraw, + Kentec320x240x16_SSD2119PixelDrawMultiple, + Kentec320x240x16_SSD2119LineDrawH, + Kentec320x240x16_SSD2119LineDrawV, + Kentec320x240x16_SSD2119RectFill, + Kentec320x240x16_SSD2119ColorTranslate, + Kentec320x240x16_SSD2119Flush +}; + +//***************************************************************************** +// +//! Initializes the display driver. +//! +//! \param ui32SysClock is the frequency of the system clock. +//! +//! This function initializes the LCD controller and the SSD2119 display +//! controller on the panel, preparing it to display data. +//! +//! \return None. +// +//***************************************************************************** +void +Kentec320x240x16_SSD2119Init(uint32_t ui32SysClock) +{ + uint32_t ui32ClockMS, ui32Count; + tLCDIDDTiming sTimings; + + // + // Determine the number of system clock cycles in 1mS + // + ui32ClockMS = CYCLES_FROM_TIME_US(ui32SysClock, 1000); + + // + // Divide by 3 to get the number of SysCtlDelay loops in 1mS. + // + ui32ClockMS /= 3; + + // + // Enable the LCD controller. + // + SysCtlPeripheralEnable(SYSCTL_PERIPH_LCD0); + + // + // Assert the LCD reset signal. + // + GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, 0); + + // + // Delay for 50ms. + // + SysCtlDelay(50 * ui32ClockMS); + + // + // Deassert the LCD reset signal. + // + GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, GPIO_PIN_6); + + // + // Delay for 50ms while the LCD comes out of reset. + // + SysCtlDelay(50 * ui32ClockMS); + + // + // Configure the LCD controller for LIDD-mode operation. + // + LCDModeSet(LCD0_BASE, LCD_MODE_LIDD, ui32SysClock, ui32SysClock); + + // + // Configure DMA-related parameters. + // + LCDDMAConfigSet(LCD0_BASE, LCD_DMA_BURST_4); + + // + // Set control signal parameters and polarities. + // + LCDIDDConfigSet(LCD0_BASE, LIDD_CONFIG_ASYNC_MPU80); + + // + // Set the LIDD interface timings for the Kentec display. Note that the + // inter-transaction delay is set at at 50nS to match the write case. + // Software needs to ensure that it delays at least 450nS more between each + // read or the read timings will be violated. + // + sTimings.ui8WSSetup = CYCLES_FROM_TIME_NS(ui32SysClock, 5); + sTimings.ui8WSDuration = CYCLES_FROM_TIME_NS(ui32SysClock, 40); + sTimings.ui8WSHold = CYCLES_FROM_TIME_NS(ui32SysClock, 5); + sTimings.ui8RSSetup = CYCLES_FROM_TIME_NS(ui32SysClock, 0); + sTimings.ui8RSDuration = CYCLES_FROM_TIME_NS(ui32SysClock, 500); + sTimings.ui8RSHold = CYCLES_FROM_TIME_NS(ui32SysClock, 100); + sTimings.ui8DelayCycles = CYCLES_FROM_TIME_NS(ui32SysClock, 50); + LCDIDDTimingSet(LCD0_BASE, 0, &sTimings); + + // + // Enter sleep mode (if not already there). + // + WriteCommand(SSD2119_SLEEP_MODE_1_REG); + WriteData(0x0001); + + // + // Set initial power parameters. + // + WriteCommand(SSD2119_PWR_CTRL_5_REG); + WriteData(0x00b2); + WriteCommand(SSD2119_VCOM_OTP_1_REG); + WriteData(0x0006); + + // + // Start the oscillator. + // + WriteCommand(SSD2119_OSC_START_REG); + WriteData(0x0001); + + // + // Set pixel format and basic display orientation (scanning direction). + // + WriteCommand(SSD2119_OUTPUT_CTRL_REG); + WriteData(0x30ef); + WriteCommand(SSD2119_LCD_DRIVE_AC_CTRL_REG); + WriteData(0x0600); + + // + // Exit sleep mode. + // + WriteCommand(SSD2119_SLEEP_MODE_1_REG); + WriteData(0x0000); + + // + // Delay 30mS + // + SysCtlDelay(30 * ui32ClockMS); + + // + // Configure pixel color format and MCU interface parameters. + // + WriteCommand(SSD2119_ENTRY_MODE_REG); + WriteData(ENTRY_MODE_DEFAULT); + + // + // Set analog parameters. + // + WriteCommand(SSD2119_SLEEP_MODE_2_REG); + WriteData(0x0999); + WriteCommand(SSD2119_ANALOG_SET_REG); + WriteData(0x3800); + + // + // Enable the display. + // + WriteCommand(SSD2119_DISPLAY_CTRL_REG); + WriteData(0x0033); + + // + // Set VCIX2 voltage to 6.1V. + // + WriteCommand(SSD2119_PWR_CTRL_2_REG); + WriteData(0x0005); + + // + // Configure gamma correction. + // + WriteCommand(SSD2119_GAMMA_CTRL_1_REG); + WriteData(0x0000); + WriteCommand(SSD2119_GAMMA_CTRL_2_REG); + WriteData(0x0303); + WriteCommand(SSD2119_GAMMA_CTRL_3_REG); + WriteData(0x0407); + WriteCommand(SSD2119_GAMMA_CTRL_4_REG); + WriteData(0x0301); + WriteCommand(SSD2119_GAMMA_CTRL_5_REG); + WriteData(0x0301); + WriteCommand(SSD2119_GAMMA_CTRL_6_REG); + WriteData(0x0403); + WriteCommand(SSD2119_GAMMA_CTRL_7_REG); + WriteData(0x0707); + WriteCommand(SSD2119_GAMMA_CTRL_8_REG); + WriteData(0x0400); + WriteCommand(SSD2119_GAMMA_CTRL_9_REG); + WriteData(0x0a00); + WriteCommand(SSD2119_GAMMA_CTRL_10_REG); + WriteData(0x1000); + + // + // Configure Vlcd63 and VCOMl. + // + WriteCommand(SSD2119_PWR_CTRL_3_REG); + WriteData(0x000a); + WriteCommand(SSD2119_PWR_CTRL_4_REG); + WriteData(0x2e00); + + // + // Set the display size and ensure that the GRAM window is set to allow + // access to the full display buffer. + // + WriteCommand(SSD2119_V_RAM_POS_REG); + WriteData((LCD_VERTICAL_MAX-1) << 8); + WriteCommand(SSD2119_H_RAM_START_REG); + WriteData(0x0000); + WriteCommand(SSD2119_H_RAM_END_REG); + WriteData(LCD_HORIZONTAL_MAX-1); + WriteCommand(SSD2119_X_RAM_ADDR_REG); + WriteData(0x0000); + WriteCommand(SSD2119_Y_RAM_ADDR_REG); + WriteData(0x0000); + + // + // Clear the contents of the display buffer. + // + WriteCommand(SSD2119_RAM_DATA_REG); + for(ui32Count = 0; ui32Count < (320 * 240); ui32Count++) + { + WriteData(0x0000); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.h b/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.h new file mode 100644 index 0000000..fa3fd02 --- /dev/null +++ b/boards/dk-tm4c129x/drivers/kentec320x240x16_ssd2119.h @@ -0,0 +1,58 @@ +//***************************************************************************** +// +// kentec320x240x16_ssd2119.h - Prototypes for the display driver for the +// Kentec K350QVG-V2-F TFT display attached to the +// LCD controller via an 8-bit LIDD interface. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __DRIVERS_KENTEC320X240X16_SSD2119_H__ +#define __DRIVERS_KENTEC320X240X16_SSD2119_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern const tDisplay g_sKentec320x240x16_SSD2119; +extern void Kentec320x240x16_SSD2119Init(uint32_t ui32SysClock); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_KENTEC320X240X16_SSD2119_H__ diff --git a/boards/dk-tm4c129x/drivers/mx66l51235f.c b/boards/dk-tm4c129x/drivers/mx66l51235f.c new file mode 100644 index 0000000..084ee1d --- /dev/null +++ b/boards/dk-tm4c129x/drivers/mx66l51235f.c @@ -0,0 +1,534 @@ +//***************************************************************************** +// +// mx66l51235f.c - Driver for the on-board SPI flash. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "driverlib/gpio.h" +#include "driverlib/rom.h" +#include "driverlib/ssi.h" +#include "utils/spi_flash.h" + +//***************************************************************************** +// +//! \addtogroup mx66l51235f_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The current value of the extended address register. This is tracked so that +// it is only updated via SPI when it needs to be changed. +// +//***************************************************************************** +static uint32_t g_ui32MX66L51235FAddr; + +//***************************************************************************** +// +//! Initializes the MX66L51235F driver. +//! +//! \param ui32SysClock is the frequency of the system clock. +//! +//! This function initializes the MX66L51235F driver and SSI interface, +//! preparing for accesses to the SPI flash device. Since the SSI interface +//! on the DK-TM4C129X board is shared with the SD card, this must be called +//! prior to any SPI flash access the immediately follows an SD card access. +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FInit(uint32_t ui32SysClock) +{ + uint32_t ui32SPIClock; + + // + // Set the SPI clock to the minimum of one quarter of system clock and + // 12.5 MHz. The SPI module can run at up to one quarter of system clock + // and the SD card, if inserted, might cause interference on the SPI bus + // (even though it is not selected) if the SPI clock exceeds 12.5 MHz. + // + ui32SPIClock = ui32SysClock / 4; + if(ui32SPIClock > 12500000) + { + ui32SPIClock = 12500000; + } + + // + // Configure the SPI flash driver on SSI3. + // + ROM_SPIFlashInit(SSI3_BASE, ui32SysClock, ui32SPIClock); + + // + // Set the current value of the extended address register to -1, causing it + // to be written on the first access. + // + g_ui32MX66L51235FAddr = 0xffffffff; +} + +//***************************************************************************** +// +// Enable program/erase of the MX66L51235F. +// +//***************************************************************************** +static void +MX66L51235FWriteEnable(void) +{ + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Enable programming/erasing of the MX66L51235F. + // + ROM_SPIFlashWriteEnable(SSI3_BASE); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); +} + +//***************************************************************************** +// +// Waits until a program/erase operation has completed. +// +//***************************************************************************** +static void +MX66L51235FWait(void) +{ + uint8_t ui8Status; + + // + // Loop until the requested operation has completed. + // + do + { + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Read the status register. + // + ui8Status = ROM_SPIFlashReadStatus(SSI3_BASE); + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + } + while(ui8Status & 1); +} + +//***************************************************************************** +// +// Writes the extended address register, allowing the full contents of the +// MX66L51235F to be accessed. +// +//***************************************************************************** +static void +MX66L51235FWriteEAR(uint32_t ui32Addr) +{ + // + // See if the extended address register needs to be written. + // + if((ui32Addr & 0xff000000) == (g_ui32MX66L51235FAddr & 0xff000000)) + { + // + // The extended address register does not need to be changed, so return + // without doing anything. + // + return; + } + + // + // Save the new value of the extended address register. + // + g_ui32MX66L51235FAddr = ui32Addr; + + // + // Enable program/erase of the SPI flash. + // + MX66L51235FWriteEnable(); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Set the SSI module into write-only mode. + // + ROM_SSIAdvModeSet(SSI3_BASE, SSI_ADV_MODE_WRITE); + + // + // Send the sector erase command. + // + ROM_SSIDataPut(SSI3_BASE, 0xc5); + + // + // Send the address of the sector to be erased, marking the last byte of + // the address as the end of the frame. + // + ROM_SSIAdvDataPutFrameEnd(SSI3_BASE, (ui32Addr >> 24) & 0xff); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); +} + +//***************************************************************************** +// +//! Erases a 4 KB sector of the MX66L51235F. +//! +//! \param ui32Addr is the address of the sector to erase. +//! +//! This function erases a sector of the MX66L51235F. Each sector is 4 KB with +//! a 4 KB alignment; the MX66L51235F will ignore the lower ten bits of the +//! address provided. This function will not return until the data has be +//! erased. +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FSectorErase(uint32_t ui32Addr) +{ + // + // Write the extended address register. + // + MX66L51235FWriteEAR(ui32Addr); + + // + // Enable program/erase of the SPI flash. + // + MX66L51235FWriteEnable(); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Erase the requested sector. + // + ROM_SPIFlashSectorErase(SSI3_BASE, ui32Addr); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + + // + // Wait for the erase operation to complete. + // + MX66L51235FWait(); +} + +//***************************************************************************** +// +//! Erases a 32 KB block of the MX66L51235F. +//! +//! \param ui32Addr is the address of the block to erase. +//! +//! This function erases a 32 KB block of the MX66L51235F. Each 32 KB block +//! has a 32 KB alignment; the MX66L51235F will ignore the lower 15 bits of the +//! address provided. This function will not return until the data has be +//! erased. +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FBlockErase32(uint32_t ui32Addr) +{ + // + // Write the extended address register. + // + MX66L51235FWriteEAR(ui32Addr); + + // + // Enable program/erase of the SPI flash. + // + MX66L51235FWriteEnable(); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Erase the requested block. + // + ROM_SPIFlashBlockErase32(SSI3_BASE, ui32Addr); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + + // + // Wait for the erase operation to complete. + // + MX66L51235FWait(); +} + +//***************************************************************************** +// +//! Erases a 64 KB block of the MX66L51235F. +//! +//! \param ui32Addr is the address of the block to erase. +//! +//! This function erases a 64 KB block of the MX66L51235F. Each 64 KB block +//! has a 64 KB alignment; the MX66L51235F will ignore the lower 16 bits of the +//! address provided. This function will not return until the data has be +//! erased. +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FBlockErase64(uint32_t ui32Addr) +{ + // + // Write the extended address register. + // + MX66L51235FWriteEAR(ui32Addr); + + // + // Enable program/erase of the SPI flash. + // + MX66L51235FWriteEnable(); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Erase the requested block. + // + ROM_SPIFlashBlockErase64(SSI3_BASE, ui32Addr); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + + // + // Wait for the erase operation to complete. + // + MX66L51235FWait(); +} + +//***************************************************************************** +// +//! Erases the entire MX66L51235F. +//! +//! This command erase the entire contents of the MX66L51235F. This takes two +//! minutes, nominally, to complete. This function will not return until the +//! data has be erased. +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FChipErase(void) +{ + // + // Enable program/erase of the SPI flash. + // + MX66L51235FWriteEnable(); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Erase the entire device. + // + ROM_SPIFlashChipErase(SSI3_BASE); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + + // + // Wait for the erase operation to complete. + // + MX66L51235FWait(); +} + +//***************************************************************************** +// +//! Programs the MX66L51235F. +//! +//! \param ui32Addr is the address to be programmed. +//! \param pui8Data is a pointer to the data to be programmed. +//! \param ui32Count is the number of bytes to be programmed. +//! +//! This function programs data into the MX66L51235F. This function will not +//! return until the data has be programmed. The addresses to be programmed +//! must not span a 256-byte boundary (in other words, ``\e ui32Addr & ~255'' +//! must be the same as ``(\e ui32Addr + \e ui32Count) & ~255''). +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FPageProgram(uint32_t ui32Addr, const uint8_t *pui8Data, + uint32_t ui32Count) +{ + // + // Write the extended address register. + // + MX66L51235FWriteEAR(ui32Addr); + + // + // Enable program/erase of the SPI flash. + // + MX66L51235FWriteEnable(); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Program the requested data. + // + ROM_SPIFlashPageProgram(SSI3_BASE, ui32Addr, pui8Data, ui32Count); + + // + // Wait until the command has been completely transmitted. + // + while(ROM_SSIBusy(SSI3_BASE)) + { + } + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + + // + // Wait for the page program operation to complete. + // + MX66L51235FWait(); +} + +//***************************************************************************** +// +//! Reads data from the MX66L51235F. +//! +//! \param ui32Addr is the address to read. +//! \param pui8Data is a pointer to the data buffer to into which to read the +//! data. +//! \param ui32Count is the number of bytes to read. +//! +//! This function reads data from the MX66L51235F. +//! +//! \return None. +// +//***************************************************************************** +void +MX66L51235FRead(uint32_t ui32Addr, uint8_t *pui8Data, uint32_t ui32Count) +{ + // + // Write the extended address register. + // + MX66L51235FWriteEAR(ui32Addr); + + // + // Assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); + + // + // Read the requested data. + // + ROM_SPIFlashRead(SSI3_BASE, ui32Addr, pui8Data, ui32Count); + + // + // De-assert the chip select to the MX66L51235F. + // + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/mx66l51235f.h b/boards/dk-tm4c129x/drivers/mx66l51235f.h new file mode 100644 index 0000000..fe18d3d --- /dev/null +++ b/boards/dk-tm4c129x/drivers/mx66l51235f.h @@ -0,0 +1,71 @@ +//***************************************************************************** +// +// mx66l51235f.h - Prototypes for the MX66L51235F driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __DRIVERS_MX66L51235F_H__ +#define __DRIVERS_MX66L51235F_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The memory size and block size in bytes. +// +//***************************************************************************** +#define MX66L51235F_MEMORY_SIZE 0x04000000 +#define MX66L51235F_BLOCK_SIZE 0x1000 + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void MX66L51235FInit(uint32_t ui32SysClock); +extern void MX66L51235FSectorErase(uint32_t ui32Addr); +extern void MX66L51235FBlockErase32(uint32_t ui32Addr); +extern void MX66L51235FBlockErase64(uint32_t ui32Addr); +extern void MX66L51235FChipErase(void); +extern void MX66L51235FPageProgram(uint32_t ui32Addr, const uint8_t *pui8Data, + uint32_t ui32Count); +extern void MX66L51235FRead(uint32_t ui32Addr, uint8_t *pui8Data, + uint32_t ui32Count); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_MX66L51235F_H__ diff --git a/boards/dk-tm4c129x/drivers/pinout.c b/boards/dk-tm4c129x/drivers/pinout.c new file mode 100644 index 0000000..12a4ddc --- /dev/null +++ b/boards/dk-tm4c129x/drivers/pinout.c @@ -0,0 +1,282 @@ +//***************************************************************************** +// +// pinout.c - Function to configure the device pins on the DK-TM4C129X. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_gpio.h" +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "driverlib/gpio.h" +#include "driverlib/pin_map.h" +#include "driverlib/rom.h" +#include "driverlib/sysctl.h" +#include "drivers/pinout.h" + +//***************************************************************************** +// +//! \addtogroup pinout_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +//! Configures the device pins for the standard usages on the DK-TM4C129X. +//! +//! This function enables the GPIO modules and configures the device pins for +//! the default, standard usages on the DK-TM4C129X. Applications that require +//! alternate configurations of the device pins can either not call this +//! function and take full responsibility for configuring all the device pins, +//! or can reconfigure the required device pins after calling this function. +//! +//! \return None. +// +//***************************************************************************** +void +PinoutSet(void) +{ + // + // Enable all the GPIO peripherals. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT); + + // + // PA0-1 are used for UART0. + // + ROM_GPIOPinConfigure(GPIO_PA0_U0RX); + ROM_GPIOPinConfigure(GPIO_PA1_U0TX); + ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); + + // + // PA2-5 are used for SSI0 to the second booster pack. + // + ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK); + ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS); + ROM_GPIOPinConfigure(GPIO_PA4_SSI0XDAT0); + ROM_GPIOPinConfigure(GPIO_PA5_SSI0XDAT1); + + // + // PB0-1/PD6-7/PL6-7 are used for USB. + // + HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTD_BASE + GPIO_O_CR) = 0xff; + ROM_GPIOPinConfigure(GPIO_PD6_USB0EPEN); + ROM_GPIOPinConfigure(GPIO_PD7_USB0PFLT); + ROM_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1); + ROM_GPIOPinTypeUSBDigital(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7); + ROM_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7); + + // + // PB2/PD4 are used for the speaker output. + // + ROM_GPIOPinConfigure(GPIO_PB2_T5CCP0); + ROM_GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_2); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_4); + ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_4, 0); + + // + // PB6-7 are used for I2C to the TMP100 and the EM connector. + // + ROM_GPIOPinConfigure(GPIO_PB6_I2C6SCL); + ROM_GPIOPinConfigure(GPIO_PB7_I2C6SDA); + ROM_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_6); + ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7); + + // + // PE5/PN3/PP1 are used for the push buttons. + // + ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_5); + ROM_GPIOPinTypeGPIOInput(GPIO_PORTN_BASE, GPIO_PIN_3); + ROM_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_1); + + // + // PE7/PP7/PT2-3 are used for the touch screen. + // + HWREG(GPIO_PORTE_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; + HWREG(GPIO_PORTE_BASE + GPIO_O_CR) = 0xff; + ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_7); + ROM_GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_7); + ROM_GPIOPinTypeGPIOInput(GPIO_PORTT_BASE, GPIO_PIN_2 | GPIO_PIN_3); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_7); + ROM_GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_7, 0); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_7); + ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_7, 0); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTT_BASE, GPIO_PIN_2 | GPIO_PIN_3); + ROM_GPIOPinWrite(GPIO_PORTT_BASE, GPIO_PIN_2 | GPIO_PIN_3, 0); + + // + // PF0/PF4-5/PH4/PQ0-2 are used for the SPI flash (on-board and SD card). + // PH4 selects the SD card and PQ1 selects the on-board SPI flash. + // + ROM_GPIOPinConfigure(GPIO_PF0_SSI3XDAT1); + ROM_GPIOPinConfigure(GPIO_PF4_SSI3XDAT2); + ROM_GPIOPinConfigure(GPIO_PF5_SSI3XDAT3); + ROM_GPIOPinConfigure(GPIO_PQ0_SSI3CLK); + ROM_GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0); + ROM_GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4 | GPIO_PIN_5); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_4); + ROM_GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_4, GPIO_PIN_4); + ROM_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0 | GPIO_PIN_2); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_1); + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, GPIO_PIN_1); + + // + // PF1/PK4/PK6 are used for Ethernet LEDs. + // + ROM_GPIOPinConfigure(GPIO_PF1_EN0LED2); + ROM_GPIOPinConfigure(GPIO_PK4_EN0LED0); + ROM_GPIOPinConfigure(GPIO_PK6_EN0LED1); + GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_1); + GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4); + GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_6); + + // + // PF6-7/PJ6/PS4-5/PR0-7 are used for the LCD. + // + ROM_GPIOPinConfigure(GPIO_PF7_LCDDATA02); + ROM_GPIOPinConfigure(GPIO_PJ6_LCDAC); + ROM_GPIOPinConfigure(GPIO_PR0_LCDCP); + ROM_GPIOPinConfigure(GPIO_PR1_LCDFP); + ROM_GPIOPinConfigure(GPIO_PR2_LCDLP); + ROM_GPIOPinConfigure(GPIO_PR3_LCDDATA03); + ROM_GPIOPinConfigure(GPIO_PR4_LCDDATA00); + ROM_GPIOPinConfigure(GPIO_PR5_LCDDATA01); + ROM_GPIOPinConfigure(GPIO_PR6_LCDDATA04); + ROM_GPIOPinConfigure(GPIO_PR7_LCDDATA05); + ROM_GPIOPinConfigure(GPIO_PS4_LCDDATA06); + ROM_GPIOPinConfigure(GPIO_PS5_LCDDATA07); + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6); + ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, GPIO_PIN_6); + GPIOPinTypeLCD(GPIO_PORTF_BASE, GPIO_PIN_7); + GPIOPinTypeLCD(GPIO_PORTJ_BASE, GPIO_PIN_6); + GPIOPinTypeLCD(GPIO_PORTR_BASE, + (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | + GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7)); + GPIOPinTypeLCD(GPIO_PORTS_BASE, GPIO_PIN_4 | GPIO_PIN_5); + + // + // PQ7 is used for the user LED. + // + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_7); + ROM_GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_7, 0); +} + +//***************************************************************************** +// +//! Configures the USB pins for ULPI connection to an external USB PHY. +//! +//! This function configures the USB ULPI pins to connect the DK-TM4C129X board +//! to an external USB PHY in ULPI mode. This allows the external PHY to act +//! as an external high-speed phy for the DK-TM4C129X. This function must be +//! called after the call to PinoutSet() to properly configure the pins. +//! +//! \return None. +// +//***************************************************************************** +#ifdef USE_ULPI +void +USBULPIPinoutSet(void) +{ + // + // Enable all the peripherals that are used by the ULPI interface. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP); + + // + // ULPI Port B pins. + // + ROM_GPIOPinConfigure(GPIO_PB2_USB0STP); + ROM_GPIOPinConfigure(GPIO_PB3_USB0CLK); + ROM_GPIOPinTypeUSBDigital(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3); + GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3, + GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); + + // + // ULPI Port P pins. + // + ROM_GPIOPinConfigure(GPIO_PP2_USB0NXT); + ROM_GPIOPinConfigure(GPIO_PP3_USB0DIR); + ROM_GPIOPinConfigure(GPIO_PP4_USB0D7); + ROM_GPIOPinConfigure(GPIO_PP5_USB0D6); + ROM_GPIOPinTypeUSBDigital(GPIO_PORTP_BASE, GPIO_PIN_2 | GPIO_PIN_3 | + GPIO_PIN_4 | GPIO_PIN_5); + GPIOPadConfigSet(GPIO_PORTP_BASE, + GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5, + GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); + + // + // ULPI Port L pins. + // + ROM_GPIOPinConfigure(GPIO_PL5_USB0D5); + ROM_GPIOPinConfigure(GPIO_PL4_USB0D4); + ROM_GPIOPinConfigure(GPIO_PL3_USB0D3); + ROM_GPIOPinConfigure(GPIO_PL2_USB0D2); + ROM_GPIOPinConfigure(GPIO_PL1_USB0D1); + ROM_GPIOPinConfigure(GPIO_PL0_USB0D0); + ROM_GPIOPinTypeUSBDigital(GPIO_PORTL_BASE, GPIO_PIN_0 | GPIO_PIN_1 | + GPIO_PIN_2 | GPIO_PIN_3 | + GPIO_PIN_4 | GPIO_PIN_5); + GPIOPadConfigSet(GPIO_PORTL_BASE, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | + GPIO_PIN_4 | GPIO_PIN_5, + GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); + // + // ULPI Port M pins used to control the external USB oscillator and the + // external USB phy on the DK-TM4C129X-DPHY board. + // + // PM1 - Enables the USB oscillator on the DK-TM4C129X-DPHY board. + // PM3 - Enables the USB phy on the DK-TM4C129X-DPHY board. + // + ROM_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_1 | GPIO_PIN_3); + ROM_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1 | GPIO_PIN_3, GPIO_PIN_1 | + GPIO_PIN_3); +} +#endif + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/pinout.h b/boards/dk-tm4c129x/drivers/pinout.h new file mode 100644 index 0000000..802d9fe --- /dev/null +++ b/boards/dk-tm4c129x/drivers/pinout.h @@ -0,0 +1,59 @@ +//***************************************************************************** +// +// pinout.h - Prototype for the function to configure the device pins on the +// DK-TM4C129X. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __DRIVERS_PINOUT_H__ +#define __DRIVERS_PINOUT_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void PinoutSet(void); +#ifdef USE_ULPI +extern void USBULPIPinoutSet(void); +#endif + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_PINOUT_H__ diff --git a/boards/dk-tm4c129x/drivers/sound.c b/boards/dk-tm4c129x/drivers/sound.c new file mode 100644 index 0000000..56f84e0 --- /dev/null +++ b/boards/dk-tm4c129x/drivers/sound.c @@ -0,0 +1,688 @@ +//***************************************************************************** +// +// sound.c - Sound driver for the speaker on the DK-TM4C129X. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "inc/hw_timer.h" +#include "inc/hw_types.h" +#include "driverlib/gpio.h" +#include "driverlib/interrupt.h" +#include "driverlib/rom.h" +#include "driverlib/sysctl.h" +#include "driverlib/timer.h" +#include "drivers/sound.h" + +//***************************************************************************** +// +//! \addtogroup sound_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// This structure defines the internal state of the sound driver. +// +//***************************************************************************** +typedef struct +{ + // + // The number of clocks per PWM period. + // + uint32_t ui32Period; + + // + // A set of flags indicating the mode of the sound driver. + // + volatile uint32_t ui32Flags; + + // + // A pointer to the sound buffer being played. + // + const int16_t *pi16Buffer; + + // + // The length of the sound buffer, in bytes. + // + uint32_t ui32Length; + + // + // The current playback offset into the sound buffer. + // + uint32_t ui32Offset; + + // + // The volume to playback the sound stream. This is a value between 0 + // (for silence) and 256 (for full volume). + // + int32_t i32Volume; + + // + // The previous and current sound samples, used for interpolating from + // 8 kHz to 64 kHz sound. + // + int16_t pi16Samples[2]; + + // + // The sound step, which corresponds to the current interpolation point + // between the previous and current sound samples. + // + int32_t i32Step; + + // + // The current requested rate adjustment. This is cleared when the + // the adjustment is made. + // + int32_t i32RateAdjust; + + // + // The callback function that indicates when half of the sound buffer has + // bene played and is therefore ready to be refilled. + // + void (*pfnCallback)(uint32_t ui32Half); +} +tSoundState; + +//***************************************************************************** +// +// The flags that are in tSoundState.ui32Flags. +// +//***************************************************************************** +#define SOUND_FLAG_STARTUP 0 +#define SOUND_FLAG_SHUTDOWN 1 +#define SOUND_FLAG_PLAY 2 +#define SOUND_FLAG_8KHZ 3 +#define SOUND_FLAG_16KHZ 4 +#define SOUND_FLAG_32KHZ 5 +#define SOUND_FLAG_64KHZ 6 + +//***************************************************************************** +// +// The current state of the sound driver. +// +//***************************************************************************** +static tSoundState g_sSoundState; + +//***************************************************************************** +// +//! Handles the TIMER5A interrupt. +//! +//! This function responds to the TIMER5A interrupt, updating the duty cycle of +//! the output waveform in order to produce sound. It is the application's +//! responsibility to ensure that this function is called in response to the +//! TIMER5A interrupt, typically by installing it in the vector table as the +//! handler for the TIMER5A interrupt. +//! +//! \return None. +// +//***************************************************************************** +void +SoundIntHandler(void) +{ + int32_t i32DutyCycle; + + // + // If there is an adjustment to be made, the apply it and set allow the + // update to be done on the next load. + // + if(g_sSoundState.i32RateAdjust) + { + g_sSoundState.ui32Period += g_sSoundState.i32RateAdjust; + g_sSoundState.i32RateAdjust = 0; + TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period); + } + + // + // Clear the timer interrupt. + // + ROM_TimerIntClear(TIMER5_BASE, TIMER_CAPA_EVENT); + + // + // See if the startup ramp is in progress. + // + if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP)) + { + // + // Increment the ramp count. + // + g_sSoundState.i32Step++; + + // + // Increase the pulse width of the output by one clock. + // + ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.i32Step); + + // + // See if this was the last step of the ramp. + // + if(g_sSoundState.i32Step >= (g_sSoundState.ui32Period / 2)) + { + // + // Indicate that the startup ramp has completed. + // + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP) = 0; + + // + // Set the step back to zero for the start of audio playback. + // + g_sSoundState.i32Step = 0; + } + + // + // There is nothing further to be done. + // + return; + } + + // + // See if the shutdown ramp is in progress. + // + if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN)) + { + // + // See if this was the last step of the ramp. + // + if(g_sSoundState.i32Step == 1) + { + // + // Disable the output signals. + // + ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period); + + // + // Clear the sound flags. + // + g_sSoundState.ui32Flags = 0; + + // + // Disable the speaker amp. + // + ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_4, 0); + } + else + { + // + // Decrement the ramp count. + // + g_sSoundState.i32Step--; + + // + // Decrease the pulse width of the output by one clock. + // + ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.i32Step); + } + + // + // There is nothing further to be done. + // + return; + } + + // + // Compute the value of the PCM sample based on the blended average of the + // previous and current samples. It should be noted that linear + // interpolation does not produce the best results with sound (it produces + // a significant amount of harmonic aliasing) but it is fast. + // + i32DutyCycle = + (((g_sSoundState.pi16Samples[0] * (8 - g_sSoundState.i32Step)) + + (g_sSoundState.pi16Samples[1] * g_sSoundState.i32Step)) / 8); + + // + // Adjust the magnitude of the sample based on the current volume. Since a + // multiplicative volume control is implemented, the volume value + // results in nearly linear volume adjustment if it is squared. + // + i32DutyCycle = (((i32DutyCycle * g_sSoundState.i32Volume * + g_sSoundState.i32Volume) / 65536) + 32768); + + // + // Set the PWM duty cycle based on this PCM sample. + // + i32DutyCycle = (g_sSoundState.ui32Period * i32DutyCycle) / 65536; + ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, i32DutyCycle); + + // + // Increment the sound step based on the sample rate. + // + if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_8KHZ)) + { + g_sSoundState.i32Step = (g_sSoundState.i32Step + 1) & 7; + } + else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_16KHZ)) + { + g_sSoundState.i32Step = (g_sSoundState.i32Step + 2) & 7; + } + else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_32KHZ)) + { + g_sSoundState.i32Step = (g_sSoundState.i32Step + 4) & 7; + } + + // + // See if the next sample has been reached. + // + if(g_sSoundState.i32Step == 0) + { + // + // Copy the current sample to the previous sample. + // + g_sSoundState.pi16Samples[0] = g_sSoundState.pi16Samples[1]; + + // + // Get the next sample from the buffer. + // + g_sSoundState.pi16Samples[1] = + g_sSoundState.pi16Buffer[g_sSoundState.ui32Offset]; + + // + // Increment the buffer pointer. + // + g_sSoundState.ui32Offset++; + if(g_sSoundState.ui32Offset == g_sSoundState.ui32Length) + { + g_sSoundState.ui32Offset = 0; + } + + // + // Call the callback function if one of the half-buffers has been + // consumed. + // + if(g_sSoundState.pfnCallback) + { + if(g_sSoundState.ui32Offset == 0) + { + g_sSoundState.pfnCallback(1); + } + else if(g_sSoundState.ui32Offset == (g_sSoundState.ui32Length / 2)) + { + g_sSoundState.pfnCallback(0); + } + } + } +} + +//***************************************************************************** +// +//! Initializes the sound driver. +//! +//! \param ui32SysClock is the frequency of the system clock. +//! +//! This function initializes the sound driver, preparing it to output sound +//! data to the speaker. +//! +//! The system clock should be as high as possible; lower clock rates reduces +//! the quality of the produced sound. For the best quality sound, the system +//! should be clocked at 120 MHz. +//! +//! \note In order for the sound driver to function properly, the sound driver +//! interrupt handler (SoundIntHandler()) must be installed into the vector +//! table for the timer 5 subtimer A interrupt. +//! +//! \return None. +// +//***************************************************************************** +void +SoundInit(uint32_t ui32SysClock) +{ + // + // Enable the peripherals used by the sound driver. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5); + + // + // Compute the PWM period based on the system clock. + // + g_sSoundState.ui32Period = ui32SysClock / 64000; + + // + // Set the default volume. + // + g_sSoundState.i32Volume = 255; + + // + // Configure the timer to run in PWM mode. + // + if((HWREG(TIMER5_BASE + TIMER_O_CTL) & TIMER_CTL_TBEN) == 0) + { + ROM_TimerConfigure(TIMER5_BASE, (TIMER_CFG_SPLIT_PAIR | + TIMER_CFG_A_PWM | + TIMER_CFG_B_PERIODIC)); + } + ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period - 1); + ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period); + ROM_TimerControlLevel(TIMER5_BASE, TIMER_A, true); + + // + // Update the timer values on timeouts and not immediately. + // + TimerUpdateMode(TIMER5_BASE, TIMER_A, TIMER_UP_LOAD_TIMEOUT | + TIMER_UP_MATCH_TIMEOUT); + + // + // Configure the timer to generate an interrupt at every time-out event. + // + ROM_TimerIntEnable(TIMER5_BASE, TIMER_CAPA_EVENT); + + // + // Enable the timer. At this point, the timer generates an interrupt + // every 15.625 us. + // + ROM_TimerEnable(TIMER5_BASE, TIMER_A); + ROM_IntEnable(INT_TIMER5A); + + // + // Clear the sound flags. + // + g_sSoundState.ui32Flags = 0; +} + +//***************************************************************************** +// +//! Make adjustments to the sample period of the PWM audio. +//! +//! \param i32RateAdjust is a signed value of the adjustment to make to the +//! current sample period. +//! +//! This function allows the sample period to be adjusted if the application +//! needs to make small adjustments to the playback rate of the audio. This +//! should only be used to makke smaller adjustments to the sample rate since +//! large changes cause distortion in the output. +//! +//! \return None. +// +//***************************************************************************** +void +SoundPeriodAdjust(int32_t i32RateAdjust) +{ + g_sSoundState.i32RateAdjust += i32RateAdjust; +} + +//***************************************************************************** +// +//! Starts playback of a sound stream. +//! +//! \param pi16Buffer is a pointer to the buffer that contains the sound to +//! play. +//! \param ui32Length is the length of the buffer in samples. This should be +//! a multiple of two. +//! \param ui32Rate is the sound playback rate; valid values are 8000, 16000, +//! 32000, and 64000. +//! \param pfnCallback is the callback function that is called when either half +//! of the sound buffer has been played. +//! +//! This function starts the playback of a sound stream contained in an +//! audio ping-pong buffer. The buffer is played repeatedly until +//! SoundStop() is called. Playback of the sound stream begins +//! immediately, so the buffer should be pre-filled with the initial sound +//! data prior to calling this function. +//! +//! \return Returns \b true if playback was started and \b false if it could +//! not be started (because something is already playing). +// +//***************************************************************************** +bool +SoundStart(int16_t *pi16Buffer, uint32_t ui32Length, uint32_t ui32Rate, + void (*pfnCallback)(uint32_t ui32Half)) +{ + // + // Return without playing the buffer if something is already playing. + // + if(g_sSoundState.ui32Flags) + { + return(false); + } + + // + // Set the sample rate flag. + // + if(ui32Rate == 8000) + { + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_8KHZ) = 1; + } + else if(ui32Rate == 16000) + { + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_16KHZ) = 1; + } + else if(ui32Rate == 32000) + { + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_32KHZ) = 1; + } + else if(ui32Rate == 64000) + { + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_64KHZ) = 1; + } + else + { + return(false); + } + + // + // Enable the speaker amp. + // + ROM_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_4, GPIO_PIN_4); + + // + // Save the pointer to the buffer. + // + g_sSoundState.pi16Buffer = pi16Buffer; + g_sSoundState.ui32Length = ui32Length; + + // + // Save the pointer to the callback function. + // + g_sSoundState.pfnCallback = pfnCallback; + + // + // Start playback from the beginning of the buffer. + // + g_sSoundState.ui32Offset = 0; + + // + // Initialize the sample buffer with silence. + // + g_sSoundState.pi16Samples[0] = 0; + g_sSoundState.pi16Samples[1] = 0; + + // + // Start playback of the stream. + // + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP) = 1; + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_PLAY) = 1; + + // + // Set the step for the startup ramp. + // + g_sSoundState.i32Step = 1; + + // + // Enable the timer interrupt. + // + ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, 1); + + // + // Success. + // + return(true); +} + +//***************************************************************************** +// +//! Stops playback of the current sound stream. +//! +//! This function immediately stops playback of the current sound stream. As +//! a result, the output is changed directly to the mid-point, possibly +//! resulting in a pop or click. It is then ramped down to no output, +//! eliminating the current draw through the amplifier and speaker. +//! +//! \return None. +// +//***************************************************************************** +void +SoundStop(void) +{ + // + // See if playback is in progress. + // + if((g_sSoundState.ui32Flags != 0) && + (HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN) == 0)) + { + // + // Temporarily disable the timer interrupt. + // + ROM_IntDisable(INT_TIMER5A); + + // + // Clear the sound flags and set the shutdown flag (to try to avoid a + // pop, though one may still occur based on the current position of the + // output waveform). + // + g_sSoundState.ui32Flags = 0; + HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN) = 1; + + // + // Set the shutdown step to the first. + // + g_sSoundState.i32Step = g_sSoundState.ui32Period / 2; + + // + // Reenable the timer interrupt. + // + ROM_IntEnable(INT_TIMER5A); + } +} + +//***************************************************************************** +// +//! Determines if the sound driver is busy. +//! +//! This function determines if the sound driver is busy, either performing the +//! startup or shutdown ramp for the speaker or playing a sound stream. +//! +//! \return Returns \b true if the sound driver is busy and \b false otherwise. +// +//***************************************************************************** +bool +SoundBusy(void) +{ + // + // The sound driver is busy if the sound flags are not zero. + // + return(g_sSoundState.ui32Flags != 0); +} + +//***************************************************************************** +// +//! Sets the volume of the sound playback. +//! +//! \param i32Volume is the volume of the sound playback, specified as a value +//! between 0 (for silence) and 255 (for full volume). +//! +//! This function sets the volume of the sound playback. Setting the volume to +//! 0 mutes the output, while setting the volume to 256 plays the sound +//! stream without any volume adjustment (that is, full volume). +//! +//! \return None. +// +//***************************************************************************** +void +SoundVolumeSet(int32_t i32Volume) +{ + // + // Set the volume mulitplier to be used. + // + g_sSoundState.i32Volume = i32Volume; +} + +//***************************************************************************** +// +//! Increases the volume of the sound playback. +//! +//! \param i32Volume is the amount by which to increase the volume of the +//! sound playback, specified as a value between 0 (for no adjustment) and 255 +//! maximum adjustment). +//! +//! This function increases the volume of the sound playback relative to the +//! current volume. +//! +//! \return None. +// +//***************************************************************************** +void +SoundVolumeUp(int32_t i32Volume) +{ + // + // Compute the new volume, limiting to the maximum if required. + // + i32Volume = g_sSoundState.i32Volume + i32Volume; + if(i32Volume > 255) + { + i32Volume = 255; + } + + // + // Set the new volume. + // + g_sSoundState.i32Volume = i32Volume; +} + +//***************************************************************************** +// +//! Decreases the volume of the sound playback. +//! +//! \param i32Volume is the amount by which to decrease the volume of the +//! sound playback, specified as a value between 0 (for no adjustment) and 255 +//! maximum adjustment). +//! +//! This function decreases the volume of the sound playback relative to the +//! current volume. +//! +//! \return None. +// +//***************************************************************************** +void +SoundVolumeDown(int32_t i32Volume) +{ + // + // Compute the new volume, limiting to the minimum if required. + // + i32Volume = g_sSoundState.i32Volume - i32Volume; + if(i32Volume < 0) + { + i32Volume = 0; + } + + // + // Set the new volume. + // + g_sSoundState.i32Volume = i32Volume; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/sound.h b/boards/dk-tm4c129x/drivers/sound.h new file mode 100644 index 0000000..9892b67 --- /dev/null +++ b/boards/dk-tm4c129x/drivers/sound.h @@ -0,0 +1,65 @@ +//***************************************************************************** +// +// sound.h - Prototypes for the sound driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __DRIVERS_SOUND_H__ +#define __DRIVERS_SOUND_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes for the APIs. +// +//***************************************************************************** +extern void SoundIntHandler(void); +extern void SoundInit(uint32_t ui32SysClock); +extern bool SoundStart(int16_t *pi16Buffer, uint32_t ui32Length, + uint32_t ui32Rate, + void (*pfnCallback)(uint32_t ui32Half)); +extern void SoundPeriodAdjust(int32_t i32RateAdjust); +extern void SoundStop(void); +extern bool SoundBusy(void); +extern void SoundVolumeSet(int32_t i32Volume); +extern void SoundVolumeUp(int32_t i32Volume); +extern void SoundVolumeDown(int32_t i32Volume); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_SOUND_H__ diff --git a/boards/dk-tm4c129x/drivers/touch.c b/boards/dk-tm4c129x/drivers/touch.c new file mode 100644 index 0000000..7129f52 --- /dev/null +++ b/boards/dk-tm4c129x/drivers/touch.c @@ -0,0 +1,762 @@ +//***************************************************************************** +// +// touch.c - Touch screen driver for the DK-TM4C129X. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_adc.h" +#include "inc/hw_gpio.h" +#include "inc/hw_ints.h" +#include "inc/hw_memmap.h" +#include "inc/hw_timer.h" +#include "inc/hw_types.h" +#include "driverlib/adc.h" +#include "driverlib/gpio.h" +#include "driverlib/interrupt.h" +#include "driverlib/rom.h" +#include "driverlib/sysctl.h" +#include "driverlib/timer.h" +#include "grlib/grlib.h" +#include "grlib/widget.h" +#include "drivers/touch.h" + +//***************************************************************************** +// +//! \addtogroup touch_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// This driver operates in four different screen orientations. They are: +// +// * Portrait - The screen is taller than it is wide, and the flex connector is +// on the left of the display. This is selected by defining +// PORTRAIT. +// +// * Landscape - The screen is wider than it is tall, and the flex connector is +// on the bottom of the display. This is selected by defining +// LANDSCAPE. +// +// * Portrait flip - The screen is taller than it is wide, and the flex +// connector is on the right of the display. This is +// selected by defining PORTRAIT_FLIP. +// +// * Landscape flip - The screen is wider than it is tall, and the flex +// connector is on the top of the display. This is +// selected by defining LANDSCAPE_FLIP. +// +// These can also be imagined in terms of screen rotation; if portrait mode is +// 0 degrees of screen rotation, landscape is 90 degrees of counter-clockwise +// rotation, portrait flip is 180 degrees of rotation, and landscape flip is +// 270 degress of counter-clockwise rotation. +// +// If no screen orientation is selected, landscape mode will be used. +// +//***************************************************************************** +#if ! defined(PORTRAIT) && ! defined(PORTRAIT_FLIP) && \ + ! defined(LANDSCAPE) && ! defined(LANDSCAPE_FLIP) +#define LANDSCAPE_FLIP +#endif + +//***************************************************************************** +// +// The GPIO pins/ADC channels to which the touch screen is connected. +// +//***************************************************************************** +#define TS_XP_BASE GPIO_PORTE_BASE +#define TS_XP_PIN GPIO_PIN_7 +#define TS_XP_ADC ADC_CTL_CH21 +#define TS_XN_BASE GPIO_PORTT_BASE +#define TS_XN_PIN GPIO_PIN_2 +#define TS_YP_BASE GPIO_PORTP_BASE +#define TS_YP_PIN GPIO_PIN_7 +#define TS_YP_ADC ADC_CTL_CH22 +#define TS_YN_BASE GPIO_PORTT_BASE +#define TS_YN_PIN GPIO_PIN_3 + +//***************************************************************************** +// +// Touchscreen calibration parameters. Screen orientation is a build time +// selection. +// +//***************************************************************************** +const int32_t g_pi32TouchParameters[7] = +{ +#ifdef PORTRAIT + 3840, // M0 + 318720, // M1 + -297763200, // M2 + 328576, // M3 + -8896, // M4 + -164591232, // M5 + 3100080, // M6 +#endif +#ifdef LANDSCAPE + 328192, // M0 + -4352, // M1 + -178717056, // M2 + 1488, // M3 + -314592, // M4 + 1012670064, // M5 + 3055164, // M6 +#endif +#ifdef PORTRAIT_FLIP + 1728, // M0 + -321696, // M1 + 1034304336, // M2 + -325440, // M3 + 1600, // M4 + 1161009600, // M5 + 3098070, // M6 +#endif +#ifdef LANDSCAPE_FLIP + -326400, // M0 + -1024, // M1 + 1155718720, // M2 + 3768, // M3 + 312024, // M4 + -299081088, // M5 + 3013754, // M6 +#endif +}; + +//***************************************************************************** +// +// The lowest ADC reading assumed to represent a press on the screen. Readings +// below this indicate no press is taking place. +// +//***************************************************************************** +#define TOUCH_MIN 150 + +//***************************************************************************** +// +// The current state of the touch screen driver's state machine. This is used +// to cycle the touch screen interface through the powering sequence required +// to read the two axes of the surface. +// +//***************************************************************************** +static uint32_t g_ui32TSState; +#define TS_STATE_INIT 0 +#define TS_STATE_SKIP_X 1 +#define TS_STATE_READ_X 2 +#define TS_STATE_SKIP_Y 3 +#define TS_STATE_READ_Y 4 + +//***************************************************************************** +// +// The most recent raw ADC reading for the X position on the screen. This +// value is not affected by the selected screen orientation. +// +//***************************************************************************** +volatile int16_t g_i16TouchX; + +//***************************************************************************** +// +// The most recent raw ADC reading for the Y position on the screen. This +// value is not affected by the selected screen orientation. +// +//***************************************************************************** +volatile int16_t g_i16TouchY; + +//***************************************************************************** +// +// The minimum raw reading that should be considered valid press. +// +//***************************************************************************** +int16_t g_i16TouchMin = TOUCH_MIN; + +//***************************************************************************** +// +// A pointer to the function to receive messages from the touch screen driver +// when events occur on the touch screen (debounced presses, movement while +// pressed, and debounced releases). +// +//***************************************************************************** +static int32_t (*g_pfnTSHandler)(uint32_t ui32Message, int32_t i32X, + int32_t i32Y); + +//***************************************************************************** +// +// The current state of the touch screen debouncer. When zero, the pen is up. +// When three, the pen is down. When one or two, the pen is transitioning from +// one state to the other. +// +//***************************************************************************** +static uint8_t g_ui8State = 0; + +//***************************************************************************** +// +// The queue of debounced pen positions. This is used to slightly delay the +// returned pen positions, so that the pen positions that occur while the pen +// is being raised are not send to the application. +// +//***************************************************************************** +static int16_t g_pi16Samples[8]; + +//***************************************************************************** +// +// The count of pen positions in g_pi16Samples. When negative, the buffer is +// being pre-filled as a result of a detected pen down event. +// +//***************************************************************************** +static int8_t g_i8Index = 0; + +//***************************************************************************** +// +//! Debounces presses of the touch screen. +//! +//! This function is called when a new X/Y sample pair has been captured in +//! order to perform debouncing of the touch screen. +//! +//! \return None. +// +//***************************************************************************** +static void +TouchScreenDebouncer(void) +{ + int32_t i32X, i32Y, i32Temp; + + // + // Convert the ADC readings into pixel values on the screen. + // + i32X = g_i16TouchX; + i32Y = g_i16TouchY; + i32Temp = (((i32X * g_pi32TouchParameters[0]) + + (i32Y * g_pi32TouchParameters[1]) + g_pi32TouchParameters[2]) / + g_pi32TouchParameters[6]); + i32Y = (((i32X * g_pi32TouchParameters[3]) + + (i32Y * g_pi32TouchParameters[4]) + g_pi32TouchParameters[5]) / + g_pi32TouchParameters[6]); + i32X = i32Temp; + + // + // See if the touch screen is being touched. + // + if((g_i16TouchX < g_i16TouchMin) || (g_i16TouchY < g_i16TouchMin)) + { + // + // If there are no valid values yet then ignore this state. + // + if((g_ui8State & 0x80) == 0) + { + g_ui8State = 0; + } + + // + // See if the pen is not up right now. + // + if(g_ui8State != 0x00) + { + // + // Decrement the state count. + // + g_ui8State--; + + // + // See if the pen has been detected as up three times in a row. + // + if(g_ui8State == 0x80) + { + // + // Indicate that the pen is up. + // + g_ui8State = 0x00; + + // + // See if there is a touch screen event handler. + // + if(g_pfnTSHandler) + { + // + // If we got caught pre-filling the values, just return the + // first valid value as a press and release. If this is + // not done there is a perceived miss of a press event. + // + if(g_i8Index < 0) + { + g_pfnTSHandler(WIDGET_MSG_PTR_DOWN, g_pi16Samples[0], + g_pi16Samples[1]); + g_i8Index = 0; + } + + // + // Send the pen up message to the touch screen event + // handler. + // + g_pfnTSHandler(WIDGET_MSG_PTR_UP, g_pi16Samples[g_i8Index], + g_pi16Samples[g_i8Index + 1]); + } + } + } + } + else + { + // + // If the state was counting down above then fall back to the idle + // state and start waiting for new values. + // + if((g_ui8State & 0x80) && (g_ui8State != 0x83)) + { + // + // Restart the release count down. + // + g_ui8State = 0x83; + } + + // + // See if the pen is not down right now. + // + if(g_ui8State != 0x83) + { + // + // Increment the state count. + // + g_ui8State++; + + // + // See if the pen has been detected as down three times in a row. + // + if(g_ui8State == 0x03) + { + // + // Indicate that the pen is down. + // + g_ui8State = 0x83; + + // + // Set the index to -8, so that the next 3 samples are stored + // into the sample buffer before sending anything back to the + // touch screen event handler. + // + g_i8Index = -8; + + // + // Store this sample into the sample buffer. + // + g_pi16Samples[0] = i32X; + g_pi16Samples[1] = i32Y; + } + } + else + { + // + // See if the sample buffer pre-fill has completed. + // + if(g_i8Index == -2) + { + // + // See if there is a touch screen event handler. + // + if(g_pfnTSHandler) + { + // + // Send the pen down message to the touch screen event + // handler. + // + g_pfnTSHandler(WIDGET_MSG_PTR_DOWN, g_pi16Samples[0], + g_pi16Samples[1]); + } + + // + // Store this sample into the sample buffer. + // + g_pi16Samples[0] = i32X; + g_pi16Samples[1] = i32Y; + + // + // Set the index to the next sample to send. + // + g_i8Index = 2; + } + + // + // Otherwise, see if the sample buffer pre-fill is in progress. + // + else if(g_i8Index < 0) + { + // + // Store this sample into the sample buffer. + // + g_pi16Samples[g_i8Index + 10] = i32X; + g_pi16Samples[g_i8Index + 11] = i32Y; + + // + // Increment the index. + // + g_i8Index += 2; + } + + // + // Otherwise, the sample buffer is full. + // + else + { + // + // See if there is a touch screen event handler. + // + if(g_pfnTSHandler) + { + // + // Send the pen move message to the touch screen event + // handler. + // + g_pfnTSHandler(WIDGET_MSG_PTR_MOVE, + g_pi16Samples[g_i8Index], + g_pi16Samples[g_i8Index + 1]); + } + + // + // Store this sample into the sample buffer. + // + g_pi16Samples[g_i8Index] = i32X; + g_pi16Samples[g_i8Index + 1] = i32Y; + + // + // Increment the index. + // + g_i8Index = (g_i8Index + 2) & 7; + } + } + } +} + +//***************************************************************************** +// +//! Handles the ADC interrupt for the touch screen. +//! +//! This function is called when the ADC sequence that samples the touch screen +//! has completed its acquisition. The touch screen state machine is advanced +//! and the acquired ADC sample is processed appropriately. +//! +//! It is the responsibility of the application using the touch screen driver +//! to ensure that this function is installed in the interrupt vector table for +//! the ADC0 samples sequencer 3 interrupt. +//! +//! \return None. +// +//***************************************************************************** +void +TouchScreenIntHandler(void) +{ + // + // Clear the ADC sample sequence interrupt. + // + HWREG(ADC0_BASE + ADC_O_ISC) = ADC_ISC_IN3; + + // + // Determine what to do based on the current state of the state machine. + // + switch(g_ui32TSState) + { + // + // The new sample is an X axis sample that should be discarded. + // + case TS_STATE_SKIP_X: + { + // + // Read and throw away the ADC sample. + // + HWREG(ADC0_BASE + ADC_O_SSFIFO3); + + // + // Set the analog mode select for the YP pin. + // + HWREG(TS_YP_BASE + GPIO_O_AMSEL) |= TS_YP_PIN; + + // + // Configure the Y axis touch layer pins as inputs. + // + HWREG(TS_YP_BASE + GPIO_O_DIR) &= ~TS_YP_PIN; + HWREG(TS_YN_BASE + GPIO_O_DIR) &= ~TS_YN_PIN; + + // + // The next sample will be a valid X axis sample. + // + g_ui32TSState = TS_STATE_READ_X; + + // + // This state has been handled. + // + break; + } + + // + // The new sample is an X axis sample that should be processed. + // + case TS_STATE_READ_X: + { + // + // Read the raw ADC sample. + // + g_i16TouchX = HWREG(ADC0_BASE + ADC_O_SSFIFO3); + + // + // Clear the analog mode select for the YP pin. + // + HWREG(TS_YP_BASE + GPIO_O_AMSEL) &= ~TS_YP_PIN; + + // + // Configure the X and Y axis touch layers as outputs. + // + HWREG(TS_XP_BASE + GPIO_O_DIR) |= TS_XP_PIN; + HWREG(TS_XN_BASE + GPIO_O_DIR) |= TS_XN_PIN; + HWREG(TS_YP_BASE + GPIO_O_DIR) |= TS_YP_PIN; + HWREG(TS_YN_BASE + GPIO_O_DIR) |= TS_YN_PIN; + + // + // Drive the positive side of the Y axis touch layer with VDD and + // the negative side with GND. Also, drive both sides of the X + // axis layer with GND to discharge any residual voltage (so that + // a no-touch condition can be properly detected). + // + HWREG(TS_XP_BASE + GPIO_O_DATA + (TS_XP_PIN << 2)) = 0; + HWREG(TS_XN_BASE + GPIO_O_DATA + (TS_XN_PIN << 2)) = 0; + HWREG(TS_YP_BASE + GPIO_O_DATA + (TS_YP_PIN << 2)) = TS_YP_PIN; + HWREG(TS_YN_BASE + GPIO_O_DATA + (TS_YN_PIN << 2)) = 0; + + // + // Configure the sample sequence to capture the X axis value. + // + HWREG(ADC0_BASE + ADC_O_SSMUX3) = TS_XP_ADC; + + // + // The next sample will be an invalid Y axis sample. + // + g_ui32TSState = TS_STATE_SKIP_Y; + + // + // This state has been handled. + // + break; + } + + // + // The new sample is a Y axis sample that should be discarded. + // + case TS_STATE_SKIP_Y: + { + // + // Read and throw away the ADC sample. + // + HWREG(ADC0_BASE + ADC_O_SSFIFO3); + + // + // Set the analog mode select for the XP pin. + // + HWREG(TS_XP_BASE + GPIO_O_AMSEL) |= TS_XP_PIN; + + // + // Configure the X axis touch layer pins as inputs. + // + HWREG(TS_XP_BASE + GPIO_O_DIR) &= ~TS_XP_PIN; + HWREG(TS_XN_BASE + GPIO_O_DIR) &= ~TS_XN_PIN; + + // + // The next sample will be a valid Y axis sample. + // + g_ui32TSState = TS_STATE_READ_Y; + + // + // This state has been handled. + // + break; + } + + // + // The new sample is a Y axis sample that should be processed. + // + case TS_STATE_READ_Y: + { + // + // Read the raw ADC sample. + // + g_i16TouchY = HWREG(ADC0_BASE + ADC_O_SSFIFO3); + + // + // The next configuration is the same as the initial configuration. + // Therefore, fall through into the initialization state to avoid + // duplicating the code. + // + } + + // + // The state machine is in its initial state + // + case TS_STATE_INIT: + { + // + // Clear the analog mode select for the XP pin. + // + HWREG(TS_XP_BASE + GPIO_O_AMSEL) &= ~TS_XP_PIN; + + // + // Configure the X and Y axis touch layers as outputs. + // + HWREG(TS_XP_BASE + GPIO_O_DIR) |= TS_XP_PIN; + HWREG(TS_XN_BASE + GPIO_O_DIR) |= TS_XN_PIN; + HWREG(TS_YP_BASE + GPIO_O_DIR) |= TS_YP_PIN; + HWREG(TS_YN_BASE + GPIO_O_DIR) |= TS_YN_PIN; + + // + // Drive one side of the X axis touch layer with VDD and the other + // with GND. Also, drive both sides of the Y axis layer with GND + // to discharge any residual voltage (so that a no-touch condition + // can be properly detected). + // + HWREG(TS_XP_BASE + GPIO_O_DATA + (TS_XP_PIN << 2)) = TS_XP_PIN; + HWREG(TS_XN_BASE + GPIO_O_DATA + (TS_XN_PIN << 2)) = 0; + HWREG(TS_YP_BASE + GPIO_O_DATA + (TS_YP_PIN << 2)) = 0; + HWREG(TS_YN_BASE + GPIO_O_DATA + (TS_YN_PIN << 2)) = 0; + + // + // Configure the sample sequence to capture the Y axis value. + // + HWREG(ADC0_BASE + ADC_O_SSMUX3) = TS_YP_ADC; + + // + // If this is the valid Y sample state, then there is a new X/Y + // sample pair. In that case, run the touch screen debouncer. + // + if(g_ui32TSState == TS_STATE_READ_Y) + { + TouchScreenDebouncer(); + } + + // + // The next sample will be an invalid X axis sample. + // + g_ui32TSState = TS_STATE_SKIP_X; + + // + // This state has been handled. + // + break; + } + } +} + +//***************************************************************************** +// +//! Initializes the touch screen driver. +//! +//! \param ui32SysClock is the frequency of the system clock. +//! +//! This function initializes the touch screen driver, beginning the process of +//! reading from the touch screen. This driver uses the following hardware +//! resources: +//! +//! - ADC 0 sample sequence 3 +//! - Timer 5 subtimer B +//! +//! \return None. +// +//***************************************************************************** +void +TouchScreenInit(uint32_t ui32SysClock) +{ + // + // Set the initial state of the touch screen driver's state machine. + // + g_ui32TSState = TS_STATE_INIT; + + // + // There is no touch screen handler initially. + // + g_pfnTSHandler = 0; + + // + // Enable the peripherals used by the touch screen interface. + // + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); + ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5); + + // + // Configure the ADC sample sequence used to read the touch screen reading. + // + ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 4); + ROM_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_TIMER, 0); + ROM_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, + TS_YP_ADC | ADC_CTL_END | ADC_CTL_IE); + ROM_ADCSequenceEnable(ADC0_BASE, 3); + + // + // Enable the ADC sample sequence interrupt. + // + ROM_ADCIntEnable(ADC0_BASE, 3); + ROM_IntEnable(INT_ADC0SS3); + + // + // Configure the timer to trigger the sampling of the touch screen + // every 2.5 milliseconds. + // + if((HWREG(TIMER5_BASE + TIMER_O_CTL) & TIMER_CTL_TAEN) == 0) + { + ROM_TimerConfigure(TIMER5_BASE, (TIMER_CFG_SPLIT_PAIR | + TIMER_CFG_A_PWM | + TIMER_CFG_B_PERIODIC)); + } + ROM_TimerPrescaleSet(TIMER5_BASE, TIMER_B, 255); + ROM_TimerLoadSet(TIMER5_BASE, TIMER_B, ((ui32SysClock / 256) / 400) - 1); + TimerControlTrigger(TIMER5_BASE, TIMER_B, true); + + // + // Enable the timer. At this point, the touch screen state machine will + // sample and run every 2.5 ms. + // + ROM_TimerEnable(TIMER5_BASE, TIMER_B); +} + +//***************************************************************************** +// +//! Sets the callback function for touch screen events. +//! +//! \param pfnCallback is a pointer to the function to be called when touch +//! screen events occur. +//! +//! This function sets the address of the function to be called when touch +//! screen events occur. The events that are recognized are the screen being +//! touched (``pen down''), the touch position moving while the screen is +//! touched (``pen move''), and the screen no longer being touched (``pen +//! up''). +//! +//! \return None. +// +//***************************************************************************** +void +TouchScreenCallbackSet(int32_t (*pfnCallback)(uint32_t ui32Message, + int32_t i32X, int32_t i32Y)) +{ + // + // Save the pointer to the callback function. + // + g_pfnTSHandler = pfnCallback; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/boards/dk-tm4c129x/drivers/touch.h b/boards/dk-tm4c129x/drivers/touch.h new file mode 100644 index 0000000..5459bdc --- /dev/null +++ b/boards/dk-tm4c129x/drivers/touch.h @@ -0,0 +1,61 @@ +//***************************************************************************** +// +// touch.h - Prototypes for the touch screen driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __DRIVERS_TOUCH_H__ +#define __DRIVERS_TOUCH_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern volatile int16_t g_i16TouchX; +extern volatile int16_t g_i16TouchY; +extern int16_t g_i16TouchMin; +extern void TouchScreenIntHandler(void); +extern void TouchScreenInit(uint32_t ui32SysClock); +extern void TouchScreenCallbackSet(int32_t (*pfnCallback)(uint32_t ui32Message, + int32_t i32X, + int32_t i32Y)); +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __DRIVERS_TOUCH_H__ diff --git a/boards/dk-tm4c129x/drivers/usb_sound.c b/boards/dk-tm4c129x/drivers/usb_sound.c new file mode 100644 index 0000000..3a858bf --- /dev/null +++ b/boards/dk-tm4c129x/drivers/usb_sound.c @@ -0,0 +1,769 @@ +//***************************************************************************** +// +// usb_sound.c - USB host audio handling functions. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_types.h" +#include "inc/hw_memmap.h" +#include "drivers/usb_sound.h" +#include "driverlib/gpio.h" +#include "driverlib/sysctl.h" +#include "driverlib/udma.h" +#include "driverlib/usb.h" +#include "usblib/usblib.h" +#include "usblib/usbmsc.h" +#include "usblib/host/usbhost.h" +#include "usblib/host/usbhaudio.h" + +//***************************************************************************** +// +// The size of the host controller's memory pool in bytes. +// +//***************************************************************************** +#define HCD_MEMORY_SIZE 768 + +//***************************************************************************** +// +// The memory pool to provide to the Host controller driver. +// +//***************************************************************************** +uint8_t g_pHCDPool[HCD_MEMORY_SIZE]; + +//***************************************************************************** +// +// The instance data for the USB host audio driver. +// +//***************************************************************************** +tUSBHostAudioInstance *g_psAudioInstance; + +//***************************************************************************** +// +// Declare the USB Events driver interface. +// +//***************************************************************************** +DECLARE_EVENT_DRIVER(g_sUSBEventDriver, 0, 0, USBHCDEvents); + +//***************************************************************************** +// +// This structure holds the state information for the USB audio device. +// +//***************************************************************************** +static struct +{ + // + // Save the application provided callback function. + // + tUSBBufferCallback pfnCallbackOut; + + // + // Save the application provided callback function. + // + tUSBBufferCallback pfnCallbackIn; + + // + // The event callback for the application. + // + tEventCallback pfnCallbackEvent; + + // + // Volume control multipliers calculated from the information received + // from the audio device. + // + uint32_t pui32Steps[3]; + + // + // The currently pending audio device events. + // + uint32_t ui32EventFlags; + + // + // The current state for the audio device. + // + volatile enum + { + // + // No device is present. + // + eStateNoDevice, + + // + // Audio device is ready. + // + eStateDeviceReady, + + // + // An unsupported device has been attached. + // + eStateUnknownDevice, + + // + // A power fault has occurred. + // + eStatePowerFault + } + iState; + +} g_sAudioState; + +//***************************************************************************** +// +// These defines are used with the ui32EventFlags in the g_sAudioState +// structure. +// +//***************************************************************************** +#define EVENT_OPEN 0x00000001 +#define EVENT_CLOSE 0x00000002 + +//***************************************************************************** +// +// The global that holds all of the host drivers in use in the application. +// In this case, only the host audio class is loaded. +// +//***************************************************************************** +static tUSBHostClassDriver const * const g_ppHostClassDrivers[] = +{ + &g_sUSBHostAudioClassDriver, + &g_sUSBEventDriver +}; + +//***************************************************************************** +// +// This global holds the number of class drivers in the g_ppHostClassDrivers +// list. +// +//***************************************************************************** +static const uint32_t g_ui32NumHostClassDrivers = + sizeof(g_ppHostClassDrivers) / sizeof(tUSBHostClassDriver *); + +//***************************************************************************** +// +// This function was the callback function registered with the USB host audio +// class driver. The only two events that are handled at this point are the +// USBH_AUDIO_EVENT_OPEN and USBH_AUDIO_EVENT_CLOSE which indicate that a new +// audio device has been found or that an existing audio device has been +// disconnected. +// +//***************************************************************************** +static void +AudioCallback(tUSBHostAudioInstance *psAudioInstance, uint32_t ui32Event, + uint32_t ui32MsgParam, void *pvBuffer) +{ + switch(ui32Event) + { + // + // New USB audio device has been enabled. + // + case USBH_AUDIO_EVENT_OPEN: + { + // + // Set the EVENT_OPEN flag and let the main routine handle it. + // + HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_OPEN) = 1; + + break; + } + + // + // USB audio device has been removed. + // + case USBH_AUDIO_EVENT_CLOSE: + { + // + // Set the EVENT_CLOSE flag and let the main routine handle it. + // + HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_CLOSE) = 1; + + break; + } + default: + { + break; + } + } +} + +//***************************************************************************** +// +// Initializes the sound output. +// +// \param ui32Flags is unused as this point but is included for future +// functionality. +// \param pfnCallback is the event callback function for audio devices. +// +// This function prepares the sound driver to enumerate an audio device and +// prepares to play audio once a valid audio device is detected. The +// \e pfnCallback function can be used to receive callbacks when there are +// changes related to the audio device. The ui32Event parameter to the +// callback is one of the SOUND_EVENT_* values. +// +// \return None +// +//***************************************************************************** +void +USBSoundInit(uint32_t ui32Flags, tEventCallback pfnCallback) +{ + // + // Initialize the USB stack mode to force host mode. + // + USBStackModeSet(0, eUSBModeForceHost, 0); + + // + // Register the host class drivers. + // + USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ui32NumHostClassDrivers); + + // + // Open an instance of the audio class driver. + // + g_psAudioInstance = USBHostAudioOpen(0, AudioCallback); + + // + // Initialize the power configuration. This sets the power enable signal + // to be active high and does not enable the power fault. + // + USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER); + + // + // Initialize the USB controller for host mode operation. + // + USBHCDInit(0, g_pHCDPool, HCD_MEMORY_SIZE); + + // + // Save the event callback function. + // + g_sAudioState.pfnCallbackEvent = pfnCallback; +} + +//***************************************************************************** +// +// Sets the volume of the audio device. +// +// \param ui32Percent is the volume percentage, which must be between 0% +// (silence) and 100% (full volume), inclusive. +// +// This function sets the volume of the sound output to a value between +// silence (0%) and full volume (100%). +// +// \return None. +// +//***************************************************************************** +void +USBSoundVolumeSet(uint32_t ui32Percent) +{ + uint32_t ui32Value; + + // + // Ignore volume changes if there is no device present. + // + if(g_sAudioState.iState == eStateDeviceReady) + { + // + // Scale the voltage percentage to the decibel range provided by the + // USB audio device. + // + ui32Value = (g_sAudioState.pui32Steps[1] * ui32Percent) / 100; + USBHostAudioVolumeSet(g_psAudioInstance, 0, 1, ui32Value); + + ui32Value = (g_sAudioState.pui32Steps[2] * ui32Percent) / 100; + USBHostAudioVolumeSet(g_psAudioInstance, 0, 2, ui32Value); + } +} + +//***************************************************************************** +// +// Returns the current volume level. +// +// \param ui32Channel is the 0 based channel number to query. +// +// This function returns the current volume, specified as a percentage between +// 0% (silence) and 100% (full volume), inclusive. The \e ui32Channel value +// starts with 0 which is the master audio volume control interface. The +// remaining \e ui32Channel values provide access to various other audio +// channels, with 1 and 2 being left and right audio channels. +// +// \return Returns the current volume. +// +//***************************************************************************** +uint32_t +USBSoundVolumeGet(uint32_t ui32Channel) +{ + uint32_t ui32Volume; + + // + // Initialize the return value in case there is no USB device present. + // + ui32Volume = 0xffffffff; + + // + // Ignore volume request if there is no device present. + // + if(g_sAudioState.iState == eStateDeviceReady) + { + ui32Volume = USBHostAudioVolumeGet(g_psAudioInstance, 0, ui32Channel); + } + + return(ui32Volume); +} + +//***************************************************************************** +// +// This sets the current output audio format of the USB audio device. +// +// \param ui32SampleRate is the sample rate. +// \param ui32BitsPerSample is the number of bits per sample. +// \param ui32Channels is the number of channels. +// +// This sets the current audio format for the USB device that is currently +// connected. If there is no USB device connected or the format is not +// supported then the function returns a non-zero value. The function +// returns zero if the USB audio device was successfully configured to the +// requested audio format. +// +// \return Returns zero if the format was successfully set or returns an +// non-zero value if the format was not able to be set. +// +//***************************************************************************** +uint32_t +USBSoundOutputFormatSet(uint32_t ui32SampleRate, + uint32_t ui32BitsPerSample, uint32_t ui32Channels) +{ + // + // Just return if there is no device at this time. + // + if(g_sAudioState.iState != eStateDeviceReady) + { + return(1); + } + + // + // Call the USB Host Audio function to set the format. + // + return(USBHostAudioFormatSet(g_psAudioInstance, ui32SampleRate, + ui32BitsPerSample, ui32Channels, + USBH_AUDIO_FORMAT_OUT)); +} + +//***************************************************************************** +// +// This sets the current input audio format of the USB audio device +// +// \param ui32SampleRate is the sample rate. +// \param ui32BitsPerSample is the number of bits per sample. +// \param ui32Channels is the number of channels. +// +// This sets the current format for the USB device that is currently connect. +// If there is no USB device connected or the format is not supported then the +// function returns 0. The function returns 1 if the USB audio device +// was successfully configured to the requested format. +// +// \return Returns 1 if the format was successfully set or returns 0 if the +// format was not changed. +// +//***************************************************************************** +uint32_t +USBSoundInputFormatSet(uint32_t ui32SampleRate, + uint32_t ui32BitsPerSample, uint32_t ui32Channels) +{ + // + // Just return if there is no device at this time. + // + if(g_sAudioState.iState != eStateDeviceReady) + { + return(0); + } + + return(USBHostAudioFormatSet(g_psAudioInstance, ui32SampleRate, + ui32BitsPerSample, ui32Channels, + USBH_AUDIO_FORMAT_IN)); +} + +//***************************************************************************** +// +// Returns the current sample rate. +// +// This function returns the sample rate that was set by a call to +// USBSoundSetFormat(). This is needed to retrieve the exact sample rate that is +// in use in case the requested rate could not be matched exactly. +// +// \return The current sample rate in samples/second. +// +//***************************************************************************** +uint32_t +USBSoundOutputFormatGet(uint32_t ui32SampleRate, uint32_t ui32Bits, + uint32_t ui32Channels) +{ + // + // Just return if there is no device at this time. + // + if(g_sAudioState.iState != eStateDeviceReady) + { + return(0); + } + + return(USBHostAudioFormatGet(g_psAudioInstance, ui32SampleRate, ui32Bits, + ui32Channels, USBH_AUDIO_FORMAT_OUT)); +} + +//***************************************************************************** +// +// Returns the current sample rate. +// +// This function returns the sample rate that was set by a call to +// USBSoundSetFormat(). This is needed to retrieve the exact sample rate that is +// in use in case the requested rate could not be matched exactly. +// +// \return The current sample rate in samples/second. +// +//***************************************************************************** +uint32_t +USBSoundInputFormatGet(uint32_t ui32SampleRate, uint32_t ui32Bits, + uint32_t ui32Channels) +{ + // + // Just return if there is no device at this time. + // + if(g_sAudioState.iState != eStateDeviceReady) + { + return(0); + } + + return(USBHostAudioFormatGet(g_psAudioInstance, ui32SampleRate, ui32Bits, + ui32Channels, USBH_AUDIO_FORMAT_IN)); +} + +//***************************************************************************** +// +// This is the generic callback from host stack. +// +// \param pvData is actually a pointer to a tEventInfo structure. +// +// This function is called to inform the application when a USB event has +// occurred that is outside those related to the audio device. At this +// point this is used to detect unsupported devices being inserted and removed. +// It is also used to inform the application when a power fault has occurred. +// This function is required when the g_USBGenerii8EventDriver is included in +// the host controller driver array that is passed in to the +// USBHCDRegisterDrivers() function. +// +// \return None. +// +//***************************************************************************** +void +USBHCDEvents(void *pvData) +{ + tEventInfo *psEventInfo; + + // + // Cast this pointer to its actual type. + // + psEventInfo = (tEventInfo *)pvData; + + switch(psEventInfo->ui32Event) + { + // + // Unknown device detected. + // + case USB_EVENT_UNKNOWN_CONNECTED: + { + // + // An unknown device was detected. + // + g_sAudioState.iState = eStateUnknownDevice; + + // + // Call the general event handler if present. + // + if(g_sAudioState.pfnCallbackEvent) + { + g_sAudioState.pfnCallbackEvent(SOUND_EVENT_UNKNOWN_DEV, 1); + } + + break; + } + + // + // Device unplugged. + // + case USB_EVENT_DISCONNECTED: + { + // + // Handle the case where an unknown device is disconnected. + // + if(g_sAudioState.iState == eStateUnknownDevice) + { + g_sAudioState.iState = eStateNoDevice; + + // + // Call the general event handler if present. + // + if(g_sAudioState.pfnCallbackEvent) + { + g_sAudioState.pfnCallbackEvent(SOUND_EVENT_UNKNOWN_DEV, 0); + } + } + else + { + // + // Call the general event handler if present. + // + if(g_sAudioState.pfnCallbackEvent) + { + g_sAudioState.pfnCallbackEvent(SOUND_EVENT_DISCONNECT, 0); + } + } + + break; + } + + // + // A power fault has occurred. + // + case USB_EVENT_POWER_FAULT: + { + // + // No power means no device is present. + // + g_sAudioState.iState = eStatePowerFault; + + break; + } + default: + { + break; + } + } +} + +//***************************************************************************** +// +// This function passes along a buffer callback from the USB host audio driver +// so that the application can process or release the buffers. +// +//***************************************************************************** +void +USBHostAudioCallback(tUSBHostAudioInstance *psAudioInstance, + uint32_t ui32Event, uint32_t ui32Param, void *pvBuffer) +{ + // + // Only call the callback if it is actually present. + // + if(g_sAudioState.pfnCallbackOut) + { + g_sAudioState.pfnCallbackOut(pvBuffer, ui32Event, ui32Param); + } + + // + // Only call the callback if it is actually present. + // + if(g_sAudioState.pfnCallbackIn) + { + g_sAudioState.pfnCallbackIn(pvBuffer, ui32Event, ui32Param); + } +} + +//***************************************************************************** +// +// Starts output of a block of PCM audio samples. +// +// \param pvBuffer is a pointer to the audio data to play. +// \param ui32Size is the length of the data in bytes. +// \param pfnCallback is a function to call when this buffer has be played. +// +// This function starts the output of a block of PCM audio samples. +// +// \return This function returns a non-zero value if the buffer was accepted, +// and returns zero if the buffer was not accepted. +// +//***************************************************************************** +uint32_t +USBSoundBufferOut(const void *pvBuffer, uint32_t ui32Size, + tUSBBufferCallback pfnCallback) +{ + // + // If there is no device present or there is a pending buffer then just + // return with a failure. + // + if(g_sAudioState.iState != eStateDeviceReady) + { + return(0); + } + + // + // Save this buffer callback. + // + g_sAudioState.pfnCallbackOut = pfnCallback; + + // + // Pass the buffer aint32_t to the USB host audio driver for playback. + // + return(USBHostAudioPlay(g_psAudioInstance, (void *)pvBuffer, ui32Size, + USBHostAudioCallback)); +} + +//***************************************************************************** +// +// Requests a new block of PCM audio samples from a USB audio device. +// +// \param pvBuffer is a pointer to a location to store the audio data. +// \param ui32Size is the size of the pvData buffer in bytes. +// \param pfnCallback is a function to call when this buffer has new data. +// +// This function request a new block of PCM audio samples from a USB audio +// device. +// +// \return This function returns a non-zero value if the buffer was accepted, +// and returns zero if the buffer was not accepted. +// +//***************************************************************************** +uint32_t +USBSoundBufferIn(const void *pvBuffer, uint32_t ui32Size, + tUSBBufferCallback pfnCallback) +{ + // + // If there is no device present or there is a pending buffer then just + // return with a failure. + // + if(g_sAudioState.iState != eStateDeviceReady) + { + return(0); + } + + // + // Save this buffer callback. + // + g_sAudioState.pfnCallbackIn = pfnCallback; + + // + // Pass the buffer aint32_t to the USB host audio driver for input. + // + return(USBHostAudioRecord(g_psAudioInstance, (void *)pvBuffer, ui32Size, + USBHostAudioCallback)); +} + +//***************************************************************************** +// +// This function reads the audio volume settings for the USB audio device and +// saves them so that the volume can be scaled correctly. +// +//***************************************************************************** +static void +GetVolumeParameters(void) +{ + uint32_t ui32Max, ui32Min, ui32Res, ui32Channel; + + for(ui32Channel = 0; ui32Channel < 3; ui32Channel++) + { + ui32Max = USBHostAudioVolumeMaxGet(g_psAudioInstance, 0, ui32Channel); + ui32Min = USBHostAudioVolumeMinGet(g_psAudioInstance, 0, ui32Channel); + ui32Res = USBHostAudioVolumeResGet(g_psAudioInstance, 0, ui32Channel); + + g_sAudioState.pui32Steps[ui32Channel] = (ui32Max - ui32Min) / ui32Res; + } +} + +//***************************************************************************** +// +// The main routine for handling USB audio, this should be called periodically +// by the main program and pass in the amount of time in milliseconds that has +// elapsed since the last call. +// +//***************************************************************************** +void +USBSoundMain(void) +{ + // + // Tell the OTG library code how much time has passed in + // milliseconds since the last call. + // + USBHCDMain(); + + switch(g_sAudioState.iState) + { + // + // This is the running state where buttons are checked and the + // screen is updated. + // + case eStateDeviceReady: + { if(HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_CLOSE)) + { + HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_CLOSE) = 0; + g_sAudioState.iState = eStateNoDevice; + + // + // Call the general event handler if present. + // + if(g_sAudioState.pfnCallbackEvent) + { + g_sAudioState.pfnCallbackEvent(SOUND_EVENT_DISCONNECT, 0); + } + } + break; + } + + // + // If there is no device then just wait for one. + // + case eStateNoDevice: + { + if(HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_OPEN)) + { + g_sAudioState.iState = eStateDeviceReady; + + HWREGBITW(&g_sAudioState.ui32EventFlags, EVENT_OPEN) = 0; + + GetVolumeParameters(); + + // + // Call the general event handler if present. + // + if(g_sAudioState.pfnCallbackEvent) + { + g_sAudioState.pfnCallbackEvent(SOUND_EVENT_READY, 0); + } + } + break; + } + + // + // An unknown device was connected. + // + case eStateUnknownDevice: + { + break; + } + + // + // Something has caused a power fault. + // + case eStatePowerFault: + { + break; + } + + default: + { + break; + } + } +} diff --git a/boards/dk-tm4c129x/drivers/usb_sound.h b/boards/dk-tm4c129x/drivers/usb_sound.h new file mode 100644 index 0000000..0105f91 --- /dev/null +++ b/boards/dk-tm4c129x/drivers/usb_sound.h @@ -0,0 +1,81 @@ +//***************************************************************************** +// +// usb_sound.h - USB host audio handling header definitions. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#ifndef __USB_SOUND_H__ +#define __USB_SOUND_H__ + +//***************************************************************************** +// +// The following are defines for the ui32Event value that is returned with the +// tEventCallback function provided to the USBSoundInit() function. +// +//***************************************************************************** + +// +// A USB audio device has been connected. +// +#define SOUND_EVENT_READY 0x00000001 + +// +// A USB device has been disconnected. +// +#define SOUND_EVENT_DISCONNECT 0x00000002 + +// +// An unknown device has been connected. +// +#define SOUND_EVENT_UNKNOWN_DEV 0x00000003 + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +typedef void (* tUSBBufferCallback)(void *pvBuffer, uint32_t ui32Event, + uint32_t ui32Value); +typedef void (* tEventCallback)(uint32_t ui32Event, uint32_t ui32Param); +extern void USBSoundMain(void); +extern void USBSoundInit(uint32_t ui32EnableReceive, + tEventCallback pfnCallback); +extern void USBSoundVolumeSet(uint32_t ui32Percent); +extern uint32_t USBSoundVolumeGet(uint32_t ui32Channel); +extern uint32_t USBSoundOutputFormatGet(uint32_t ui32SampleRate, + uint32_t ui32Bits, + uint32_t ui32Channels); +extern uint32_t USBSoundOutputFormatSet(uint32_t ui32SampleRate, + uint32_t ui32Bits, + uint32_t ui32Channels); +extern uint32_t USBSoundInputFormatGet(uint32_t ui32SampleRate, + uint32_t ui32BitsPerSample, + uint32_t ui32Channels); +extern uint32_t USBSoundInputFormatSet(uint32_t ui32SampleRate, + uint32_t ui32Bits, + uint32_t ui32Channels); +extern uint32_t USBSoundBufferOut(const void *pvData, uint32_t ui32Length, + tUSBBufferCallback pfnCallback); + +extern uint32_t USBSoundBufferIn(const void *pvData, uint32_t ui32Length, + tUSBBufferCallback pfnCallback); + +#endif -- cgit v1.3.1