Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nickshl/DevCore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornickshl <nicolai.shlapunov@gmail.com>2018-10-05 04:23:23 +0300
committernickshl <nicolai.shlapunov@gmail.com>2018-10-05 04:23:23 +0300
commitdea80e6a1743a02e119fe0a9bb4a00c3e6301d1e (patch)
tree808bc1a5ca97e81650b6ab0fe8e22164b78f5eb2 /Display
parent07550101d661d0c1d6bbb4d84c3ca3f1a11b4daf (diff)
DevCore - initial version
Diffstat (limited to 'Display')
-rw-r--r--Display/DisplayDrv.cpp573
-rw-r--r--Display/DisplayDrv.h202
-rw-r--r--Display/Fonts.c1312
-rw-r--r--Display/Fonts.h47
-rw-r--r--Display/ILI9341.cpp566
-rw-r--r--Display/ILI9341.h258
-rw-r--r--Display/Image.cpp366
-rw-r--r--Display/Image.h178
-rw-r--r--Display/Primitives.cpp326
-rw-r--r--Display/Primitives.h161
-rw-r--r--Display/Strings.cpp242
-rw-r--r--Display/Strings.h146
-rw-r--r--Display/TiledMap.cpp179
-rw-r--r--Display/TiledMap.h131
-rw-r--r--Display/VisObject.cpp125
-rw-r--r--Display/VisObject.h199
-rw-r--r--Display/XPT2046.cpp145
-rw-r--r--Display/XPT2046.h129
18 files changed, 5285 insertions, 0 deletions
diff --git a/Display/DisplayDrv.cpp b/Display/DisplayDrv.cpp
new file mode 100644
index 0000000..16c1eac
--- /dev/null
+++ b/Display/DisplayDrv.cpp
@@ -0,0 +1,573 @@
+//******************************************************************************
+// @file DisplayDrv.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Display Driver Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DisplayDrv.h"
+
+// *****************************************************************************
+// *** Get Instance ********************************************************
+// *****************************************************************************
+DisplayDrv& DisplayDrv::GetInstance(void)
+{
+ static DisplayDrv display_drv;
+ return display_drv;
+}
+
+// *****************************************************************************
+// *** Display Driver Setup ************************************************
+// *****************************************************************************
+Result DisplayDrv::Setup()
+{
+ // Init display driver
+ tft.Init();
+ // Set mode - mode can be set earlier than Display initialization
+ SetUpdateMode(update_mode);
+
+ // If deisplay and touchscreen share same SPI
+ if(tft_hspi == touch_hspi)
+ {
+ // Set prescaler for SPI
+ MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_64);
+ // Init touchscreen driver
+ touch.Init();
+ // Restore prescaler for SPI
+ MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_2);
+ }
+ else
+ {
+ // Init touchscreen driver
+ touch.Init();
+ }
+
+ // Set string parameters
+ fps_str.SetParams(str, width/3, height - 6, COLOR_MAGENTA, String::FONT_4x6);
+ // Show string if flag is set
+ if(DISPLAY_DEBUG_INFO)
+ {
+ // Max Z
+ fps_str.Show(0xFFFFFFFFU);
+ }
+
+ // Always ok
+ return Result::RESULT_OK;
+}
+
+// *****************************************************************************
+// *** Display Driver Loop *************************************************
+// *****************************************************************************
+Result DisplayDrv::Loop()
+{
+ // Variable for find FPS
+ uint32_t time_ms = HAL_GetTick();
+
+ // If semaphore doesn't exist or taken within 100 ms - draw screen
+ // Time need for update touchscreen state every 100 ms even display not
+ // updated
+ if(screen_update.Take(100U) == Result::RESULT_OK)
+ {
+ // Set window for all screen and pointer to first pixel
+ LockDisplay();
+ // Set address window for all screen
+ tft.SetAddrWindow(0, 0, width-1, height-1);
+ // For each line/row
+ for(int32_t i=0; i < height; i++)
+ {
+ // Clear half of buffer
+ memset(scr_buf[i%2], 0x00, sizeof(scr_buf[0]));
+ // Take semaphore before draw line
+ line_mutex.Lock();
+ // Set pointer to first element
+ VisObject* p_obj = object_list;
+ // Do for all objects
+ while(p_obj != nullptr)
+ {
+ // Draw object to buf
+ if(update_mode) p_obj->DrawInBufH(scr_buf[i%2], width, i);
+ else p_obj->DrawInBufW(scr_buf[i%2], width, i);
+ // Set pointer to next object in list
+ p_obj = p_obj->p_next;
+ }
+ // Give semaphore after changes
+ line_mutex.Release();
+ // Wait until previous transfer complete
+ while(tft.IsTransferComplete() == false) taskYIELD();
+ // Write stream to LCD
+ tft.SpiWriteStream((uint8_t*)scr_buf[i%2], width*tft.GetBytesPerPixel());
+ // DO NOT TRY "OPTIMIZE" CODE !!!
+ // Two "while" cycles used for generate next line when previous line
+ // transfer via SPI to display.
+ }
+ // Wait until last transfer complete
+ while(tft.IsTransferComplete() == false) taskYIELD();
+ // Pull up CS
+ tft.StopTransfer();
+ // Give semaphore after draw frame
+ UnlockDisplay();
+ // Calculate FPS if debug info is ON
+ if(DISPLAY_DEBUG_INFO)
+ {
+ // FPS in format XX.X
+ fps_x10 = (1000 * 10) / (HAL_GetTick() - time_ms);
+ }
+ }
+
+ bool tmp_is_touch = false;
+ int32_t tmp_tx = tx;
+ int32_t tmp_ty = ty;
+ // Try to take mutex. 1 ms should be enough.
+ if(touchscreen_mutex.Lock(1U) == Result::RESULT_OK)
+ {
+ // Set prescaler for SPI it display share save SPI with touchscreen
+ if(tft_hspi == touch_hspi)
+ {
+ MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_64);
+ }
+ // Get touch coordinates
+ tmp_is_touch = touch.GetXY(tmp_tx, tmp_ty);
+ // Reset prescaler for SPI it display share save SPI with touchscreen
+ if(tft_hspi == touch_hspi)
+ {
+ // Restore prescaler for SPI
+ MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_2);
+ }
+ // Give semaphore for drawing frame - we can enter in this "if" statement
+ // only if mutex taken
+ touchscreen_mutex.Release();
+ }
+ // If touch state changed (move)
+ if(is_touch && tmp_is_touch && ((tx != tmp_tx) || (ty != tmp_ty)) )
+ {
+ // Go thru VisObject list and call Active() function for active object
+ // Take semaphore before draw line
+ line_mutex.Lock();
+ // Set pointer to first element
+ VisObject* p_obj = object_list_last;
+ // If list not empty
+ if(p_obj != nullptr)
+ {
+ // Do for all objects
+ while(p_obj != nullptr)
+ {
+ // If we found active object
+ if(p_obj->active)
+ {
+ // And touch in this object area
+ if( (tx >= p_obj->GetStartX()) && (tx <= p_obj->GetEndX())
+ && (ty >= p_obj->GetStartY()) && (ty <= p_obj->GetEndY())
+ && (tmp_tx >= p_obj->GetStartX()) && (tmp_tx <= p_obj->GetEndX())
+ && (tmp_ty >= p_obj->GetStartY()) && (tmp_ty <= p_obj->GetEndY()) )
+ {
+ // Call Action() function for Move
+ p_obj->Action(VisObject::ACT_MOVE, tmp_tx, tmp_ty);
+ // No need check all other objects - only one object can be touched
+ break;
+ }
+ if( (tx >= p_obj->GetStartX()) && (tx <= p_obj->GetEndX())
+ && (ty >= p_obj->GetStartY()) && (ty <= p_obj->GetEndY())
+ && ( ((tmp_tx < p_obj->GetStartX()) || (tmp_tx > p_obj->GetEndX()))
+ || ((tmp_ty < p_obj->GetStartY()) || (tmp_ty > p_obj->GetEndY())) ) )
+ {
+ // Call Action() function for Move Out
+ p_obj->Action(VisObject::ACT_MOVEOUT, tmp_tx, tmp_ty);
+ }
+ if( (tmp_tx >= p_obj->GetStartX()) && (tmp_tx <= p_obj->GetEndX())
+ && (tmp_ty >= p_obj->GetStartY()) && (tmp_ty <= p_obj->GetEndY())
+ && ( ((tx < p_obj->GetStartX()) || (tx > p_obj->GetEndX()))
+ || ((ty < p_obj->GetStartY()) || (ty > p_obj->GetEndY())) ) )
+ {
+ // Call Action() function for Move In
+ p_obj->Action(VisObject::ACT_MOVEIN, tmp_tx, tmp_ty);
+ }
+ }
+ // Get previous object
+ p_obj = p_obj->p_prev;
+ }
+ }
+ // Give semaphore after changes
+ line_mutex.Release();
+ }
+ // If touch state changed (touch & release)
+ if(is_touch != tmp_is_touch)
+ {
+ // Go thru VisObject list and call Active() function for active object
+ // Take semaphore before draw line
+ line_mutex.Lock();
+ // Set pointer to first element
+ VisObject* p_obj = object_list_last;
+ // If list not empty
+ if(p_obj != nullptr)
+ {
+ // Do for all objects
+ while(p_obj != nullptr)
+ {
+ // If we found active object
+ if(p_obj->active)
+ {
+ // And touch in this object area
+ if( (tmp_tx >= p_obj->GetStartX()) && (tmp_tx <= p_obj->GetEndX())
+ && (tmp_ty >= p_obj->GetStartY()) && (tmp_ty <= p_obj->GetEndY()) )
+ {
+ // Call Action() function
+ p_obj->Action(tmp_is_touch ? VisObject::ACT_TOUCH : VisObject::ACT_UNTOUCH,
+ tmp_tx, tmp_ty);
+ // No need check all other objects - only one object can be touched
+ break;
+ }
+ }
+ // Get previous object
+ p_obj = p_obj->p_prev;
+ }
+ }
+ // Give semaphore after changes
+ line_mutex.Release();
+ }
+ // Save new touch state
+ is_touch = tmp_is_touch;
+ tx = tmp_tx;
+ ty = tmp_ty;
+
+ // FIX ME: debug code. Should be removed.
+ if(DISPLAY_DEBUG_INFO)
+ {
+ if(is_touch) sprintf(str, "X: %4ld, Y: %4ld", tx, ty);
+ else sprintf(str, "FPS: %2lu.%1lu, time: %lu", fps_x10/10, fps_x10%10, RtosTick::GetTimeMs()/1000UL);
+ fps_str.SetString(str);
+ }
+
+ // Always run
+ return Result::RESULT_OK;
+}
+
+// *****************************************************************************
+// *** Add Visual Object to object list ************************************
+// *****************************************************************************
+Result DisplayDrv::AddVisObjectToList(VisObject* obj, uint32_t z)
+{
+ Result result = Result::ERR_NULL_PTR;
+
+ if((obj != nullptr) && (obj->p_prev == nullptr) && (obj->p_next == nullptr) && (obj != object_list))
+ {
+ // Take semaphore before add to list
+ line_mutex.Lock();
+ // Set object Z
+ obj->z = z;
+ // Set prev pointer to nullptr
+ obj->p_prev = nullptr;
+ // Set next pointer to nullptr
+ obj->p_next = nullptr;
+ // If object list empty
+ if(object_list == nullptr)
+ {
+ // Add object to list
+ object_list = obj;
+ // Set pointer to last object in the list
+ object_list_last = obj;
+ }
+ else if(object_list->z > z)
+ {
+ // Set next element to current head element
+ obj->p_next = object_list;
+ // Set prev element to next after head element
+ object_list->p_prev = obj;
+ // Set new head for list
+ object_list = obj;
+ }
+ else
+ {
+ // Set temporary pointer
+ VisObject* p_last = object_list;
+ // Find last element
+ while((p_last->p_next != nullptr) && (p_last->p_next->z < z)) p_last = p_last->p_next;
+ // If it not last element
+ if(p_last->p_next != nullptr)
+ {
+ // Set next pointer in object
+ obj->p_next = p_last->p_next;
+ // Set prev pointer in object
+ obj->p_next->p_prev = obj;
+ }
+ else
+ {
+ // Set pointer to last object in the list
+ object_list_last = obj;
+ }
+ // Set next pointer in prev element
+ p_last->p_next = obj;
+ // Set prev pointer to new object in list
+ obj->p_prev = p_last;
+ }
+ // Give semaphore after changes
+ line_mutex.Release();
+ // Set return status
+ result = Result::RESULT_OK;
+ }
+
+ return result;
+}
+
+// *****************************************************************************
+// *** Delete Visual Object from object list *******************************
+// *****************************************************************************
+Result DisplayDrv::DelVisObjectFromList(VisObject* obj)
+{
+ Result result = Result::ERR_NULL_PTR;
+
+ if((obj != nullptr) && ((obj->p_prev != nullptr) || (obj->p_next != nullptr) || (obj == object_list)) )
+ {
+ // Take semaphore before delete from list
+ line_mutex.Lock();
+ // Remove element from head
+ if(obj == object_list)
+ {
+ // Set pointer to next object or clear pointer if no more elements
+ object_list = obj->p_next;
+ // Clear previous element in first object
+ object_list->p_prev = nullptr;
+ }
+ else if(obj == object_list_last)
+ {
+ // Set next pointer in previous object to nullptr
+ obj->p_prev->p_next = nullptr;
+ // Set pointer to previous object
+ object_list_last = obj->p_prev;
+ }
+ else
+ {
+ // Remove element from head
+ if(obj->p_prev == nullptr) object_list = obj->p_next;
+ // Remove element from middle
+ else if(obj->p_next != nullptr)
+ {
+ obj->p_prev->p_next = obj->p_next;
+ obj->p_next->p_prev = obj->p_prev;
+ }
+ // remove element from tail
+ else obj->p_prev->p_next = nullptr;
+ }
+ // Clear pointers in object
+ obj->p_prev = nullptr;
+ obj->p_next = nullptr;
+ // Give semaphore after changes
+ line_mutex.Release();
+ // Set return status
+ result = Result::RESULT_OK;
+ }
+
+ return result;
+}
+
+// *****************************************************************************
+// *** Lock display ********************************************************
+// *****************************************************************************
+Result DisplayDrv::LockDisplay(uint32_t wait_ms)
+{
+ // Take semaphore for protect draw frame
+ Result result = frame_mutex.Lock(wait_ms);
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** Unlock display ******************************************************
+// *****************************************************************************
+Result DisplayDrv::UnlockDisplay(void)
+{
+ // Give semaphore for drawing frame
+ Result result = frame_mutex.Release();
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** Lock display line ***************************************************
+// *****************************************************************************
+Result DisplayDrv::LockDisplayLine(uint32_t wait_ms)
+{
+ // Take semaphore for protect draw line
+ Result result = line_mutex.Lock(wait_ms);
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** Unlock display line *************************************************
+// *****************************************************************************
+Result DisplayDrv::UnlockDisplayLine(void)
+{
+ // Give semaphore for drawing frame
+ Result result = line_mutex.Release();
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** Update display ******************************************************
+// *****************************************************************************
+Result DisplayDrv::UpdateDisplay(void)
+{
+ // Give semaphore for update screen
+ Result result = screen_update.Give();
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** Set Update Mode *****************************************************
+// *****************************************************************************
+void DisplayDrv::SetUpdateMode(bool is_vertical)
+{
+ // Lock display
+ LockDisplay();
+ // Wait while transfer complete before change settings
+ while(tft.IsTransferComplete() == false);
+ // Change Update mode
+ if(is_vertical)
+ {
+ tft.SetRotation(2U);
+ }
+ else
+ {
+ tft.SetRotation(3U);
+ }
+ // Set width and height variables for selected screen update mode
+ width = tft.GetWidth();
+ height = tft.GetHeight();
+ // Save Update mode
+ update_mode = is_vertical;
+ // Unlock display
+ UnlockDisplay();
+}
+
+// *****************************************************************************
+// *** Get Touch X and Y coordinate ****************************************
+// *****************************************************************************
+bool DisplayDrv::GetTouchXY(int32_t& x, int32_t& y)
+{
+ // Result variable
+ bool result = false;
+
+ // Try to take mutex. 1 ms should be enough.
+ if(touchscreen_mutex.Lock(1U) == Result::RESULT_OK)
+ {
+ // If display driver gets touch coordinates and touch still present
+ if(is_touch && touch.IsTouch())
+ {
+ // Return last values
+ x = tx;
+ y = ty;
+ // Set result
+ result = true;
+ }
+ else
+ {
+ // If no touch - clear flag for prevent return wrong coordinates if
+ // display will touched without reads new coordinates
+ is_touch = false;
+ }
+ // Give semaphore for drawing frame - we can enter in this "if" statement
+ // only if mutex taken
+ touchscreen_mutex.Release();
+ }
+ // Return result
+ return result;
+}
+
+// *************************************************************************
+// *** Check touch *****************************************************
+// *************************************************************************
+bool DisplayDrv::IsTouch()
+{
+ return touch.IsTouch();
+}
+
+// *****************************************************************************
+// *** Calibrate Touchscreen ***********************************************
+// *****************************************************************************
+void DisplayDrv::TouchCalibrate()
+{
+ // Box for calibration
+ Box background(0, 0, width, height, COLOR_BLACK, true);
+ Box box(0, 0, 2, 2, COLOR_WHITE, true);
+ int32_t tx;
+ int32_t ty;
+ int32_t x1, x2;
+ int32_t y1, y2;
+
+ // Reset calibration
+ touch.SetCalibrationConsts(XPT2046::COEF, XPT2046::COEF, 0, 0);
+
+ // Show background box
+ background.Show(0xFFFFFFFFU-1U);
+ // Show box
+ box.Show(0xFFFFFFFFU);
+
+ // Move box to position
+ box.Move(10-1, 10-1);
+ // Wait press for get initial coordinates
+ while(!GetTouchXY(x1, y1))
+ {
+ // Update Display
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
+ // Wait unpress and measure coordinates continuously for averaging
+ while(GetTouchXY(tx, ty))
+ {
+ x1 = (x1 + tx) / 2;
+ y1 = (y1 + ty) / 2;
+ // Update Display - for update touch coordinates
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
+
+ // Move box to position
+ box.Move(width - 10 - 1, height - 10 - 1);
+ // Wait press for get initial coordinates
+ while(!GetTouchXY(x2, y2))
+ {
+ // Update Display
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
+ // Wait unpress and measure coordinates continuously for averaging
+ while(GetTouchXY(tx, ty))
+ {
+ x2 = (x2 + tx) / 2;
+ y2 = (y2 + ty) / 2;
+ // Update Display
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
+
+ // Calc coefs
+ int32_t kx = ((x2 - x1) * XPT2046::COEF) / (width - 2*10);
+ int32_t ky = ((y2 - y1) * XPT2046::COEF) / (height - 2*10);
+ int32_t bx = 10 - (x1 * XPT2046::COEF) / kx;
+ int32_t by = 10 - (y1 * XPT2046::COEF) / ky;
+
+ // Save calibration
+ touch.SetCalibrationConsts(kx, ky, bx, by);
+
+ // Hide box
+ box.Hide();
+}
diff --git a/Display/DisplayDrv.h b/Display/DisplayDrv.h
new file mode 100644
index 0000000..aafa814
--- /dev/null
+++ b/Display/DisplayDrv.h
@@ -0,0 +1,202 @@
+//******************************************************************************
+// @file DisplayDrv.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Display Driver Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef DisplayDrv_h
+#define DisplayDrv_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "DevCfg.h"
+#include "AppTask.h"
+#include "RtosMutex.h"
+#include "RtosSemaphore.h"
+
+#include "ILI9341.h"
+#include "XPT2046.h"
+#include "VisObject.h"
+#include "Primitives.h"
+#include "Strings.h"
+#include "Image.h"
+#include "TiledMap.h"
+
+// *****************************************************************************
+// *** Display Driver Class ************************************************
+// *****************************************************************************
+class DisplayDrv : public AppTask
+{
+ public:
+ // *************************************************************************
+ // *** Get Instance ****************************************************
+ // *************************************************************************
+ static DisplayDrv& GetInstance(void);
+
+ // *************************************************************************
+ // *** Display Driver Setup ********************************************
+ // *************************************************************************
+ virtual Result Setup();
+
+ // *************************************************************************
+ // *** Display Driver Loop *********************************************
+ // *************************************************************************
+ virtual Result Loop();
+
+ // *************************************************************************
+ // *** Add Visual Object to object list ********************************
+ // *************************************************************************
+ Result AddVisObjectToList(VisObject* obj, uint32_t z);
+
+ // *************************************************************************
+ // *** Delete Visual Object from object list ***************************
+ // *************************************************************************
+ Result DelVisObjectFromList(VisObject* obj);
+
+ // *************************************************************************
+ // *** Lock display ****************************************************
+ // *************************************************************************
+ Result LockDisplay(uint32_t wait_ms = portMAX_DELAY);
+
+ // *************************************************************************
+ // *** Unlock display **************************************************
+ // *************************************************************************
+ Result UnlockDisplay(void);
+
+ // *************************************************************************
+ // *** Lock display line ***********************************************
+ // *************************************************************************
+ Result LockDisplayLine(uint32_t wait_ms = portMAX_DELAY);
+
+ // *************************************************************************
+ // *** Unlock display line *********************************************
+ // *************************************************************************
+ Result UnlockDisplayLine(void);
+
+ // *************************************************************************
+ // *** Update display **************************************************
+ // *************************************************************************
+ Result UpdateDisplay(void);
+
+ // *************************************************************************
+ // *** Set Update Mode *************************************************
+ // *************************************************************************
+ void SetUpdateMode(bool is_vertical = false);
+
+ // *************************************************************************
+ // *** GetScreenW ******************************************************
+ // *************************************************************************
+ inline int32_t GetScreenW(void) {return width;}
+
+ // *************************************************************************
+ // *** GetScreenH ******************************************************
+ // *************************************************************************
+ inline int32_t GetScreenH(void) {return height;}
+
+ // *************************************************************************
+ // *** Get Touch X and Y coordinate ************************************
+ // *************************************************************************
+ bool GetTouchXY(int32_t& x, int32_t& y);
+
+ // *************************************************************************
+ // *** Check touch *****************************************************
+ // *************************************************************************
+ bool IsTouch();
+
+ // *************************************************************************
+ // *** Calibrate Touchscreen *******************************************
+ // *************************************************************************
+ void TouchCalibrate();
+
+ private:
+ // Display FPS/touch coordinates
+ static const bool DISPLAY_DEBUG_INFO = true;
+
+ // Display driver object
+ ILI9341 tft = TFT_HSPI;
+ // Display SPI handle
+ SPI_HandleTypeDef* tft_hspi = TFT_HSPI;
+
+ // Touchscreen driver object
+ XPT2046 touch = TOUCH_HSPI;
+ // Touchscreen SPI handle
+ SPI_HandleTypeDef* touch_hspi = TOUCH_HSPI;
+
+ // Pointer to first object in list
+ VisObject* object_list = nullptr;
+ // Pointer to last object in list
+ VisObject* object_list_last = nullptr;
+
+ // Update mode: true - vertical, false = horizontal
+ bool update_mode = false;
+ // Variables for update screen mode
+ int32_t width = 0;
+ int32_t height = 0;
+ // Double Screen Line buffer
+ uint16_t scr_buf[2][ILI9341::GetMaxLine()];
+
+ // Touch coordinates and state
+ bool is_touch = false;
+ int32_t tx = 0;
+ int32_t ty = 0;
+
+ // FPS multiplied to 10
+ volatile uint32_t fps_x10 = 0U;
+ // Buffer for print FPS string
+ char str[32] = {" "};
+ // FPS string
+ String fps_str;
+
+ // Semaphore for update screen
+ RtosSemaphore screen_update;
+ // Mutex to synchronize when drawing lines
+ RtosMutex line_mutex;
+ // Mutex to synchronize when drawing frames
+ RtosMutex frame_mutex;
+ // Mutex for synchronize when reads touch coordinates
+ RtosMutex touchscreen_mutex;
+
+ // *************************************************************************
+ // ** Private constructor. Only GetInstance() allow to access this class. **
+ // *************************************************************************
+ DisplayDrv() : AppTask(DISPLAY_DRV_TASK_STACK_SIZE, DISPLAY_DRV_TASK_PRIORITY,
+ "DisplayDrv") {};
+};
+
+#endif
diff --git a/Display/Fonts.c b/Display/Fonts.c
new file mode 100644
index 0000000..06bf86b
--- /dev/null
+++ b/Display/Fonts.c
@@ -0,0 +1,1312 @@
+//******************************************************************************
+// @file Fonts.c
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Fonts data
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+const unsigned char font4x6[256][6] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 - ' '
+ {0x04, 0x0A, 0x0E, 0x0A, 0x04, 0x00}, // 0x01 - ''
+ {0x04, 0x0E, 0x0A, 0x0E, 0x04, 0x00}, // 0x02 - ''
+ {0x00, 0x0A, 0x0E, 0x0E, 0x04, 0x00}, // 0x03 - ''
+ {0x00, 0x04, 0x0E, 0x0E, 0x04, 0x00}, // 0x04 - ''
+ {0x04, 0x0E, 0x0E, 0x04, 0x0E, 0x00}, // 0x05 - ''
+ {0x04, 0x04, 0x0E, 0x04, 0x0E, 0x00}, // 0x06 - ''
+ {0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, // 0x07 - ''
+ {0x0F, 0x0F, 0x0B, 0x0F, 0x0F, 0x0F}, // 0x08 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09 - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A - ' '
+ {0x00, 0x0C, 0x08, 0x06, 0x06, 0x00}, // 0x0B - ' '
+ {0x04, 0x0A, 0x04, 0x0E, 0x04, 0x00}, // 0x0C - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D - ' '
+ {0x04, 0x0C, 0x0A, 0x08, 0x04, 0x00}, // 0x0E - ''
+ {0x04, 0x0E, 0x0A, 0x0E, 0x04, 0x00}, // 0x0F - ''
+ {0x02, 0x06, 0x0E, 0x06, 0x02, 0x00}, // 0x10 - ''
+ {0x08, 0x0C, 0x0E, 0x0C, 0x08, 0x00}, // 0x11 - ''
+ {0x04, 0x0E, 0x04, 0x0E, 0x04, 0x00}, // 0x12 - ''
+ {0x0A, 0x0A, 0x0A, 0x00, 0x0A, 0x00}, // 0x13 - ''
+ {0x0E, 0x0B, 0x0B, 0x0A, 0x0A, 0x00}, // 0x14 - ''
+ {0x0C, 0x06, 0x0A, 0x0C, 0x06, 0x00}, // 0x15 - ''
+ {0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, // 0x16 - ''
+ {0x04, 0x0E, 0x04, 0x0E, 0x04, 0x0E}, // 0x17 - ''
+ {0x04, 0x0E, 0x04, 0x04, 0x04, 0x00}, // 0x18 - ''
+ {0x04, 0x04, 0x04, 0x0E, 0x04, 0x00}, // 0x19 - ''
+ {0x00, 0x04, 0x0F, 0x04, 0x00, 0x00}, // 0x1A - ' '
+ {0x00, 0x02, 0x0F, 0x02, 0x00, 0x00}, // 0x1B - ''
+ {0x00, 0x00, 0x02, 0x0E, 0x00, 0x00}, // 0x1C - ''
+ {0x00, 0x0A, 0x0E, 0x0A, 0x00, 0x00}, // 0x1D - ''
+ {0x00, 0x04, 0x0E, 0x0E, 0x00, 0x00}, // 0x1E - ''
+ {0x00, 0x0E, 0x0E, 0x04, 0x00, 0x00}, // 0x1F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 - ' '
+ {0x04, 0x04, 0x04, 0x00, 0x04, 0x00}, // 0x21 - '!'
+ {0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00}, // 0x22 - '"'
+ {0x0A, 0x0E, 0x0A, 0x0E, 0x0A, 0x00}, // 0x23 - '#'
+ {0x04, 0x0C, 0x06, 0x0C, 0x06, 0x04}, // 0x24 - '$'
+ {0x02, 0x08, 0x04, 0x02, 0x08, 0x00}, // 0x25 - '%'
+ {0x04, 0x0A, 0x0C, 0x0A, 0x0E, 0x00}, // 0x26 - '&'
+ {0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, // 0x27 - '''
+ {0x04, 0x02, 0x02, 0x02, 0x04, 0x00}, // 0x28 - '('
+ {0x02, 0x04, 0x04, 0x04, 0x02, 0x00}, // 0x29 - ')'
+ {0x0A, 0x04, 0x0E, 0x04, 0x0A, 0x00}, // 0x2A - '*'
+ {0x00, 0x04, 0x0E, 0x04, 0x00, 0x00}, // 0x2B - '+'
+ {0x00, 0x00, 0x00, 0x00, 0x06, 0x02}, // 0x2C - ','
+ {0x00, 0x00, 0x0E, 0x00, 0x00, 0x00}, // 0x2D - '-'
+ {0x00, 0x00, 0x00, 0x00, 0x04, 0x00}, // 0x2E - '.'
+ {0x08, 0x08, 0x04, 0x02, 0x02, 0x00}, // 0x2F - '/'
+ {0x0C, 0x0A, 0x0A, 0x0A, 0x06, 0x00}, // 0x30 - '0'
+ {0x04, 0x06, 0x04, 0x04, 0x0E, 0x00}, // 0x31 - '1'
+ {0x06, 0x08, 0x04, 0x02, 0x0E, 0x00}, // 0x32 - '2'
+ {0x06, 0x08, 0x04, 0x08, 0x06, 0x00}, // 0x33 - '3'
+ {0x08, 0x0A, 0x0E, 0x08, 0x08, 0x00}, // 0x34 - '4'
+ {0x0E, 0x02, 0x06, 0x08, 0x06, 0x00}, // 0x35 - '5'
+ {0x04, 0x02, 0x06, 0x0A, 0x04, 0x00}, // 0x36 - '6'
+ {0x0E, 0x08, 0x0C, 0x04, 0x04, 0x00}, // 0x37 - '7'
+ {0x04, 0x0A, 0x04, 0x0A, 0x04, 0x00}, // 0x38 - '8'
+ {0x04, 0x0A, 0x0C, 0x08, 0x04, 0x00}, // 0x39 - '9'
+ {0x00, 0x00, 0x04, 0x00, 0x04, 0x00}, // 0x3A - ':'
+ {0x00, 0x00, 0x04, 0x00, 0x06, 0x02}, // 0x3B - ';'
+ {0x08, 0x04, 0x02, 0x04, 0x08, 0x00}, // 0x3C - '<'
+ {0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00}, // 0x3D - '='
+ {0x02, 0x04, 0x08, 0x04, 0x02, 0x00}, // 0x3E - '>'
+ {0x06, 0x08, 0x04, 0x00, 0x04, 0x00}, // 0x3F - '?'
+ {0x0E, 0x0A, 0x0A, 0x02, 0x0E, 0x00}, // 0x40 - '@'
+ {0x04, 0x0A, 0x0E, 0x0A, 0x0A, 0x00}, // 0x41 - 'A'
+ {0x06, 0x0A, 0x06, 0x0A, 0x06, 0x00}, // 0x42 - 'B'
+ {0x0C, 0x02, 0x02, 0x02, 0x0C, 0x00}, // 0x43 - 'C'
+ {0x06, 0x0A, 0x0A, 0x0A, 0x06, 0x00}, // 0x44 - 'D'
+ {0x0E, 0x02, 0x06, 0x02, 0x0E, 0x00}, // 0x45 - 'E'
+ {0x0E, 0x02, 0x06, 0x02, 0x02, 0x00}, // 0x46 - 'F'
+ {0x0C, 0x02, 0x0A, 0x0A, 0x0C, 0x00}, // 0x47 - 'G'
+ {0x0A, 0x0A, 0x0E, 0x0A, 0x0A, 0x00}, // 0x48 - 'H'
+ {0x0E, 0x04, 0x04, 0x04, 0x0E, 0x00}, // 0x49 - 'I'
+ {0x08, 0x08, 0x08, 0x0A, 0x04, 0x00}, // 0x4A - 'J'
+ {0x0A, 0x0A, 0x06, 0x0A, 0x0A, 0x00}, // 0x4B - 'K'
+ {0x02, 0x02, 0x02, 0x02, 0x0E, 0x00}, // 0x4C - 'L'
+ {0x0A, 0x0E, 0x0E, 0x0A, 0x0A, 0x00}, // 0x4D - 'M'
+ {0x0A, 0x0E, 0x0A, 0x0A, 0x0A, 0x00}, // 0x4E - 'N'
+ {0x04, 0x0A, 0x0A, 0x0A, 0x04, 0x00}, // 0x4F - 'O'
+ {0x06, 0x0A, 0x06, 0x02, 0x02, 0x00}, // 0x50 - 'P'
+ {0x04, 0x0A, 0x0A, 0x0E, 0x0C, 0x00}, // 0x51 - 'Q'
+ {0x06, 0x0A, 0x06, 0x0A, 0x0A, 0x00}, // 0x52 - 'R'
+ {0x0C, 0x02, 0x0E, 0x08, 0x06, 0x00}, // 0x53 - 'S'
+ {0x0E, 0x04, 0x04, 0x04, 0x04, 0x00}, // 0x54 - 'T'
+ {0x0A, 0x0A, 0x0A, 0x0A, 0x0E, 0x00}, // 0x55 - 'U'
+ {0x0A, 0x0A, 0x0A, 0x0A, 0x04, 0x00}, // 0x56 - 'V'
+ {0x0A, 0x0A, 0x0E, 0x0E, 0x0A, 0x00}, // 0x57 - 'W'
+ {0x0A, 0x0A, 0x04, 0x0A, 0x0A, 0x00}, // 0x58 - 'X'
+ {0x0A, 0x0A, 0x04, 0x04, 0x04, 0x00}, // 0x59 - 'Y'
+ {0x0E, 0x08, 0x04, 0x02, 0x0E, 0x00}, // 0x5A - 'Z'
+ {0x06, 0x02, 0x02, 0x02, 0x06, 0x00}, // 0x5B - '['
+ {0x02, 0x02, 0x04, 0x08, 0x08, 0x00}, // 0x5C - '\'
+ {0x06, 0x04, 0x04, 0x04, 0x06, 0x00}, // 0x5D - ']'
+ {0x04, 0x0A, 0x00, 0x00, 0x00, 0x00}, // 0x5E - '^'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0F}, // 0x5F - '_'
+ {0x06, 0x04, 0x00, 0x00, 0x00, 0x00}, // 0x60 - '`'
+ {0x00, 0x00, 0x0C, 0x0A, 0x0E, 0x00}, // 0x61 - 'a'
+ {0x02, 0x02, 0x06, 0x0A, 0x06, 0x00}, // 0x62 - 'b'
+ {0x00, 0x00, 0x0C, 0x02, 0x0C, 0x00}, // 0x63 - 'c'
+ {0x08, 0x08, 0x0C, 0x0A, 0x0C, 0x00}, // 0x64 - 'd'
+ {0x00, 0x00, 0x0E, 0x06, 0x0C, 0x00}, // 0x65 - 'e'
+ {0x08, 0x04, 0x0E, 0x04, 0x04, 0x00}, // 0x66 - 'f'
+ {0x00, 0x00, 0x0E, 0x0A, 0x08, 0x0E}, // 0x67 - 'g'
+ {0x02, 0x02, 0x06, 0x0A, 0x0A, 0x00}, // 0x68 - 'h'
+ {0x04, 0x00, 0x04, 0x04, 0x04, 0x00}, // 0x69 - 'i'
+ {0x04, 0x00, 0x04, 0x04, 0x04, 0x06}, // 0x6A - 'j'
+ {0x02, 0x02, 0x0A, 0x06, 0x0A, 0x00}, // 0x6B - 'k'
+ {0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, // 0x6C - 'l'
+ {0x00, 0x00, 0x0E, 0x0E, 0x0A, 0x00}, // 0x6D - 'm'
+ {0x00, 0x00, 0x06, 0x0A, 0x0A, 0x00}, // 0x6E - 'n'
+ {0x00, 0x00, 0x04, 0x0A, 0x04, 0x00}, // 0x6F - 'o'
+ {0x00, 0x00, 0x06, 0x0A, 0x06, 0x02}, // 0x70 - 'p'
+ {0x00, 0x00, 0x0C, 0x0A, 0x0C, 0x08}, // 0x71 - 'q'
+ {0x00, 0x00, 0x06, 0x02, 0x02, 0x00}, // 0x72 - 'r'
+ {0x00, 0x00, 0x0C, 0x04, 0x06, 0x00}, // 0x73 - 's'
+ {0x00, 0x04, 0x0E, 0x04, 0x0C, 0x00}, // 0x74 - 't'
+ {0x00, 0x00, 0x0A, 0x0A, 0x0E, 0x00}, // 0x75 - 'u'
+ {0x00, 0x00, 0x0A, 0x0A, 0x04, 0x00}, // 0x76 - 'v'
+ {0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x00}, // 0x77 - 'w'
+ {0x00, 0x00, 0x0A, 0x04, 0x0A, 0x00}, // 0x78 - 'x'
+ {0x00, 0x00, 0x0A, 0x0A, 0x04, 0x02}, // 0x79 - 'y'
+ {0x00, 0x00, 0x06, 0x04, 0x0C, 0x00}, // 0x7A - 'z'
+ {0x0C, 0x04, 0x06, 0x04, 0x0C, 0x00}, // 0x7B - '{'
+ {0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, // 0x7C - '|'
+ {0x06, 0x04, 0x0C, 0x04, 0x06, 0x00}, // 0x7D - '}'
+ {0x0A, 0x05, 0x00, 0x00, 0x00, 0x00}, // 0x7E - '~'
+ {0x00, 0x04, 0x0A, 0x0E, 0x00, 0x00}, // 0x7F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x80 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x81 - '�'
+ {0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, // 0x82 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x83 - '�'
+ {0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00}, // 0x84 - '�'
+ {0x00, 0x00, 0x04, 0x00, 0x04, 0x00}, // 0x85 - '�'
+ {0x04, 0x04, 0x0F, 0x04, 0x04, 0x04}, // 0x86 - '�'
+ {0x04, 0x0F, 0x00, 0x0F, 0x04, 0x04}, // 0x87 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x88 - '�'
+ {0x02, 0x08, 0x04, 0x02, 0x08, 0x00}, // 0x89 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8A - '�'
+ {0x08, 0x04, 0x02, 0x04, 0x08, 0x00}, // 0x8B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x90 - '�'
+ {0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, // 0x91 - '�'
+ {0x06, 0x02, 0x00, 0x00, 0x00, 0x00}, // 0x92 - '�'
+ {0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00}, // 0x93 - '�'
+ {0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00}, // 0x94 - '�'
+ {0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, // 0x95 - '�'
+ {0x00, 0x00, 0x0E, 0x00, 0x00, 0x00}, // 0x96 - '�'
+ {0x00, 0x00, 0x0E, 0x00, 0x00, 0x00}, // 0x97 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x98 - '�'
+ {0x0E, 0x04, 0x04, 0x04, 0x04, 0x00}, // 0x99 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9A - '�'
+ {0x02, 0x04, 0x08, 0x04, 0x02, 0x00}, // 0x9B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0 - '�'
+ {0x07, 0x05, 0x07, 0x04, 0x03, 0x00}, // 0xA1 - '�'
+ {0x00, 0x02, 0x05, 0x05, 0x02, 0x01}, // 0xA2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA3 - '�'
+ {0x00, 0x07, 0x05, 0x05, 0x07, 0x00}, // 0xA4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA5 - '�'
+ {0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, // 0xA6 - '�'
+ {0x0C, 0x06, 0x0A, 0x0C, 0x06, 0x00}, // 0xA7 - '�'
+ {0x07, 0x01, 0x03, 0x01, 0x07, 0x00}, // 0xA8 - '�'
+ {0x00, 0x00, 0x0C, 0x02, 0x0C, 0x00}, // 0xA9 - '�'
+ {0x06, 0x01, 0x07, 0x01, 0x06, 0x00}, // 0xAA - '�'
+ {0x08, 0x04, 0x02, 0x04, 0x08, 0x00}, // 0xAB - '�'
+ {0x00, 0x00, 0x07, 0x04, 0x04, 0x04}, // 0xAC - '�'
+ {0x00, 0x00, 0x0E, 0x00, 0x00, 0x00}, // 0xAD - '�'
+ {0x06, 0x0A, 0x06, 0x0A, 0x0A, 0x00}, // 0xAE - '�'
+ {0x05, 0x02, 0x02, 0x02, 0x02, 0x00}, // 0xAF - '�'
+ {0x04, 0x0A, 0x04, 0x00, 0x00, 0x00}, // 0xB0 - '�'
+ {0x00, 0x04, 0x0E, 0x04, 0x00, 0x00}, // 0xB1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB4 - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x04, 0x00}, // 0xB5 - '�'
+ {0x0E, 0x0B, 0x0B, 0x0A, 0x0A, 0x00}, // 0xB6 - '�'
+ {0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, // 0xB7 - '�'
+ {0x05, 0x00, 0x07, 0x03, 0x06, 0x00}, // 0xB8 - '�'
+ {0x05, 0x07, 0x07, 0x07, 0x05, 0x00}, // 0xB9 - '�'
+ {0x00, 0x00, 0x06, 0x03, 0x06, 0x00}, // 0xBA - '�'
+ {0x02, 0x04, 0x08, 0x04, 0x02, 0x00}, // 0xBB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBE - '�'
+ {0x00, 0x00, 0x05, 0x02, 0x02, 0x00}, // 0xBF - '�'
+ {0x02, 0x05, 0x07, 0x05, 0x05, 0x00}, // 0xC0 - '�'
+ {0x07, 0x01, 0x03, 0x05, 0x03, 0x00}, // 0xC1 - '�'
+ {0x03, 0x05, 0x03, 0x05, 0x03, 0x00}, // 0xC2 - '�'
+ {0x07, 0x01, 0x01, 0x01, 0x01, 0x00}, // 0xC3 - '�'
+ {0x02, 0x02, 0x02, 0x07, 0x05, 0x00}, // 0xC4 - '�'
+ {0x07, 0x01, 0x03, 0x01, 0x07, 0x00}, // 0xC5 - '�'
+ {0x05, 0x07, 0x02, 0x07, 0x05, 0x00}, // 0xC6 - '�'
+ {0x07, 0x04, 0x06, 0x04, 0x07, 0x00}, // 0xC7 - '�'
+ {0x05, 0x05, 0x07, 0x07, 0x05, 0x00}, // 0xC8 - '�'
+ {0x07, 0x05, 0x07, 0x07, 0x05, 0x00}, // 0xC9 - '�'
+ {0x05, 0x03, 0x03, 0x05, 0x05, 0x00}, // 0xCA - '�'
+ {0x06, 0x05, 0x05, 0x05, 0x05, 0x00}, // 0xCB - '�'
+ {0x05, 0x07, 0x05, 0x05, 0x05, 0x00}, // 0xCC - '�'
+ {0x05, 0x05, 0x07, 0x05, 0x05, 0x00}, // 0xCD - '�'
+ {0x02, 0x05, 0x05, 0x05, 0x02, 0x00}, // 0xCE - '�'
+ {0x07, 0x05, 0x05, 0x05, 0x05, 0x00}, // 0xCF - '�'
+ {0x03, 0x05, 0x03, 0x01, 0x01, 0x00}, // 0xD0 - '�'
+ {0x06, 0x01, 0x01, 0x01, 0x06, 0x00}, // 0xD1 - '�'
+ {0x07, 0x02, 0x02, 0x02, 0x02, 0x00}, // 0xD2 - '�'
+ {0x05, 0x05, 0x07, 0x04, 0x03, 0x00}, // 0xD3 - '�'
+ {0x02, 0x07, 0x05, 0x07, 0x02, 0x00}, // 0xD4 - '�'
+ {0x05, 0x05, 0x02, 0x05, 0x05, 0x00}, // 0xD5 - '�'
+ {0x05, 0x05, 0x05, 0x05, 0x0F, 0x08}, // 0xD6 - '�'
+ {0x05, 0x05, 0x07, 0x04, 0x04, 0x00}, // 0xD7 - '�'
+ {0x05, 0x05, 0x07, 0x07, 0x07, 0x00}, // 0xD8 - '�'
+ {0x05, 0x05, 0x07, 0x07, 0x0F, 0x08}, // 0xD9 - '�'
+ {0x03, 0x02, 0x06, 0x06, 0x06, 0x00}, // 0xDA - '�'
+ {0x05, 0x05, 0x07, 0x05, 0x07, 0x00}, // 0xDB - '�'
+ {0x01, 0x01, 0x03, 0x05, 0x03, 0x00}, // 0xDC - '�'
+ {0x03, 0x04, 0x06, 0x04, 0x03, 0x00}, // 0xDD - '�'
+ {0x05, 0x0F, 0x0B, 0x0F, 0x05, 0x00}, // 0xDE - '�'
+ {0x06, 0x05, 0x06, 0x05, 0x05, 0x00}, // 0xDF - '�'
+ {0x00, 0x00, 0x06, 0x05, 0x06, 0x00}, // 0xE0 - '�'
+ {0x00, 0x00, 0x07, 0x03, 0x07, 0x00}, // 0xE1 - '�'
+ {0x00, 0x00, 0x03, 0x07, 0x07, 0x00}, // 0xE2 - '�'
+ {0x00, 0x00, 0x07, 0x01, 0x01, 0x00}, // 0xE3 - '�'
+ {0x00, 0x00, 0x02, 0x07, 0x05, 0x00}, // 0xE4 - '�'
+ {0x00, 0x00, 0x07, 0x03, 0x06, 0x00}, // 0xE5 - '�'
+ {0x00, 0x00, 0x07, 0x02, 0x07, 0x00}, // 0xE6 - '�'
+ {0x00, 0x00, 0x07, 0x06, 0x07, 0x00}, // 0xE7 - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x05, 0x00}, // 0xE8 - '�'
+ {0x02, 0x00, 0x05, 0x07, 0x05, 0x00}, // 0xE9 - '�'
+ {0x00, 0x00, 0x05, 0x03, 0x05, 0x00}, // 0xEA - '�'
+ {0x00, 0x00, 0x06, 0x05, 0x05, 0x00}, // 0xEB - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x07, 0x00}, // 0xEC - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x05, 0x00}, // 0xED - '�'
+ {0x00, 0x00, 0x02, 0x05, 0x02, 0x00}, // 0xEE - '�'
+ {0x00, 0x00, 0x07, 0x05, 0x05, 0x00}, // 0xEF - '�'
+ {0x00, 0x00, 0x03, 0x05, 0x03, 0x01}, // 0xF0 - '�'
+ {0x00, 0x00, 0x06, 0x01, 0x06, 0x00}, // 0xF1 - '�'
+ {0x00, 0x00, 0x07, 0x02, 0x02, 0x00}, // 0xF2 - '�'
+ {0x00, 0x00, 0x05, 0x05, 0x02, 0x01}, // 0xF3 - '�'
+ {0x00, 0x00, 0x07, 0x05, 0x07, 0x02}, // 0xF4 - '�'
+ {0x00, 0x00, 0x05, 0x02, 0x05, 0x00}, // 0xF5 - '�'
+ {0x00, 0x00, 0x05, 0x05, 0x0F, 0x08}, // 0xF6 - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x04, 0x00}, // 0xF7 - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x07, 0x00}, // 0xF8 - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x0F, 0x08}, // 0xF9 - '�'
+ {0x00, 0x00, 0x03, 0x06, 0x06, 0x00}, // 0xFA - '�'
+ {0x00, 0x00, 0x05, 0x07, 0x07, 0x00}, // 0xFB - '�'
+ {0x00, 0x00, 0x01, 0x07, 0x07, 0x00}, // 0xFC - '�'
+ {0x00, 0x00, 0x03, 0x06, 0x03, 0x00}, // 0xFD - '�'
+ {0x00, 0x00, 0x05, 0x0F, 0x05, 0x00}, // 0xFE - '�'
+ {0x00, 0x00, 0x07, 0x06, 0x05, 0x00} // 0xFF - '�'
+};
+
+const unsigned char font6x8[256][8] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 - ' '
+ {0x1C, 0x22, 0x36, 0x22, 0x2A, 0x22, 0x1C, 0x00}, // 0x01 - ''
+ {0x1C, 0x3E, 0x2A, 0x3E, 0x22, 0x3E, 0x1C, 0x00}, // 0x02 - ''
+ {0x00, 0x14, 0x3E, 0x3E, 0x3E, 0x1C, 0x08, 0x00}, // 0x03 - ''
+ {0x00, 0x08, 0x1C, 0x3E, 0x3E, 0x1C, 0x08, 0x00}, // 0x04 - ''
+ {0x08, 0x1C, 0x1C, 0x08, 0x3E, 0x3E, 0x08, 0x00}, // 0x05 - ''
+ {0x00, 0x08, 0x1C, 0x3E, 0x3E, 0x08, 0x1C, 0x00}, // 0x06 - ''
+ {0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x00}, // 0x07 - ''
+ {0x3F, 0x3F, 0x3F, 0x33, 0x33, 0x3F, 0x3F, 0x3F}, // 0x08 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09 - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A - ' '
+ {0x00, 0x38, 0x30, 0x2C, 0x12, 0x12, 0x0C, 0x00}, // 0x0B - ' '
+ {0x1C, 0x22, 0x22, 0x1C, 0x08, 0x1C, 0x08, 0x00}, // 0x0C - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D - ' '
+ {0x30, 0x2C, 0x34, 0x2C, 0x34, 0x36, 0x06, 0x00}, // 0x0E - ''
+ {0x00, 0x2A, 0x1C, 0x36, 0x1C, 0x2A, 0x00, 0x00}, // 0x0F - ''
+ {0x04, 0x0C, 0x1C, 0x3C, 0x1C, 0x0C, 0x04, 0x00}, // 0x10 - ''
+ {0x10, 0x18, 0x1C, 0x1E, 0x1C, 0x18, 0x10, 0x00}, // 0x11 - ''
+ {0x08, 0x1C, 0x3E, 0x08, 0x3E, 0x1C, 0x08, 0x00}, // 0x12 - ''
+ {0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x14, 0x00}, // 0x13 - ''
+ {0x3C, 0x2A, 0x2A, 0x2C, 0x28, 0x28, 0x28, 0x00}, // 0x14 - ''
+ {0x1C, 0x22, 0x0C, 0x14, 0x18, 0x22, 0x1C, 0x00}, // 0x15 - ''
+ {0x00, 0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00}, // 0x16 - ''
+ {0x08, 0x1C, 0x3E, 0x08, 0x3E, 0x1C, 0x08, 0x1C}, // 0x17 - ''
+ {0x08, 0x1C, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x00}, // 0x18 - ''
+ {0x08, 0x08, 0x08, 0x08, 0x3E, 0x1C, 0x08, 0x00}, // 0x19 - ''
+ {0x00, 0x08, 0x18, 0x3E, 0x18, 0x08, 0x00, 0x00}, // 0x1A - ' '
+ {0x00, 0x08, 0x0C, 0x3E, 0x0C, 0x08, 0x00, 0x00}, // 0x1B - ''
+ {0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3E, 0x00}, // 0x1C - ''
+ {0x00, 0x14, 0x14, 0x3E, 0x14, 0x14, 0x00, 0x00}, // 0x1D - ''
+ {0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x00, 0x00}, // 0x1E - ''
+ {0x3E, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x00, 0x00}, // 0x1F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 - ' '
+ {0x08, 0x1C, 0x1C, 0x08, 0x08, 0x00, 0x08, 0x00}, // 0x21 - '!'
+ {0x36, 0x36, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x22 - '"'
+ {0x00, 0x14, 0x3E, 0x14, 0x14, 0x3E, 0x14, 0x00}, // 0x23 - '#'
+ {0x04, 0x1C, 0x02, 0x0C, 0x10, 0x0E, 0x08, 0x00}, // 0x24 - '$'
+ {0x26, 0x26, 0x10, 0x08, 0x04, 0x32, 0x32, 0x00}, // 0x25 - '%'
+ {0x04, 0x0A, 0x0A, 0x04, 0x2A, 0x12, 0x2C, 0x00}, // 0x26 - '&'
+ {0x0C, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x27 - '''
+ {0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x00}, // 0x28 - '('
+ {0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00}, // 0x29 - ')'
+ {0x00, 0x14, 0x1C, 0x3E, 0x1C, 0x14, 0x00, 0x00}, // 0x2A - '*'
+ {0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00}, // 0x2B - '+'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x04}, // 0x2C - ','
+ {0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, // 0x2D - '-'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // 0x2E - '.'
+ {0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, // 0x2F - '/'
+ {0x1C, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x1C, 0x00}, // 0x30 - '0'
+ {0x08, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00}, // 0x31 - '1'
+ {0x1C, 0x22, 0x20, 0x18, 0x04, 0x02, 0x3E, 0x00}, // 0x32 - '2'
+ {0x1C, 0x22, 0x20, 0x1C, 0x20, 0x22, 0x1C, 0x00}, // 0x33 - '3'
+ {0x10, 0x18, 0x14, 0x12, 0x3E, 0x10, 0x10, 0x00}, // 0x34 - '4'
+ {0x3E, 0x02, 0x02, 0x1E, 0x20, 0x22, 0x1C, 0x00}, // 0x35 - '5'
+ {0x18, 0x04, 0x02, 0x1E, 0x22, 0x22, 0x1C, 0x00}, // 0x36 - '6'
+ {0x3E, 0x20, 0x10, 0x08, 0x04, 0x04, 0x04, 0x00}, // 0x37 - '7'
+ {0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00}, // 0x38 - '8'
+ {0x1C, 0x22, 0x22, 0x3C, 0x20, 0x10, 0x0C, 0x00}, // 0x39 - '9'
+ {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00}, // 0x3A - ':'
+ {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x04}, // 0x3B - ';'
+ {0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00}, // 0x3C - '<'
+ {0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00}, // 0x3D - '='
+ {0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00}, // 0x3E - '>'
+ {0x1C, 0x22, 0x20, 0x18, 0x08, 0x00, 0x08, 0x00}, // 0x3F - '?'
+ {0x1C, 0x22, 0x3A, 0x2A, 0x3A, 0x02, 0x1C, 0x00}, // 0x40 - '@'
+ {0x1C, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00}, // 0x41 - 'A'
+ {0x1E, 0x22, 0x22, 0x1E, 0x22, 0x22, 0x1E, 0x00}, // 0x42 - 'B'
+ {0x1C, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1C, 0x00}, // 0x43 - 'C'
+ {0x1E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1E, 0x00}, // 0x44 - 'D'
+ {0x3E, 0x02, 0x02, 0x1E, 0x02, 0x02, 0x3E, 0x00}, // 0x45 - 'E'
+ {0x3E, 0x02, 0x02, 0x1E, 0x02, 0x02, 0x02, 0x00}, // 0x46 - 'F'
+ {0x1C, 0x22, 0x02, 0x3A, 0x22, 0x22, 0x3C, 0x00}, // 0x47 - 'G'
+ {0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00}, // 0x48 - 'H'
+ {0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00}, // 0x49 - 'I'
+ {0x20, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1C, 0x00}, // 0x4A - 'J'
+ {0x22, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x22, 0x00}, // 0x4B - 'K'
+ {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3E, 0x00}, // 0x4C - 'L'
+ {0x22, 0x36, 0x2A, 0x22, 0x22, 0x22, 0x22, 0x00}, // 0x4D - 'M'
+ {0x22, 0x26, 0x2A, 0x32, 0x22, 0x22, 0x22, 0x00}, // 0x4E - 'N'
+ {0x1C, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 0x4F - 'O'
+ {0x1E, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x02, 0x00}, // 0x50 - 'P'
+ {0x1C, 0x22, 0x22, 0x22, 0x2A, 0x12, 0x2C, 0x00}, // 0x51 - 'Q'
+ {0x1E, 0x22, 0x22, 0x1E, 0x12, 0x22, 0x22, 0x00}, // 0x52 - 'R'
+ {0x1C, 0x22, 0x02, 0x1C, 0x20, 0x22, 0x1C, 0x00}, // 0x53 - 'S'
+ {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00}, // 0x54 - 'T'
+ {0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 0x55 - 'U'
+ {0x22, 0x22, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00}, // 0x56 - 'V'
+ {0x22, 0x22, 0x2A, 0x2A, 0x2A, 0x2A, 0x14, 0x00}, // 0x57 - 'W'
+ {0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00}, // 0x58 - 'X'
+ {0x22, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x00}, // 0x59 - 'Y'
+ {0x1E, 0x10, 0x08, 0x04, 0x02, 0x02, 0x1E, 0x00}, // 0x5A - 'Z'
+ {0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C, 0x00}, // 0x5B - '['
+ {0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00}, // 0x5C - '\'
+ {0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x00}, // 0x5D - ']'
+ {0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x5E - '^'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00}, // 0x5F - '_'
+ {0x0C, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x60 - '`'
+ {0x00, 0x00, 0x1C, 0x20, 0x3C, 0x22, 0x3C, 0x00}, // 0x61 - 'a'
+ {0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x00}, // 0x62 - 'b'
+ {0x00, 0x00, 0x1C, 0x22, 0x02, 0x22, 0x1C, 0x00}, // 0x63 - 'c'
+ {0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x00}, // 0x64 - 'd'
+ {0x00, 0x00, 0x1C, 0x22, 0x1E, 0x02, 0x1C, 0x00}, // 0x65 - 'e'
+ {0x18, 0x04, 0x04, 0x1E, 0x04, 0x04, 0x04, 0x00}, // 0x66 - 'f'
+ {0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x1C}, // 0x67 - 'g'
+ {0x02, 0x02, 0x0E, 0x12, 0x12, 0x12, 0x12, 0x00}, // 0x68 - 'h'
+ {0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00}, // 0x69 - 'i'
+ {0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x12, 0x0C}, // 0x6A - 'j'
+ {0x02, 0x02, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x00}, // 0x6B - 'k'
+ {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00}, // 0x6C - 'l'
+ {0x00, 0x00, 0x16, 0x2A, 0x2A, 0x22, 0x22, 0x00}, // 0x6D - 'm'
+ {0x00, 0x00, 0x0E, 0x12, 0x12, 0x12, 0x12, 0x00}, // 0x6E - 'n'
+ {0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 0x6F - 'o'
+ {0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02}, // 0x70 - 'p'
+ {0x00, 0x00, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20}, // 0x71 - 'q'
+ {0x00, 0x00, 0x1A, 0x24, 0x04, 0x04, 0x0E, 0x00}, // 0x72 - 'r'
+ {0x00, 0x00, 0x1C, 0x02, 0x1C, 0x20, 0x1C, 0x00}, // 0x73 - 's'
+ {0x00, 0x04, 0x1E, 0x04, 0x04, 0x14, 0x08, 0x00}, // 0x74 - 't'
+ {0x00, 0x00, 0x12, 0x12, 0x12, 0x1A, 0x14, 0x00}, // 0x75 - 'u'
+ {0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00}, // 0x76 - 'v'
+ {0x00, 0x00, 0x22, 0x22, 0x2A, 0x3E, 0x14, 0x00}, // 0x77 - 'w'
+ {0x00, 0x00, 0x12, 0x12, 0x0C, 0x12, 0x12, 0x00}, // 0x78 - 'x'
+ {0x00, 0x00, 0x12, 0x12, 0x12, 0x1C, 0x08, 0x06}, // 0x79 - 'y'
+ {0x00, 0x00, 0x1E, 0x10, 0x0C, 0x02, 0x1E, 0x00}, // 0x7A - 'z'
+ {0x18, 0x04, 0x04, 0x06, 0x04, 0x04, 0x18, 0x00}, // 0x7B - '{'
+ {0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00}, // 0x7C - '|'
+ {0x0C, 0x10, 0x10, 0x30, 0x10, 0x10, 0x0C, 0x00}, // 0x7D - '}'
+ {0x14, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x7E - '~'
+ {0x08, 0x1C, 0x36, 0x22, 0x22, 0x3E, 0x00, 0x00}, // 0x7F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x80 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x81 - '�'
+ {0x0C, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x82 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x83 - '�'
+ {0x36, 0x36, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x84 - '�'
+ {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00}, // 0x85 - '�'
+ {0x08, 0x08, 0x08, 0x3F, 0x08, 0x08, 0x08, 0x08}, // 0x86 - '�'
+ {0x08, 0x3F, 0x08, 0x3F, 0x08, 0x08, 0x08, 0x08}, // 0x87 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x88 - '�'
+ {0x26, 0x26, 0x10, 0x08, 0x04, 0x32, 0x32, 0x00}, // 0x89 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8A - '�'
+ {0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00}, // 0x8B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x90 - '�'
+ {0x0C, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x91 - '�'
+ {0x0C, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x92 - '�'
+ {0x36, 0x36, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x93 - '�'
+ {0x36, 0x36, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x94 - '�'
+ {0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x00}, // 0x95 - '�'
+ {0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, // 0x96 - '�'
+ {0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, // 0x97 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x98 - '�'
+ {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00}, // 0x99 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9A - '�'
+ {0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00}, // 0x9B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0 - '�'
+ {0x2A, 0x2A, 0x22, 0x3C, 0x20, 0x22, 0x1C, 0x00}, // 0xA1 - '�'
+ {0x0C, 0x00, 0x12, 0x12, 0x12, 0x1C, 0x08, 0x06}, // 0xA2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA3 - '�'
+ {0x00, 0x33, 0x1E, 0x33, 0x1E, 0x33, 0x00, 0x00}, // 0xA4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA5 - '�'
+ {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // 0xA6 - '�'
+ {0x1C, 0x22, 0x0C, 0x14, 0x18, 0x22, 0x1C, 0x00}, // 0xA7 - '�'
+ {0x14, 0x3E, 0x02, 0x1E, 0x02, 0x02, 0x3E, 0x00}, // 0xA8 - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x02, 0x22, 0x1C, 0x00}, // 0xA9 - '�'
+ {0x1C, 0x22, 0x02, 0x0E, 0x02, 0x22, 0x1C, 0x00}, // 0xAA - '�'
+ {0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00}, // 0xAB - '�'
+ {0x00, 0x00, 0x00, 0x0F, 0x08, 0x08, 0x08, 0x08}, // 0xAC - '�'
+ {0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, // 0xAD - '�'
+ {0x1E, 0x22, 0x22, 0x1E, 0x12, 0x22, 0x22, 0x00}, // 0xAE - '�'
+ {0x22, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00}, // 0xAF - '�'
+ {0x0C, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00}, // 0xB0 - '�'
+ {0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00}, // 0xB1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB4 - '�'
+ {0x00, 0x00, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x00}, // 0xB5 - '�'
+ {0x3C, 0x2A, 0x2A, 0x2C, 0x28, 0x28, 0x28, 0x00}, // 0xB6 - '�'
+ {0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, // 0xB7 - '�'
+ {0x14, 0x00, 0x1C, 0x22, 0x1E, 0x02, 0x1C, 0x00}, // 0xB8 - '�'
+ {0x39, 0x3B, 0x0B, 0x0D, 0x3D, 0x09, 0x09, 0x00}, // 0xB9 - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x0E, 0x22, 0x1C, 0x00}, // 0xBA - '�'
+ {0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00}, // 0xBB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBE - '�'
+ {0x14, 0x00, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00}, // 0xBF - '�'
+ {0x1C, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00}, // 0xC0 - '�'
+ {0x3E, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x1E, 0x00}, // 0xC1 - '�'
+ {0x1E, 0x22, 0x22, 0x1E, 0x22, 0x22, 0x1E, 0x00}, // 0xC2 - '�'
+ {0x3E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00}, // 0xC3 - '�'
+ {0x1C, 0x12, 0x12, 0x12, 0x12, 0x3F, 0x21, 0x00}, // 0xC4 - '�'
+ {0x3E, 0x02, 0x02, 0x1E, 0x02, 0x02, 0x3E, 0x00}, // 0xC5 - '�'
+ {0x2A, 0x2A, 0x2A, 0x1C, 0x2A, 0x2A, 0x2A, 0x00}, // 0xC6 - '�'
+ {0x0E, 0x11, 0x10, 0x0E, 0x10, 0x11, 0x0E, 0x00}, // 0xC7 - '�'
+ {0x22, 0x22, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x00}, // 0xC8 - '�'
+ {0x2A, 0x2A, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x00}, // 0xC9 - '�'
+ {0x22, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x22, 0x00}, // 0xCA - '�'
+ {0x38, 0x24, 0x24, 0x24, 0x24, 0x24, 0x26, 0x00}, // 0xCB - '�'
+ {0x22, 0x36, 0x2A, 0x22, 0x22, 0x22, 0x22, 0x00}, // 0xCC - '�'
+ {0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00}, // 0xCD - '�'
+ {0x1C, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 0xCE - '�'
+ {0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00}, // 0xCF - '�'
+ {0x1E, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x02, 0x00}, // 0xD0 - '�'
+ {0x1C, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1C, 0x00}, // 0xD1 - '�'
+ {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00}, // 0xD2 - '�'
+ {0x22, 0x22, 0x22, 0x3C, 0x20, 0x22, 0x1C, 0x00}, // 0xD3 - '�'
+ {0x1C, 0x2A, 0x2A, 0x2A, 0x1C, 0x08, 0x08, 0x00}, // 0xD4 - '�'
+ {0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00}, // 0xD5 - '�'
+ {0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3E, 0x20}, // 0xD6 - '�'
+ {0x22, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00}, // 0xD7 - '�'
+ {0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x3E, 0x00}, // 0xD8 - '�'
+ {0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x3E, 0x20}, // 0xD9 - '�'
+ {0x07, 0x05, 0x04, 0x1C, 0x24, 0x24, 0x1C, 0x00}, // 0xDA - '�'
+ {0x22, 0x22, 0x22, 0x2E, 0x32, 0x32, 0x2E, 0x00}, // 0xDB - '�'
+ {0x02, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x1E, 0x00}, // 0xDC - '�'
+ {0x1C, 0x22, 0x20, 0x38, 0x20, 0x22, 0x1C, 0x00}, // 0xDD - '�'
+ {0x12, 0x2A, 0x2A, 0x2E, 0x2A, 0x2A, 0x12, 0x00}, // 0xDE - '�'
+ {0x3C, 0x22, 0x22, 0x3C, 0x24, 0x22, 0x22, 0x00}, // 0xDF - '�'
+ {0x00, 0x00, 0x1C, 0x20, 0x3C, 0x22, 0x3C, 0x00}, // 0xE0 - '�'
+ {0x20, 0x1C, 0x02, 0x1E, 0x22, 0x22, 0x1C, 0x00}, // 0xE1 - '�'
+ {0x00, 0x00, 0x1E, 0x22, 0x1E, 0x22, 0x1E, 0x00}, // 0xE2 - '�'
+ {0x00, 0x00, 0x1E, 0x12, 0x02, 0x02, 0x02, 0x00}, // 0xE3 - '�'
+ {0x00, 0x00, 0x1C, 0x12, 0x12, 0x3F, 0x21, 0x00}, // 0xE4 - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x1E, 0x02, 0x1C, 0x00}, // 0xE5 - '�'
+ {0x00, 0x00, 0x2A, 0x2A, 0x1C, 0x2A, 0x2A, 0x00}, // 0xE6 - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x18, 0x22, 0x1C, 0x00}, // 0xE7 - '�'
+ {0x00, 0x00, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x00}, // 0xE8 - '�'
+ {0x00, 0x18, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x00}, // 0xE9 - '�'
+ {0x00, 0x00, 0x12, 0x0A, 0x06, 0x0A, 0x12, 0x00}, // 0xEA - '�'
+ {0x00, 0x00, 0x1C, 0x12, 0x12, 0x12, 0x11, 0x00}, // 0xEB - '�'
+ {0x00, 0x00, 0x22, 0x36, 0x2A, 0x22, 0x22, 0x00}, // 0xEC - '�'
+ {0x00, 0x00, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00}, // 0xED - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00}, // 0xEE - '�'
+ {0x00, 0x00, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x00}, // 0xEF - '�'
+ {0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02}, // 0xF0 - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x02, 0x22, 0x1C, 0x00}, // 0xF1 - '�'
+ {0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x00}, // 0xF2 - '�'
+ {0x00, 0x00, 0x12, 0x12, 0x12, 0x1C, 0x08, 0x06}, // 0xF3 - '�'
+ {0x00, 0x00, 0x1C, 0x2A, 0x2A, 0x1C, 0x08, 0x00}, // 0xF4 - '�'
+ {0x00, 0x00, 0x12, 0x12, 0x0C, 0x12, 0x12, 0x00}, // 0xF5 - '�'
+ {0x00, 0x00, 0x12, 0x12, 0x12, 0x12, 0x3E, 0x20}, // 0xF6 - '�'
+ {0x00, 0x00, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x00}, // 0xF7 - '�'
+ {0x00, 0x00, 0x2A, 0x2A, 0x2A, 0x2A, 0x3E, 0x00}, // 0xF8 - '�'
+ {0x00, 0x00, 0x2A, 0x2A, 0x2A, 0x2A, 0x3E, 0x20}, // 0xF9 - '�'
+ {0x00, 0x00, 0x07, 0x05, 0x1C, 0x24, 0x1C, 0x00}, // 0xFA - '�'
+ {0x00, 0x00, 0x22, 0x22, 0x2E, 0x32, 0x2E, 0x00}, // 0xFB - '�'
+ {0x00, 0x00, 0x02, 0x02, 0x1E, 0x22, 0x1E, 0x00}, // 0xFC - '�'
+ {0x00, 0x00, 0x1C, 0x22, 0x38, 0x22, 0x1C, 0x00}, // 0xFD - '�'
+ {0x00, 0x00, 0x12, 0x2A, 0x2E, 0x2A, 0x12, 0x00}, // 0xFE - '�'
+ {0x00, 0x00, 0x3C, 0x22, 0x3C, 0x24, 0x22, 0x00} // 0xFF - '�'
+};
+
+const unsigned char font8x8[256][8] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 - ' '
+ {0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E}, // 0x01 - ''
+ {0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E}, // 0x02 - ''
+ {0x36, 0x7F, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x00}, // 0x03 - ''
+ {0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08, 0x00}, // 0x04 - ''
+ {0x1C, 0x3E, 0x1C, 0x7F, 0x7F, 0x6B, 0x08, 0x1C}, // 0x05 - ''
+ {0x08, 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x08, 0x1C}, // 0x06 - ''
+ {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00}, // 0x07 - ''
+ {0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF}, // 0x08 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09 - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A - ' '
+ {0xF0, 0xE0, 0xF0, 0xBE, 0x33, 0x33, 0x33, 0x1E}, // 0x0B - ' '
+ {0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18}, // 0x0C - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D - ' '
+ {0xFE, 0xC6, 0xFE, 0xC6, 0xC6, 0xE6, 0x67, 0x03}, // 0x0E - ''
+ {0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99}, // 0x0F - ''
+ {0x01, 0x07, 0x1F, 0x7F, 0x1F, 0x07, 0x01, 0x00}, // 0x10 - ''
+ {0x40, 0x70, 0x7C, 0x7F, 0x7C, 0x70, 0x40, 0x00}, // 0x11 - ''
+ {0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18}, // 0x12 - ''
+ {0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00}, // 0x13 - ''
+ {0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00}, // 0x14 - ''
+ {0x7E, 0xC3, 0x1E, 0x33, 0x33, 0x1E, 0x31, 0x1F}, // 0x15 - ''
+ {0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00}, // 0x16 - ''
+ {0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF}, // 0x17 - ''
+ {0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00}, // 0x18 - ''
+ {0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00}, // 0x19 - ''
+ {0x00, 0x18, 0x30, 0x7F, 0x30, 0x18, 0x00, 0x00}, // 0x1A - ' '
+ {0x00, 0x0C, 0x06, 0x7F, 0x06, 0x0C, 0x00, 0x00}, // 0x1B - ''
+ {0x00, 0x00, 0x03, 0x03, 0x03, 0x7F, 0x00, 0x00}, // 0x1C - ''
+ {0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00}, // 0x1D - ''
+ {0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00}, // 0x1E - ''
+ {0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00}, // 0x1F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 - ' '
+ {0x0C, 0x1E, 0x1E, 0x0C, 0x0C, 0x00, 0x0C, 0x00}, // 0x21 - '!'
+ {0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x22 - '"'
+ {0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // 0x23 - '#'
+ {0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // 0x24 - '$'
+ {0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // 0x25 - '%'
+ {0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // 0x26 - '&'
+ {0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x27 - '''
+ {0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // 0x28 - '('
+ {0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // 0x29 - ')'
+ {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // 0x2A - '*'
+ {0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // 0x2B - '+'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0C, 0x06}, // 0x2C - ','
+ {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // 0x2D - '-'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // 0x2E - '.'
+ {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // 0x2F - '/'
+ {0x1E, 0x33, 0x3B, 0x3F, 0x37, 0x33, 0x1E, 0x00}, // 0x30 - '0'
+ {0x0C, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // 0x31 - '1'
+ {0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // 0x32 - '2'
+ {0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // 0x33 - '3'
+ {0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x30, 0x00}, // 0x34 - '4'
+ {0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // 0x35 - '5'
+ {0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // 0x36 - '6'
+ {0x3F, 0x33, 0x30, 0x18, 0x0C, 0x06, 0x06, 0x00}, // 0x37 - '7'
+ {0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // 0x38 - '8'
+ {0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // 0x39 - '9'
+ {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00}, // 0x3A - ':'
+ {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0E, 0x0C, 0x06}, // 0x3B - ';'
+ {0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // 0x3C - '<'
+ {0x00, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x00, 0x00}, // 0x3D - '='
+ {0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // 0x3E - '>'
+ {0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // 0x3F - '?'
+ {0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // 0x40 - '@'
+ {0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // 0x41 - 'A'
+ {0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // 0x42 - 'B'
+ {0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // 0x43 - 'C'
+ {0x3F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x3F, 0x00}, // 0x44 - 'D'
+ {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // 0x45 - 'E'
+ {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // 0x46 - 'F'
+ {0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // 0x47 - 'G'
+ {0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // 0x48 - 'H'
+ {0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0x49 - 'I'
+ {0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // 0x4A - 'J'
+ {0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // 0x4B - 'K'
+ {0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // 0x4C - 'L'
+ {0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00}, // 0x4D - 'M'
+ {0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // 0x4E - 'N'
+ {0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // 0x4F - 'O'
+ {0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // 0x50 - 'P'
+ {0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // 0x51 - 'Q'
+ {0x3F, 0x66, 0x66, 0x3E, 0x1E, 0x36, 0x67, 0x00}, // 0x52 - 'R'
+ {0x1E, 0x33, 0x07, 0x1C, 0x38, 0x33, 0x1E, 0x00}, // 0x53 - 'S'
+ {0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0x54 - 'T'
+ {0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // 0x55 - 'U'
+ {0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // 0x56 - 'V'
+ {0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // 0x57 - 'W'
+ {0x63, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x63, 0x00}, // 0x58 - 'X'
+ {0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // 0x59 - 'Y'
+ {0x7F, 0x33, 0x19, 0x0C, 0x46, 0x63, 0x7F, 0x00}, // 0x5A - 'Z'
+ {0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // 0x5B - '['
+ {0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // 0x5C - '\'
+ {0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // 0x5D - ']'
+ {0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // 0x5E - '^'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, // 0x5F - '_'
+ {0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x60 - '`'
+ {0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // 0x61 - 'a'
+ {0x07, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3D, 0x00}, // 0x62 - 'b'
+ {0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // 0x63 - 'c'
+ {0x38, 0x30, 0x30, 0x3E, 0x33, 0x33, 0x6E, 0x00}, // 0x64 - 'd'
+ {0x00, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // 0x65 - 'e'
+ {0x1C, 0x36, 0x06, 0x0F, 0x06, 0x06, 0x0F, 0x00}, // 0x66 - 'f'
+ {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // 0x67 - 'g'
+ {0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // 0x68 - 'h'
+ {0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0x69 - 'i'
+ {0x18, 0x00, 0x1E, 0x18, 0x18, 0x18, 0x1B, 0x0E}, // 0x6A - 'j'
+ {0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // 0x6B - 'k'
+ {0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0x6C - 'l'
+ {0x00, 0x00, 0x37, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // 0x6D - 'm'
+ {0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // 0x6E - 'n'
+ {0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // 0x6F - 'o'
+ {0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // 0x70 - 'p'
+ {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // 0x71 - 'q'
+ {0x00, 0x00, 0x1B, 0x36, 0x36, 0x06, 0x0F, 0x00}, // 0x72 - 'r'
+ {0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // 0x73 - 's'
+ {0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // 0x74 - 't'
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // 0x75 - 'u'
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // 0x76 - 'v'
+ {0x00, 0x00, 0x63, 0x63, 0x6B, 0x7F, 0x36, 0x00}, // 0x77 - 'w'
+ {0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // 0x78 - 'x'
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // 0x79 - 'y'
+ {0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // 0x7A - 'z'
+ {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF}, // 0x7B - '{'
+ {0xFF, 0x81, 0xBD, 0xBD, 0xBD, 0xBD, 0x81, 0xFF}, // 0x7C - '|'
+ {0xFF, 0x20, 0x70, 0x7C, 0xFE, 0xFE, 0x7C, 0x00}, // 0x7D - '}'
+ {0x07, 0x00, 0x00, 0x40, 0xFF, 0x40, 0x00, 0x00}, // 0x7E - '~'
+ {0x00, 0xE1, 0xFD, 0xFF, 0xFD, 0x31, 0x10, 0x00}, // 0x7F - ''
+ {0x00, 0xC1, 0xE3, 0xFF, 0x3F, 0x00, 0x00, 0x00}, // 0x80 - '�'
+ {0xF0, 0x08, 0x04, 0x02, 0xE1, 0xC1, 0xE1, 0xC1}, // 0x81 - '�'
+ {0x0F, 0x10, 0x21, 0x71, 0x9F, 0x8F, 0x8F, 0x87}, // 0x82 - '�'
+ {0xC1, 0xE1, 0xFD, 0xF1, 0xDA, 0x0C, 0x08, 0xF0}, // 0x83 - '�'
+ {0x87, 0x8F, 0x8F, 0x8F, 0x4F, 0x20, 0x10, 0x0F}, // 0x84 - '�'
+ {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00}, // 0x85 - '�'
+ {0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18}, // 0x86 - '�'
+ {0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18}, // 0x87 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x88 - '�'
+ {0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // 0x89 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8A - '�'
+ {0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // 0x8B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x90 - '�'
+ {0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x91 - '�'
+ {0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x92 - '�'
+ {0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x93 - '�'
+ {0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x94 - '�'
+ {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00}, // 0x95 - '�'
+ {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // 0x96 - '�'
+ {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // 0x97 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x98 - '�'
+ {0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0x99 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9A - '�'
+ {0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // 0x9B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0 - '�'
+ {0x08, 0x63, 0x63, 0x7E, 0x60, 0x63, 0x3E, 0x00}, // 0xA1 - '�'
+ {0x6B, 0x6B, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x3E}, // 0xA2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA3 - '�'
+ {0x00, 0x63, 0x3E, 0x63, 0x63, 0x3E, 0x63, 0x00}, // 0xA4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA5 - '�'
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // 0xA6 - '�'
+ {0x7E, 0xC3, 0x1E, 0x33, 0x33, 0x1E, 0x31, 0x1F}, // 0xA7 - '�'
+ {0x36, 0x7F, 0x46, 0x1E, 0x06, 0x46, 0x7F, 0x00}, // 0xA8 - '�'
+ {0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // 0xA9 - '�'
+ {0x3C, 0x66, 0x03, 0x1F, 0x03, 0x66, 0x3C, 0x00}, // 0xAA - '�'
+ {0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // 0xAB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18}, // 0xAC - '�'
+ {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // 0xAD - '�'
+ {0x3F, 0x66, 0x66, 0x3E, 0x1E, 0x36, 0x67, 0x00}, // 0xAE - '�'
+ {0x33, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0xAF - '�'
+ {0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // 0xB0 - '�'
+ {0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // 0xB1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB4 - '�'
+ {0x00, 0x00, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x00}, // 0xB5 - '�'
+ {0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00}, // 0xB6 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00}, // 0xB7 - '�'
+ {0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // 0xB8 - '�'
+ {0x71, 0x33, 0x37, 0x7F, 0x3B, 0x33, 0x33, 0x00}, // 0xB9 - '�'
+ {0x00, 0x00, 0x3E, 0x63, 0x0F, 0x63, 0x3E, 0x00}, // 0xBA - '�'
+ {0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // 0xBB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBE - '�'
+ {0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0xBF - '�'
+ {0x7C, 0x66, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x00}, // 0xC0 - '�'
+ {0x7F, 0x66, 0x06, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // 0xC1 - '�'
+ {0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // 0xC2 - '�'
+ {0x7F, 0x66, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x00}, // 0xC3 - '�'
+ {0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3}, // 0xC4 - '�'
+ {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // 0xC5 - '�'
+ {0x6B, 0x6B, 0x3E, 0x1C, 0x3E, 0x6B, 0x6B, 0x00}, // 0xC6 - '�'
+ {0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // 0xC7 - '�'
+ {0x63, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x00}, // 0xC8 - '�'
+ {0x6B, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x00}, // 0xC9 - '�'
+ {0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // 0xCA - '�'
+ {0x78, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x63, 0x00}, // 0xCB - '�'
+ {0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00}, // 0xCC - '�'
+ {0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x00}, // 0xCD - '�'
+ {0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // 0xCE - '�'
+ {0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00}, // 0xCF - '�'
+ {0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // 0xD0 - '�'
+ {0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // 0xD1 - '�'
+ {0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // 0xD2 - '�'
+ {0x63, 0x63, 0x63, 0x7E, 0x60, 0x63, 0x3E, 0x00}, // 0xD3 - '�'
+ {0x3E, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x1C, 0x00}, // 0xD4 - '�'
+ {0x63, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x63, 0x00}, // 0xD5 - '�'
+ {0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x7F, 0x60}, // 0xD6 - '�'
+ {0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x00}, // 0xD7 - '�'
+ {0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x00}, // 0xD8 - '�'
+ {0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xFF, 0xC0}, // 0xD9 - '�'
+ {0x0F, 0x0F, 0x0D, 0x3C, 0x6C, 0x6C, 0x3C, 0x00}, // 0xDA - '�'
+ {0x63, 0x63, 0x63, 0x6F, 0x7B, 0x7B, 0x6F, 0x00}, // 0xDB - '�'
+ {0x0F, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00}, // 0xDC - '�'
+ {0x1E, 0x33, 0x60, 0x7C, 0x60, 0x33, 0x1E, 0x00}, // 0xDD - '�'
+ {0x3B, 0x6B, 0x6B, 0x6F, 0x6B, 0x6B, 0x3B, 0x00}, // 0xDE - '�'
+ {0x7E, 0x63, 0x63, 0x7E, 0x7C, 0x66, 0x63, 0x00}, // 0xDF - '�'
+ {0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // 0xE0 - '�'
+ {0x60, 0x3E, 0x03, 0x3E, 0x63, 0x63, 0x3E, 0x00}, // 0xE1 - '�'
+ {0x00, 0x00, 0x3F, 0x66, 0x3E, 0x66, 0x3F, 0x00}, // 0xE2 - '�'
+ {0x00, 0x00, 0x7F, 0x66, 0x06, 0x06, 0x0F, 0x00}, // 0xE3 - '�'
+ {0x00, 0x00, 0x3C, 0x36, 0x36, 0x36, 0x7F, 0x63}, // 0xE4 - '�'
+ {0x00, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // 0xE5 - '�'
+ {0x00, 0x00, 0x6B, 0x3E, 0x1C, 0x3E, 0x6B, 0x00}, // 0xE6 - '�'
+ {0x00, 0x00, 0x3E, 0x63, 0x38, 0x63, 0x3E, 0x00}, // 0xE7 - '�'
+ {0x00, 0x00, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x00}, // 0xE8 - '�'
+ {0x08, 0x63, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x00}, // 0xE9 - '�'
+ {0x00, 0x00, 0x67, 0x36, 0x1E, 0x36, 0x67, 0x00}, // 0xEA - '�'
+ {0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x67, 0x00}, // 0xEB - '�'
+ {0x00, 0x00, 0x63, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // 0xEC - '�'
+ {0x00, 0x00, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x00}, // 0xED - '�'
+ {0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // 0xEE - '�'
+ {0x00, 0x00, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x00}, // 0xEF - '�'
+ {0x00, 0x00, 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // 0xF0 - '�'
+ {0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // 0xF1 - '�'
+ {0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x3C, 0x00}, // 0xF2 - '�'
+ {0x00, 0x00, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x3E}, // 0xF3 - '�'
+ {0x00, 0x00, 0x3E, 0x6B, 0x6B, 0x3E, 0x08, 0x1C}, // 0xF4 - '�'
+ {0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // 0xF5 - '�'
+ {0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x7F, 0x60}, // 0xF6 - '�'
+ {0x00, 0x00, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x00}, // 0xF7 - '�'
+ {0x00, 0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x00}, // 0xF8 - '�'
+ {0x00, 0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0xFF, 0xC0}, // 0xF9 - '�'
+ {0x00, 0x00, 0x0F, 0x0D, 0x3C, 0x6C, 0x3C, 0x00}, // 0xFA - '�'
+ {0x00, 0x00, 0x63, 0x63, 0x6F, 0x7B, 0x6F, 0x00}, // 0xFB - '�'
+ {0x00, 0x00, 0x0F, 0x06, 0x3E, 0x66, 0x3E, 0x00}, // 0xFC - '�'
+ {0x00, 0x00, 0x3E, 0x63, 0x78, 0x63, 0x3E, 0x00}, // 0xFD - '�'
+ {0x00, 0x00, 0x3B, 0x6B, 0x6F, 0x6B, 0x3B, 0x00}, // 0xFE - '�'
+ {0x00, 0x00, 0x7E, 0x63, 0x7E, 0x66, 0x63, 0x00} // 0xFF - '�'
+};
+
+const unsigned char font8x12[256][12] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 - ' '
+ {0x00, 0x7E, 0xC3, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0xC3, 0x7E, 0x00, 0x00}, // 0x01 - ''
+ {0x00, 0x7E, 0xFF, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x00, 0x00}, // 0x02 - ''
+ {0x00, 0x00, 0x22, 0x77, 0x7F, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x00, 0x00}, // 0x03 - ''
+ {0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x00, 0x00, 0x00}, // 0x04 - ''
+ {0x00, 0x18, 0x3C, 0x3C, 0xFF, 0xE7, 0xE7, 0x18, 0x18, 0x7E, 0x00, 0x00}, // 0x05 - ''
+ {0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x7E, 0x00, 0x00}, // 0x06 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00}, // 0x07 - ''
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x81, 0x81, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF}, // 0x08 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09 - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A - ' '
+ {0x00, 0x7C, 0x70, 0x5C, 0x4E, 0x1F, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x0B - ' '
+ {0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, // 0x0C - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D - ' '
+ {0x00, 0xFE, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xE6, 0xE7, 0x67, 0x03, 0x00}, // 0x0E - ''
+ {0x00, 0x00, 0x18, 0xDB, 0x7E, 0xE7, 0xE7, 0x7E, 0xDB, 0x18, 0x00, 0x00}, // 0x0F - ''
+ {0x00, 0x01, 0x03, 0x07, 0x1F, 0x7F, 0x1F, 0x07, 0x03, 0x01, 0x00, 0x00}, // 0x10 - ''
+ {0x00, 0x40, 0x60, 0x70, 0x7C, 0x7F, 0x7C, 0x70, 0x60, 0x40, 0x00, 0x00}, // 0x11 - ''
+ {0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00}, // 0x12 - ''
+ {0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00}, // 0x13 - ''
+ {0x00, 0xFE, 0xDB, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0xD8, 0x00, 0x00}, // 0x14 - ''
+ {0x00, 0x7E, 0xC6, 0x0C, 0x3C, 0x66, 0x66, 0x3C, 0x30, 0x63, 0x7E, 0x00}, // 0x15 - ''
+ {0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00}, // 0x16 - ''
+ {0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00}, // 0x17 - ''
+ {0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00}, // 0x18 - ''
+ {0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00}, // 0x19 - ''
+ {0x00, 0x00, 0x00, 0x18, 0x30, 0x7F, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00}, // 0x1A - ' '
+ {0x00, 0x00, 0x00, 0x0C, 0x06, 0x7F, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00}, // 0x1B - ''
+ {0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x7F, 0x00, 0x00, 0x00, 0x00}, // 0x1C - ''
+ {0x00, 0x00, 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00}, // 0x1D - ''
+ {0x00, 0x00, 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x7F, 0x00, 0x00}, // 0x1E - ''
+ {0x00, 0x00, 0x7F, 0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x00, 0x00}, // 0x1F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 - ' '
+ {0x00, 0x0C, 0x1E, 0x1E, 0x1E, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // 0x21 - '!'
+ {0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x22 - '"'
+ {0x00, 0x36, 0x36, 0x7F, 0x36, 0x36, 0x36, 0x7F, 0x36, 0x36, 0x00, 0x00}, // 0x23 - '#'
+ {0x0C, 0x0C, 0x3E, 0x03, 0x03, 0x1E, 0x30, 0x30, 0x1F, 0x0C, 0x0C, 0x00}, // 0x24 - '$'
+ {0x00, 0x00, 0x00, 0x23, 0x33, 0x18, 0x0C, 0x06, 0x33, 0x31, 0x00, 0x00}, // 0x25 - '%'
+ {0x00, 0x0E, 0x1B, 0x1B, 0x0E, 0x5F, 0x7B, 0x33, 0x3B, 0x6E, 0x00, 0x00}, // 0x26 - '&'
+ {0x00, 0x0C, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x27 - '''
+ {0x00, 0x30, 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x00}, // 0x28 - '('
+ {0x00, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00}, // 0x29 - ')'
+ {0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00}, // 0x2A - '*'
+ {0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, // 0x2B - '+'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x06, 0x00}, // 0x2C - ','
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x2D - '-'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00}, // 0x2E - '.'
+ {0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00}, // 0x2F - '/'
+ {0x00, 0x3E, 0x63, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x63, 0x3E, 0x00, 0x00}, // 0x30 - '0'
+ {0x00, 0x08, 0x0C, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00, 0x00}, // 0x31 - '1'
+ {0x00, 0x1E, 0x33, 0x33, 0x30, 0x18, 0x0C, 0x06, 0x33, 0x3F, 0x00, 0x00}, // 0x32 - '2'
+ {0x00, 0x1E, 0x33, 0x30, 0x30, 0x1C, 0x30, 0x30, 0x33, 0x1E, 0x00, 0x00}, // 0x33 - '3'
+ {0x00, 0x30, 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x30, 0x78, 0x00, 0x00}, // 0x34 - '4'
+ {0x00, 0x3F, 0x03, 0x03, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00, 0x00}, // 0x35 - '5'
+ {0x00, 0x1C, 0x06, 0x03, 0x03, 0x1F, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x36 - '6'
+ {0x00, 0x7F, 0x63, 0x63, 0x60, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00, 0x00}, // 0x37 - '7'
+ {0x00, 0x1E, 0x33, 0x33, 0x37, 0x1E, 0x3B, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x38 - '8'
+ {0x00, 0x1E, 0x33, 0x33, 0x33, 0x3E, 0x18, 0x18, 0x0C, 0x0E, 0x00, 0x00}, // 0x39 - '9'
+ {0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00}, // 0x3A - ':'
+ {0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x1C, 0x1C, 0x18, 0x0C, 0x00}, // 0x3B - ';'
+ {0x00, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x00}, // 0x3C - '<'
+ {0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x3D - '='
+ {0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00}, // 0x3E - '>'
+ {0x00, 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // 0x3F - '?'
+ {0x00, 0x3E, 0x63, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x03, 0x3E, 0x00, 0x00}, // 0x40 - '@'
+ {0x00, 0x0C, 0x1E, 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0x41 - 'A'
+ {0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x3F, 0x00, 0x00}, // 0x42 - 'B'
+ {0x00, 0x3C, 0x66, 0x63, 0x03, 0x03, 0x03, 0x63, 0x66, 0x3C, 0x00, 0x00}, // 0x43 - 'C'
+ {0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00, 0x00}, // 0x44 - 'D'
+ {0x00, 0x7F, 0x46, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x46, 0x7F, 0x00, 0x00}, // 0x45 - 'E'
+ {0x00, 0x7F, 0x66, 0x46, 0x26, 0x3E, 0x26, 0x06, 0x06, 0x0F, 0x00, 0x00}, // 0x46 - 'F'
+ {0x00, 0x3C, 0x66, 0x63, 0x03, 0x03, 0x73, 0x63, 0x66, 0x7C, 0x00, 0x00}, // 0x47 - 'G'
+ {0x00, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0x48 - 'H'
+ {0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00}, // 0x49 - 'I'
+ {0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x4A - 'J'
+ {0x00, 0x67, 0x66, 0x36, 0x36, 0x1E, 0x36, 0x36, 0x66, 0x67, 0x00, 0x00}, // 0x4B - 'K'
+ {0x00, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x66, 0x7F, 0x00, 0x00}, // 0x4C - 'L'
+ {0x00, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00}, // 0x4D - 'M'
+ {0x00, 0x63, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x00, 0x00}, // 0x4E - 'N'
+ {0x00, 0x1C, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00, 0x00}, // 0x4F - 'O'
+ {0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00}, // 0x50 - 'P'
+ {0x00, 0x1C, 0x36, 0x63, 0x63, 0x63, 0x73, 0x7B, 0x3E, 0x30, 0x78, 0x00}, // 0x51 - 'Q'
+ {0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00}, // 0x52 - 'R'
+ {0x00, 0x1E, 0x33, 0x33, 0x03, 0x0E, 0x18, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x53 - 'S'
+ {0x00, 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00}, // 0x54 - 'T'
+ {0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x55 - 'U'
+ {0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00, 0x00}, // 0x56 - 'V'
+ {0x00, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x36, 0x36, 0x36, 0x00, 0x00}, // 0x57 - 'W'
+ {0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x1E, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0x58 - 'X'
+ {0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00}, // 0x59 - 'Y'
+ {0x00, 0x7F, 0x73, 0x19, 0x18, 0x0C, 0x06, 0x46, 0x63, 0x7F, 0x00, 0x00}, // 0x5A - 'Z'
+ {0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00}, // 0x5B - '['
+ {0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, 0x00}, // 0x5C - '\'
+ {0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00}, // 0x5D - ']'
+ {0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x5E - '^'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00}, // 0x5F - '_'
+ {0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x60 - '`'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x6E, 0x00, 0x00}, // 0x61 - 'a'
+ {0x00, 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3B, 0x00, 0x00}, // 0x62 - 'b'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x03, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0x63 - 'c'
+ {0x00, 0x38, 0x30, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00, 0x00}, // 0x64 - 'd'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0x65 - 'e'
+ {0x00, 0x1C, 0x36, 0x06, 0x06, 0x1F, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00}, // 0x66 - 'f'
+ {0x00, 0x00, 0x00, 0x00, 0x6E, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x33, 0x1E}, // 0x67 - 'g'
+ {0x00, 0x07, 0x06, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00}, // 0x68 - 'h'
+ {0x00, 0x18, 0x18, 0x00, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00}, // 0x69 - 'i'
+ {0x00, 0x30, 0x30, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // 0x6A - 'j'
+ {0x00, 0x07, 0x06, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00, 0x00}, // 0x6B - 'k'
+ {0x00, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00}, // 0x6C - 'l'
+ {0x00, 0x00, 0x00, 0x00, 0x3F, 0x6B, 0x6B, 0x6B, 0x6B, 0x63, 0x00, 0x00}, // 0x6D - 'm'
+ {0x00, 0x00, 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0x6E - 'n'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0x6F - 'o'
+ {0x00, 0x00, 0x00, 0x00, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // 0x70 - 'p'
+ {0x00, 0x00, 0x00, 0x00, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x78}, // 0x71 - 'q'
+ {0x00, 0x00, 0x00, 0x00, 0x37, 0x76, 0x6E, 0x06, 0x06, 0x0F, 0x00, 0x00}, // 0x72 - 'r'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x06, 0x18, 0x33, 0x1E, 0x00, 0x00}, // 0x73 - 's'
+ {0x00, 0x00, 0x04, 0x06, 0x3F, 0x06, 0x06, 0x06, 0x36, 0x1C, 0x00, 0x00}, // 0x74 - 't'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00, 0x00}, // 0x75 - 'u'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00, 0x00}, // 0x76 - 'v'
+ {0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x6B, 0x6B, 0x36, 0x36, 0x00, 0x00}, // 0x77 - 'w'
+ {0x00, 0x00, 0x00, 0x00, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00, 0x00}, // 0x78 - 'x'
+ {0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x30, 0x18, 0x0F}, // 0x79 - 'y'
+ {0x00, 0x00, 0x00, 0x00, 0x3F, 0x31, 0x18, 0x06, 0x23, 0x3F, 0x00, 0x00}, // 0x7A - 'z'
+ {0x00, 0x38, 0x0C, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x0C, 0x38, 0x00, 0x00}, // 0x7B - '{'
+ {0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00}, // 0x7C - '|'
+ {0x00, 0x07, 0x0C, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x0C, 0x07, 0x00, 0x00}, // 0x7D - '}'
+ {0x00, 0xCE, 0x5B, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x7E - '~'
+ {0x00, 0x00, 0x00, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x00, 0x00, 0x00}, // 0x7F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x80 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x81 - '�'
+ {0x00, 0x0C, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x82 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x83 - '�'
+ {0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x84 - '�'
+ {0x00, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x00}, // 0x85 - '�'
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // 0x86 - '�'
+ {0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18}, // 0x87 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x88 - '�'
+ {0x00, 0x00, 0x00, 0x23, 0x33, 0x18, 0x0C, 0x06, 0x33, 0x31, 0x00, 0x00}, // 0x89 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8A - '�'
+ {0x00, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x00}, // 0x8B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x90 - '�'
+ {0x00, 0x0C, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x91 - '�'
+ {0x00, 0x0C, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x92 - '�'
+ {0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x93 - '�'
+ {0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x94 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00}, // 0x95 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x96 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x97 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x98 - '�'
+ {0x00, 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00}, // 0x99 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9A - '�'
+ {0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00}, // 0x9B - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9D - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9F - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0 - '�'
+ {0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, 0x00}, // 0xA1 - '�'
+ {0x00, 0x00, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x30, 0x18, 0x0F}, // 0xA2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA3 - '�'
+ {0x00, 0x00, 0x66, 0x3C, 0x24, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA5 - '�'
+ {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // 0xA6 - '�'
+ {0x00, 0x7E, 0xC6, 0x0C, 0x3C, 0x66, 0x66, 0x3C, 0x30, 0x63, 0x7E, 0x00}, // 0xA7 - '�'
+ {0x36, 0x7F, 0x46, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x46, 0x7F, 0x00, 0x00}, // 0xA8 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x03, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0xA9 - '�'
+ {0x00, 0x3C, 0x66, 0x63, 0x03, 0x0F, 0x03, 0x63, 0x66, 0x3C, 0x00, 0x00}, // 0xAA - '�'
+ {0x00, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x00}, // 0xAB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // 0xAC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xAD - '�'
+ {0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00}, // 0xAE - '�'
+ {0x33, 0x33, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00}, // 0xAF - '�'
+ {0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB0 - '�'
+ {0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, // 0xB1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x00, 0x00}, // 0xB5 - '�'
+ {0x00, 0xFE, 0xDB, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0xD8, 0x00, 0x00}, // 0xB6 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB7 - '�'
+ {0x00, 0x12, 0x12, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0xB8 - '�'
+ {0x00, 0x73, 0x73, 0x33, 0x37, 0x7F, 0x7B, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0xB9 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x0F, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0xBA - '�'
+ {0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00}, // 0xBB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBE - '�'
+ {0x00, 0x66, 0x66, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00}, // 0xBF - '�'
+ {0x00, 0x0C, 0x1E, 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0xC0 - '�'
+ {0x00, 0x7F, 0x46, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x00, 0x00}, // 0xC1 - '�'
+ {0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x3F, 0x00, 0x00}, // 0xC2 - '�'
+ {0x00, 0x7F, 0x46, 0x46, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00}, // 0xC3 - '�'
+ {0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x00}, // 0xC4 - '�'
+ {0x00, 0x7F, 0x46, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x46, 0x7F, 0x00, 0x00}, // 0xC5 - '�'
+ {0x00, 0x99, 0xDB, 0x5A, 0x7E, 0x3C, 0x7E, 0x5A, 0xDB, 0x99, 0x00, 0x00}, // 0xC6 - '�'
+ {0x00, 0x3C, 0x66, 0x62, 0x60, 0x38, 0x60, 0x62, 0x66, 0x3C, 0x00, 0x00}, // 0xC7 - '�'
+ {0x00, 0x63, 0x63, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0x63, 0x00, 0x00}, // 0xC8 - '�'
+ {0x18, 0x6B, 0x6F, 0x73, 0x7B, 0x7F, 0x6F, 0x67, 0x63, 0x63, 0x00, 0x00}, // 0xC9 - '�'
+ {0x00, 0x67, 0x66, 0x36, 0x36, 0x1E, 0x36, 0x36, 0x66, 0x67, 0x00, 0x00}, // 0xCA - '�'
+ {0x00, 0x78, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x63, 0x00, 0x00}, // 0xCB - '�'
+ {0x00, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00}, // 0xCC - '�'
+ {0x00, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00}, // 0xCD - '�'
+ {0x00, 0x1C, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00, 0x00}, // 0xCE - '�'
+ {0x00, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00}, // 0xCF - '�'
+ {0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00}, // 0xD0 - '�'
+ {0x00, 0x3C, 0x66, 0x63, 0x03, 0x03, 0x03, 0x63, 0x66, 0x3C, 0x00, 0x00}, // 0xD1 - '�'
+ {0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00}, // 0xD2 - '�'
+ {0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, 0x00}, // 0xD3 - '�'
+ {0x00, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x00, 0x00}, // 0xD4 - '�'
+ {0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x1E, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0xD5 - '�'
+ {0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x7F, 0x60, 0x00}, // 0xD6 - '�'
+ {0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x00, 0x00}, // 0xD7 - '�'
+ {0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x00, 0x00}, // 0xD8 - '�'
+ {0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xFF, 0xC0, 0x00}, // 0xD9 - '�'
+ {0x00, 0x07, 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, 0x00}, // 0xDA - '�'
+ {0x00, 0x63, 0x63, 0x63, 0x63, 0x6F, 0x7B, 0x7B, 0x7B, 0x6F, 0x00, 0x00}, // 0xDB - '�'
+ {0x00, 0x00, 0x03, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x3F, 0x00, 0x00}, // 0xDC - '�'
+ {0x00, 0x1E, 0x33, 0x63, 0x60, 0x78, 0x60, 0x63, 0x33, 0x1E, 0x00, 0x00}, // 0xDD - '�'
+ {0x00, 0x73, 0xDB, 0xDB, 0xDF, 0xDF, 0xDB, 0xDB, 0xDB, 0x73, 0x00, 0x00}, // 0xDE - '�'
+ {0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0xE7, 0x00, 0x00}, // 0xDF - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x6E, 0x00, 0x00}, // 0xE0 - '�'
+ {0x00, 0x00, 0x00, 0x20, 0x3E, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0xE1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1F, 0x33, 0x1F, 0x33, 0x33, 0x1F, 0x00, 0x00}, // 0xE2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}, // 0xE3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3E, 0x36, 0x36, 0x36, 0x36, 0x7F, 0x63, 0x00}, // 0xE4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0xE5 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x49, 0x6B, 0x3E, 0x3E, 0x6B, 0x49, 0x00, 0x00}, // 0xE6 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x31, 0x1C, 0x30, 0x31, 0x1E, 0x00, 0x00}, // 0xE7 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x3B, 0x3F, 0x37, 0x33, 0x00, 0x00}, // 0xE8 - '�'
+ {0x00, 0x10, 0x18, 0x08, 0x33, 0x33, 0x3B, 0x3F, 0x37, 0x33, 0x00, 0x00}, // 0xE9 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x1B, 0x0F, 0x1B, 0x13, 0x33, 0x00, 0x00}, // 0xEA - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x38, 0x3C, 0x34, 0x36, 0x32, 0x33, 0x00, 0x00}, // 0xEB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x63, 0x77, 0x6B, 0x6B, 0x63, 0x63, 0x00, 0x00}, // 0xEC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0xED - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00}, // 0xEE - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00}, // 0xEF - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x1F, 0x03, 0x03}, // 0xF0 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x03, 0x03, 0x33, 0x1E, 0x00, 0x00}, // 0xF1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00}, // 0xF2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x66, 0x3C}, // 0xF3 - '�'
+ {0x00, 0x00, 0x00, 0x08, 0x3E, 0x6B, 0x6B, 0x6B, 0x3E, 0x08, 0x08, 0x00}, // 0xF4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00, 0x00}, // 0xF5 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x7F, 0x60, 0x00}, // 0xF6 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x00, 0x00}, // 0xF7 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x7F, 0x00, 0x00}, // 0xF8 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0xFF, 0xC0, 0x00}, // 0xF9 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00}, // 0xFA - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x6F, 0x7B, 0x7B, 0x6F, 0x00, 0x00}, // 0xFB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x1F, 0x33, 0x33, 0x1F, 0x00, 0x00}, // 0xFC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x1E, 0x33, 0x3C, 0x30, 0x33, 0x1E, 0x00, 0x00}, // 0xFD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3B, 0x6F, 0x6F, 0x6F, 0x6F, 0x3B, 0x00, 0x00}, // 0xFE - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x3E, 0x33, 0x33, 0x3E, 0x36, 0x33, 0x00, 0x00} // 0xFF - '�'
+};
+
+const unsigned char font12x16[256][32] =
+{
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 - ' '
+ {0xE0, 0x00, 0x18, 0x03, 0x04, 0x04, 0x04, 0x04, 0xB2, 0x09, 0xB2, 0x09, 0x02, 0x08, 0x02, 0x08, 0x12, 0x09, 0xE2, 0x08, 0x04, 0x04, 0x04, 0x04, 0x18, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x01 - ''
+ {0xE0, 0x00, 0xF8, 0x03, 0xFC, 0x07, 0xFC, 0x07, 0x4E, 0x0E, 0x4E, 0x0E, 0xFE, 0x0F, 0xFE, 0x0F, 0xEE, 0x0E, 0x1E, 0x0F, 0xFC, 0x07, 0xFC, 0x07, 0xF8, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x02 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0xBC, 0x07, 0xFC, 0x07, 0xFC, 0x07, 0xFC, 0x07, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x03 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0xFC, 0x07, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x04 - ''
+ {0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF0, 0x01, 0xF0, 0x01, 0xEC, 0x06, 0xFE, 0x0F, 0xFE, 0x0F, 0xFE, 0x0F, 0x4C, 0x06, 0xE0, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x05 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0xFC, 0x07, 0xFC, 0x07, 0xFC, 0x07, 0x58, 0x03, 0xE0, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x06 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x07 - ''
+ {0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x9F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x9F, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F}, // 0x08 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09 - ' '
+ {0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x9F, 0x0F, 0x6F, 0x0F, 0xF7, 0x0E, 0xF7, 0x0E, 0xF7, 0x0E, 0xF7, 0x0E, 0x6F, 0x0F, 0x9F, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F}, // 0x0A - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x06, 0x78, 0x05, 0xCC, 0x04, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xCC, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0B - ' '
+ {0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x30, 0x03, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x30, 0x03, 0xE0, 0x01, 0xC0, 0x00, 0xC0, 0x00, 0xF0, 0x03, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0C - ' '
+ {0x40, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x01, 0x40, 0x00, 0x40, 0x00, 0x70, 0x00, 0x78, 0x00, 0x78, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D - ' '
+ {0x30, 0x00, 0x70, 0x00, 0xD0, 0x00, 0x90, 0x01, 0x30, 0x03, 0x70, 0x02, 0xD0, 0x02, 0x90, 0x03, 0x1C, 0x03, 0x1E, 0x02, 0x1E, 0x02, 0x8C, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00}, // 0x0E - ''
+ {0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0xE4, 0x04, 0xF8, 0x03, 0x18, 0x03, 0x0C, 0x06, 0x0E, 0x0E, 0x0C, 0x06, 0x18, 0x03, 0xF8, 0x03, 0xE4, 0x04, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xF8, 0x00, 0xF8, 0x01, 0xF8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x10 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0xC0, 0x01, 0xE0, 0x01, 0xF0, 0x01, 0xF8, 0x01, 0xF0, 0x01, 0xE0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x11 - ''
+ {0x00, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x12 - ''
+ {0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x13 - ''
+ {0x00, 0x00, 0xF8, 0x07, 0x6C, 0x03, 0x66, 0x03, 0x66, 0x03, 0x66, 0x03, 0x6C, 0x03, 0x78, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x14 - ''
+ {0x00, 0x00, 0xF8, 0x01, 0x0C, 0x03, 0x0C, 0x00, 0x0C, 0x00, 0xF8, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0xF8, 0x01, 0x00, 0x03, 0x00, 0x03, 0x0C, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x15 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0xF8, 0x07, 0xF8, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x16 - ''
+ {0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x40, 0x00, 0xF8, 0x03, 0x00, 0x00}, // 0x17 - ''
+ {0x00, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x18 - ''
+ {0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x19 - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x01, 0x80, 0x03, 0xFC, 0x07, 0x80, 0x03, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x1A - ' '
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x38, 0x00, 0xFC, 0x07, 0x38, 0x00, 0x30, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x1B - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x1C - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x18, 0x03, 0x1C, 0x07, 0xFE, 0x0F, 0x1C, 0x07, 0x18, 0x03, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x1D - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0xFC, 0x07, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x1E - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0F, 0xFC, 0x07, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x1F - ''
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 - ' '
+ {0x60, 0x00, 0x60, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x21 - '!'
+ {0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x22 - '"'
+ {0x00, 0x00, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0xFC, 0x0F, 0x30, 0x03, 0x30, 0x03, 0x98, 0x01, 0x98, 0x01, 0xFE, 0x03, 0xCC, 0x00, 0xCC, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x23 - '#'
+ {0x60, 0x00, 0x60, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x6C, 0x00, 0x6C, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0x60, 0x03, 0x60, 0x03, 0xFC, 0x03, 0xF8, 0x01, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x24 - '$'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x0C, 0x1C, 0x0E, 0x1C, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x07, 0x0E, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x25 - '%'
+ {0x00, 0x00, 0xE0, 0x00, 0xB0, 0x01, 0x98, 0x01, 0x98, 0x01, 0xD8, 0x00, 0x70, 0x00, 0x78, 0x00, 0x7C, 0x00, 0xCC, 0x06, 0xCC, 0x03, 0x8C, 0x01, 0xDC, 0x03, 0x78, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x26 - '&'
+ {0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x27 - '''
+ {0xC0, 0x01, 0x60, 0x00, 0x70, 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x30, 0x00, 0x70, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x28 - '('
+ {0x38, 0x00, 0x60, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x29 - ')'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x03, 0x6C, 0x03, 0xF8, 0x01, 0xF0, 0x00, 0xFC, 0x03, 0xF0, 0x00, 0xF8, 0x01, 0x6C, 0x03, 0x6C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x2A - '*'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFC, 0x03, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x2B - '+'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x30, 0x00}, // 0x2C - ','
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x2D - '-'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x2E - '.'
+ {0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x2F - '/'
+ {0xF0, 0x01, 0xFC, 0x07, 0x0C, 0x06, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x0C, 0x06, 0xFC, 0x07, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x30 - '0'
+ {0xC0, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xF8, 0x07, 0xF8, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x31 - '1'
+ {0xF8, 0x03, 0xFC, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x06, 0x0E, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00}, // 0x32 - '2'
+ {0xF8, 0x03, 0xFC, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x00, 0x0C, 0x00, 0x0E, 0xF0, 0x07, 0xF0, 0x03, 0x00, 0x06, 0x00, 0x0C, 0x06, 0x0C, 0x0E, 0x0E, 0xFC, 0x07, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x33 - '3'
+ {0x80, 0x03, 0xC0, 0x03, 0xE0, 0x03, 0x70, 0x03, 0x38, 0x03, 0x1C, 0x03, 0x0E, 0x03, 0x06, 0x03, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x34 - '4'
+ {0xFE, 0x0F, 0xFE, 0x0F, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x03, 0xFC, 0x07, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x0C, 0x06, 0x0C, 0x0E, 0x0E, 0xFC, 0x07, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x35 - '5'
+ {0xC0, 0x03, 0xE0, 0x03, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0xFE, 0x03, 0xFE, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x06, 0x0C, 0x0E, 0x0E, 0xFC, 0x07, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x36 - '6'
+ {0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0x80, 0x01, 0xC0, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x37 - '7'
+ {0xF0, 0x01, 0xF8, 0x03, 0x1C, 0x07, 0x0C, 0x06, 0x0C, 0x06, 0x1C, 0x07, 0xF8, 0x03, 0xFC, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x06, 0x0C, 0x0E, 0x0E, 0xFC, 0x07, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x38 - '8'
+ {0xF8, 0x03, 0xFC, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x06, 0x0C, 0x0E, 0x0E, 0xFC, 0x0F, 0xF8, 0x0F, 0x00, 0x06, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xF8, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x39 - '9'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x3A - ':'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00}, // 0x3B - ';'
+ {0x00, 0x03, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x3C - '<'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x3D - '='
+ {0x0C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x3E - '>'
+ {0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x3F - '?'
+ {0xF8, 0x03, 0xFC, 0x07, 0x0C, 0x06, 0xE6, 0x0D, 0xF6, 0x0D, 0xB6, 0x0D, 0xB6, 0x0D, 0xB6, 0x0D, 0xB6, 0x0D, 0xF6, 0x07, 0xE6, 0x03, 0x0E, 0x00, 0xFC, 0x03, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x40 - '@'
+ {0x60, 0x00, 0x60, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x0C, 0x03, 0xFC, 0x03, 0xFC, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x41 - 'A'
+ {0xFE, 0x00, 0xFE, 0x01, 0x86, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x03, 0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x42 - 'B'
+ {0xF0, 0x01, 0xF8, 0x03, 0x1C, 0x07, 0x0C, 0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0C, 0x06, 0x1C, 0x07, 0xF8, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x43 - 'C'
+ {0xFE, 0x00, 0xFE, 0x01, 0x86, 0x03, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x86, 0x03, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x44 - 'D'
+ {0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x45 - 'E'
+ {0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x46 - 'F'
+ {0xF0, 0x03, 0xF8, 0x07, 0x1C, 0x06, 0x0C, 0x00, 0x06, 0x00, 0x06, 0x00, 0xC6, 0x07, 0xC6, 0x07, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x06, 0x1C, 0x06, 0xF8, 0x07, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x47 - 'G'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x48 - 'H'
+ {0xF8, 0x01, 0xF8, 0x01, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x49 - 'I'
+ {0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x03, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x4A - 'J'
+ {0x06, 0x06, 0x06, 0x07, 0x86, 0x03, 0xC6, 0x01, 0xE6, 0x00, 0x76, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x76, 0x00, 0xE6, 0x00, 0xC6, 0x01, 0x86, 0x03, 0x06, 0x07, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x4B - 'K'
+ {0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x4C - 'L'
+ {0x06, 0x06, 0x0E, 0x07, 0x0E, 0x07, 0x9E, 0x07, 0x9E, 0x07, 0xF6, 0x06, 0xF6, 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x4D - 'M'
+ {0x06, 0x06, 0x0E, 0x06, 0x0E, 0x06, 0x1E, 0x06, 0x36, 0x06, 0x36, 0x06, 0x66, 0x06, 0x66, 0x06, 0xC6, 0x06, 0xC6, 0x06, 0x86, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x4E - 'N'
+ {0xF0, 0x00, 0xF8, 0x01, 0x9C, 0x03, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x9C, 0x03, 0xF8, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x4F - 'O'
+ {0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x50 - 'P'
+ {0xF0, 0x00, 0xF8, 0x01, 0x9C, 0x03, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xC6, 0x06, 0xCC, 0x03, 0x9C, 0x03, 0xF8, 0x07, 0xF0, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x51 - 'Q'
+ {0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0xE6, 0x00, 0xC6, 0x01, 0x86, 0x03, 0x06, 0x07, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x52 - 'R'
+ {0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x00, 0x0E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0x00, 0x07, 0x00, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x53 - 'S'
+ {0xFC, 0x03, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x54 - 'T'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x55 - 'U'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x56 - 'V'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x06, 0x66, 0x06, 0xF6, 0x06, 0x9E, 0x07, 0x0E, 0x07, 0x0E, 0x07, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x57 - 'W'
+ {0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x58 - 'X'
+ {0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x59 - 'Y'
+ {0xFE, 0x07, 0xFE, 0x07, 0x00, 0x03, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x5A - 'Z'
+ {0xF8, 0x01, 0xF8, 0x01, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x5B - '['
+ {0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x5C - '\'
+ {0xF8, 0x01, 0xF8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x5D - ']'
+ {0x40, 0x00, 0xE0, 0x00, 0xF0, 0x01, 0xB8, 0x03, 0x1C, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x5E - '^'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0F, 0xFE, 0x0F}, // 0x5F - '_'
+ {0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x60 - '`'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xFC, 0x07, 0x00, 0x06, 0xF8, 0x07, 0xFC, 0x07, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x61 - 'a'
+ {0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xF6, 0x01, 0xFE, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x62 - 'b'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0E, 0x06, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x63 - 'c'
+ {0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0xF8, 0x06, 0xFC, 0x07, 0x8E, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x06, 0xFC, 0x07, 0xF8, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0x64 - 'd'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x06, 0xFE, 0x07, 0xFE, 0x03, 0x06, 0x00, 0x0E, 0x00, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x65 - 'e'
+ {0xE0, 0x01, 0xF0, 0x01, 0x38, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x66 - 'f'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0xFC, 0x07, 0x0E, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x07, 0xF8, 0x06, 0x00, 0x06, 0x00, 0x07, 0xFC, 0x03, 0xFC, 0x01}, // 0x67 - 'g'
+ {0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xF6, 0x00, 0xFE, 0x01, 0x8E, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x68 - 'h'
+ {0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x69 - 'i'
+ {0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x98, 0x01, 0xF8, 0x01, 0xF0, 0x00}, // 0x6A - 'j'
+ {0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x8C, 0x01, 0xCC, 0x01, 0xEC, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0xEC, 0x00, 0xCC, 0x01, 0x8C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x6B - 'k'
+ {0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x6C - 'l'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x01, 0xFE, 0x03, 0xFE, 0x07, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x6D - 'm'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x01, 0xFC, 0x03, 0x0C, 0x07, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x6E - 'n'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x6F - 'o'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFE, 0x03, 0xF6, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00}, // 0x70 - 'p'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0xFC, 0x07, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x07, 0xF8, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06}, // 0x71 - 'q'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x03, 0xFC, 0x07, 0x1C, 0x06, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x72 - 'r'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0xFE, 0x01, 0x06, 0x00, 0xFE, 0x00, 0xFC, 0x01, 0x80, 0x01, 0x80, 0x01, 0xFE, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x73 - 's'
+ {0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xF8, 0x01, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x74 - 't'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x07, 0xF8, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0x75 - 'u'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x76 - 'v'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xF6, 0x06, 0xFC, 0x03, 0x9C, 0x03, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0x77 - 'w'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x8E, 0x03, 0xDC, 0x01, 0xF8, 0x00, 0x70, 0x00, 0xF8, 0x00, 0xDC, 0x01, 0x8E, 0x03, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x78 - 'x'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00}, // 0x79 - 'y'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x03, 0xFE, 0x01, 0xC0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x00, 0xFE, 0x03, 0xFE, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0x7A - 'z'
+ {0xC0, 0x03, 0xE0, 0x03, 0x70, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x70, 0x00, 0xE0, 0x03, 0xC0, 0x03, 0x00, 0x00}, // 0x7B - '{'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x7C - '|'
+ {0x3C, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0x80, 0x03, 0xC0, 0x01, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x7C, 0x00, 0x3C, 0x00, 0x00, 0x00}, // 0x7D - '}'
+ {0x00, 0x00, 0x00, 0x00, 0x38, 0x06, 0x6C, 0x03, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x7E - '~'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x7F - ''
+ {0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04, 0x11, 0x01, 0x44, 0x04}, // 0x80 - '�'
+ {0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05}, // 0x81 - '�'
+ {0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B, 0xEE, 0x0E, 0xBB, 0x0B}, // 0x82 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x83 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x84 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x85 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x86 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x87 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x88 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x60, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x89 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x8A - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x8B - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8C - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8D - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x8E - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x8F - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x90 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x91 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x92 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x93 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x94 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x95 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0x96 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xEC, 0x0F, 0xEC, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x97 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xEC, 0x0F, 0xEC, 0x0F, 0x0C, 0x00, 0xFC, 0x0F, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x98 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0xFC, 0x0F, 0x0C, 0x00, 0xEC, 0x0F, 0xEC, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x99 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xEF, 0x0F, 0xEF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9A - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0xEF, 0x0F, 0xEF, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x9B - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xEC, 0x0F, 0xEC, 0x0F, 0x0C, 0x00, 0xEC, 0x0F, 0xEC, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x9C - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9D - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xEF, 0x0F, 0xEF, 0x0F, 0x00, 0x00, 0xEF, 0x0F, 0xEF, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0x9E - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x9F - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0xA1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0xA2 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xFC, 0x0F, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA3 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0xA5 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0xFC, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0xA6 - '�'
+ {0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0xEF, 0x0F, 0xEF, 0x0F, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6C, 0x00}, // 0xA7 - '�'
+ {0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0xA8 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0xA9 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xAA - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00}, // 0xAB - '�'
+ {0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F}, // 0xAC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F}, // 0xAD - '�'
+ {0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00}, // 0xAE - '�'
+ {0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F}, // 0xAF - '�'
+ {0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB0 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0xA4, 0x04, 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x10, 0x01, 0xA0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x20, 0x04, 0x1C, 0x08, 0xFE, 0x0F, 0xFE, 0x0F, 0xFE, 0x0F, 0xFE, 0x0F, 0xFC, 0x07, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x20, 0x04, 0x1C, 0x08, 0xFE, 0x0F, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x04, 0x04, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB4 - '�'
+ {0x00, 0x00, 0xC0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0x90, 0x00, 0x90, 0x00, 0xE0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB5 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x60, 0x00, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00}, // 0xB6 - '�'
+ {0xF0, 0x00, 0xF8, 0x01, 0x98, 0x01, 0x98, 0x01, 0xF8, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB7 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xB8 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xB9 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBA - '�'
+ {0x00, 0x00, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC4, 0x00, 0xCC, 0x00, 0xD8, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBB - '�'
+ {0xC3, 0x00, 0xC7, 0x06, 0xC7, 0x0F, 0xC7, 0x09, 0xCF, 0x0F, 0xCB, 0x06, 0xCB, 0x00, 0xDB, 0x00, 0xD3, 0x0F, 0xF3, 0x0F, 0xE3, 0x00, 0xE3, 0x00, 0xE3, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBC - '�'
+ {0x00, 0x00, 0x06, 0x06, 0xF6, 0x06, 0xFC, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x03, 0xF6, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBE - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xBF - '�'
+ {0xF0, 0x07, 0xF8, 0x07, 0x1C, 0x06, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xC0 - '�'
+ {0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xC1 - '�'
+ {0xFE, 0x00, 0xFE, 0x01, 0x86, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x03, 0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xC2 - '�'
+ {0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xC3 - '�'
+ {0xF0, 0x07, 0xF8, 0x07, 0x1C, 0x06, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFF, 0x0F, 0xFF, 0x0F, 0x03, 0x0C, 0x03, 0x0C}, // 0xC4 - '�'
+ {0xFE, 0x07, 0xFE, 0x07, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0xC5 - '�'
+ {0x61, 0x08, 0x63, 0x0C, 0x63, 0x0C, 0x67, 0x06, 0x66, 0x06, 0x6E, 0x03, 0xFC, 0x03, 0xFC, 0x03, 0x6E, 0x07, 0x66, 0x06, 0x67, 0x0E, 0x63, 0x0C, 0x63, 0x0C, 0x61, 0x08, 0x00, 0x00, 0x00, 0x00}, // 0xC6 - '�'
+ {0xF8, 0x03, 0xFC, 0x07, 0x0E, 0x0E, 0x06, 0x0C, 0x00, 0x0C, 0x00, 0x0E, 0xF0, 0x07, 0xF0, 0x03, 0x00, 0x06, 0x00, 0x0C, 0x06, 0x0C, 0x0E, 0x0E, 0xFC, 0x07, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0xC7 - '�'
+ {0x06, 0x06, 0x06, 0x07, 0x06, 0x07, 0x86, 0x07, 0xC6, 0x06, 0xC6, 0x06, 0x66, 0x06, 0x66, 0x06, 0x36, 0x06, 0x36, 0x06, 0x1E, 0x06, 0x0E, 0x06, 0x0E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xC8 - '�'
+ {0x46, 0x06, 0x66, 0x07, 0x26, 0x07, 0x86, 0x07, 0xC6, 0x06, 0xC6, 0x06, 0x66, 0x06, 0x66, 0x06, 0x36, 0x06, 0x36, 0x06, 0x1E, 0x06, 0x0E, 0x06, 0x0E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xC9 - '�'
+ {0x06, 0x06, 0x06, 0x07, 0x86, 0x03, 0xC6, 0x01, 0xE6, 0x00, 0x76, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x76, 0x00, 0xE6, 0x00, 0xC6, 0x01, 0x86, 0x03, 0x06, 0x07, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xCA - '�'
+ {0xF0, 0x07, 0xF8, 0x07, 0x1C, 0x06, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xCB - '�'
+ {0x06, 0x06, 0x0E, 0x07, 0x0E, 0x07, 0x9E, 0x07, 0x9E, 0x07, 0xF6, 0x06, 0xF6, 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xCC - '�'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xCD - '�'
+ {0xF0, 0x00, 0xF8, 0x01, 0x9C, 0x03, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x9C, 0x03, 0xF8, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xCE - '�'
+ {0xFE, 0x07, 0xFE, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xCF - '�'
+ {0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xD0 - '�'
+ {0xF0, 0x01, 0xF8, 0x03, 0x1C, 0x07, 0x0C, 0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0C, 0x06, 0x1C, 0x07, 0xF8, 0x03, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xD1 - '�'
+ {0xFC, 0x03, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xD2 - '�'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFC, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0x03, 0xFE, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xD3 - '�'
+ {0x60, 0x00, 0x60, 0x00, 0xFC, 0x03, 0xFE, 0x07, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFE, 0x07, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xD4 - '�'
+ {0x06, 0x06, 0x06, 0x06, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xD5 - '�'
+ {0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x06, 0x00, 0x06}, // 0xD6 - '�'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFC, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xD7 - '�'
+ {0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0xD8 - '�'
+ {0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x0C, 0x00, 0x0C}, // 0xD9 - '�'
+ {0x1F, 0x00, 0x1F, 0x00, 0x1B, 0x00, 0x1B, 0x00, 0x18, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0x18, 0x07, 0x18, 0x06, 0x18, 0x06, 0x18, 0x06, 0x18, 0x07, 0xF8, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xDA - '�'
+ {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x06, 0x7E, 0x06, 0xE6, 0x06, 0xC6, 0x06, 0xC6, 0x06, 0xC6, 0x06, 0xE6, 0x06, 0x7E, 0x06, 0x3E, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xDB - '�'
+ {0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xDC - '�'
+ {0xF8, 0x00, 0xFC, 0x01, 0x8E, 0x03, 0x06, 0x03, 0x00, 0x06, 0x00, 0x06, 0xF0, 0x07, 0xF0, 0x07, 0x00, 0x06, 0x00, 0x06, 0x06, 0x03, 0x8E, 0x03, 0xFC, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xDD - '�'
+ {0xC3, 0x01, 0xE3, 0x03, 0x73, 0x07, 0x33, 0x06, 0x1B, 0x0C, 0x1B, 0x0C, 0x1F, 0x0C, 0x1F, 0x0C, 0x1B, 0x0C, 0x1B, 0x0C, 0x33, 0x06, 0x73, 0x07, 0xE3, 0x03, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xDE - '�'
+ {0xF8, 0x07, 0xFC, 0x07, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x06, 0xFC, 0x07, 0xF8, 0x07, 0x70, 0x06, 0x38, 0x06, 0x1C, 0x06, 0x0E, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xDF - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xFC, 0x07, 0x00, 0x06, 0xF8, 0x07, 0xFC, 0x07, 0x06, 0x06, 0x06, 0x06, 0xFE, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0xE0 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFC, 0x03, 0xFE, 0x01, 0x06, 0x00, 0xF6, 0x01, 0xFE, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xFE, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xE1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x01, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0xFC, 0x01, 0x0C, 0x03, 0x0C, 0x03, 0xFC, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xE2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0xFC, 0x03, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xE3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0xF8, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0xFE, 0x07, 0xFE, 0x07, 0x06, 0x06, 0x06, 0x06}, // 0xE4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x06, 0xFE, 0x07, 0xFE, 0x03, 0x06, 0x00, 0x0E, 0x00, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xE5 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x0C, 0x67, 0x0E, 0x6E, 0x07, 0xFC, 0x03, 0xFC, 0x03, 0x6C, 0x03, 0x66, 0x06, 0x67, 0x0E, 0x63, 0x0C, 0x00, 0x00, 0x00, 0x00}, // 0xE6 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF8, 0x01, 0x0C, 0x03, 0x00, 0x03, 0xE0, 0x01, 0x00, 0x03, 0x0C, 0x03, 0xF8, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xE7 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x07, 0x8C, 0x07, 0xCC, 0x06, 0x6C, 0x06, 0x3C, 0x06, 0x1C, 0x06, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xE8 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x40, 0x00, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x07, 0x8C, 0x07, 0xCC, 0x06, 0x6C, 0x06, 0x3C, 0x06, 0x1C, 0x06, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xE9 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x01, 0xCC, 0x01, 0xEC, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0xEC, 0x00, 0xCC, 0x01, 0x8C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0xEA - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x03, 0xF8, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0xEB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x07, 0x9E, 0x07, 0x9E, 0x07, 0xF6, 0x06, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xEC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0xFC, 0x07, 0xFC, 0x07, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xED - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xEE - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x07, 0xFC, 0x07, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xEF - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x0E, 0x07, 0xFE, 0x03, 0xF6, 0x01, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00}, // 0xF0 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0xFC, 0x03, 0x0E, 0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0E, 0x06, 0xFC, 0x03, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xF1 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xF2 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0C, 0x03, 0x98, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00}, // 0xF3 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xFC, 0x03, 0xFE, 0x07, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFE, 0x07, 0xFC, 0x03, 0x60, 0x00, 0x60, 0x00}, // 0xF4 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x8E, 0x03, 0xDC, 0x01, 0xF8, 0x00, 0x70, 0x00, 0xF8, 0x00, 0xDC, 0x01, 0x8E, 0x03, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0xF5 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0xFC, 0x07, 0xFC, 0x07, 0x00, 0x06, 0x00, 0x06}, // 0xF6 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0xFC, 0x03, 0xF8, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0xF7 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFE, 0x07, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00}, // 0xF8 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0xFE, 0x0F, 0xFE, 0x0F, 0x00, 0x0C, 0x00, 0x0C}, // 0xF9 - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x36, 0x00, 0xF0, 0x03, 0xF0, 0x07, 0x30, 0x06, 0x30, 0x06, 0xF0, 0x07, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00}, // 0xFA - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x06, 0xFE, 0x06, 0xC6, 0x06, 0xC6, 0x06, 0xFE, 0x06, 0x7E, 0x06, 0x00, 0x00, 0x00, 0x00}, // 0xFB - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xFC, 0x01, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0xFC, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xFC - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xFC, 0x01, 0x06, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0x00, 0x03, 0x86, 0x03, 0xFC, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xFD - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x01, 0xE6, 0x03, 0x76, 0x07, 0x3E, 0x06, 0x3E, 0x06, 0x36, 0x06, 0x76, 0x07, 0xE6, 0x03, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x00}, // 0xFE - '�'
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0xF8, 0x03, 0x70, 0x03, 0x38, 0x03, 0x1C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00} // 0xFF - '�'
+};
diff --git a/Display/Fonts.h b/Display/Fonts.h
new file mode 100644
index 0000000..5dc96ca
--- /dev/null
+++ b/Display/Fonts.h
@@ -0,0 +1,47 @@
+//******************************************************************************
+// @file Fonts.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Fonts data, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef Fonts_h
+#define Fonts_h
+
+extern const unsigned char font4x6[256][6];
+extern const unsigned char font6x8[256][8];
+extern const unsigned char font8x8[256][8];
+extern const unsigned char font8x12[256][16];
+extern const unsigned char font12x16[256][24];
+
+#endif
diff --git a/Display/ILI9341.cpp b/Display/ILI9341.cpp
new file mode 100644
index 0000000..f680a33
--- /dev/null
+++ b/Display/ILI9341.cpp
@@ -0,0 +1,566 @@
+//******************************************************************************
+// @file ILI9341.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: ILI9341 Low Level Driver Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "ILI9341.h"
+
+// *****************************************************************************
+// *** Defines *************************************************************
+// *****************************************************************************
+
+// Commands definitions
+
+#define CMD_NOP 0x00 // No Operation
+#define CMD_SWRESET 0x01 // Software Reset
+#define CMD_RDDID 0x04 // Read Display Identification Information
+#define CMD_RDDST 0x09 // Read Display Status
+
+#define CMD_RDMODE 0x0A // Read Display Power Mode
+#define CMD_RDMADCTL 0x0B // Read Display MADCTL
+#define CMD_RDPIXFMT 0x0C // Read Display Pixel Format
+#define CMD_RDIMGFMT 0x0D // Read Display Image Format
+#define CMD_RDSIGMOD 0x0E // Read Display Signal Mode
+#define CMD_RDSELFDIAG 0x0F // Read Display Self-Diagnostic Result
+
+#define CMD_SLPIN 0x10 // Enter Sleep Mode
+#define CMD_SLPOUT 0x11 // Sleep OUT
+#define CMD_PTLON 0x12 // Partial Mode ON
+#define CMD_NORON 0x13 // Normal Display Mode ON
+
+#define CMD_INVOFF 0x20 // Display Inversion OFF
+#define CMD_INVON 0x21 // Display Inversion ON
+#define CMD_GAMMASET 0x26 // Gamma Set
+#define CMD_DISPOFF 0x28 // Display OFF
+#define CMD_DISPON 0x29 // Display ON
+
+#define CMD_CASET 0x2A // Column Address Set
+#define CMD_PASET 0x2B // Page Address Set
+#define CMD_RAMWR 0x2C // Memory Write
+#define CMD_GSET 0x2D // Color SET
+#define CMD_RAMRD 0x2E // Memory Read
+
+#define CMD_PTLAR 0x30 // Partial Area
+#define CMD_VSCRDEF 0x33 // Vertical Scrolling Definition
+#define CMD_TELOFF 0x34 // Tearing Effect Line OFF
+#define CMD_TELON 0x35 // Tearing Effect Line ON
+#define CMD_MADCTL 0x36 // Memory Access Control
+#define CMD_VSAADDR 0x37 // Vertical Scrolling Start Address
+#define CMD_IDLMOFF 0x38 // Idle Mode OFF
+#define CMD_IDLMON 0x39 // Idle Mode ON
+#define CMD_PIXFMT 0x3A // Pixel Format Set
+
+#define CMD_RGBISC 0xB0 // RGB Interface Signal Control
+#define CMD_FRMCTR1 0xB1 // Frame Control (In Normal Mode)
+#define CMD_FRMCTR2 0xB2 // Frame Control (In Idle Mode)
+#define CMD_FRMCTR3 0xB3 // Frame Control (In Partial Mode)
+#define CMD_INVCTR 0xB4 // Display Inversion Control
+#define CMD_BLKPC 0xB5 // Blanking Porch Control
+#define CMD_DFUNCTR 0xB6 // Display Function Control
+
+#define CMD_PWCTR1 0xC0 // Power Control 1
+#define CMD_PWCTR2 0xC1 // Power Control 2
+#define CMD_VMCTR1 0xC5 // VCOM Control 1
+#define CMD_VMCTR2 0xC7 // VCOM Control 2
+#define CMD_PWCTRA 0xCB // Power control A
+#define CMD_PWCTRB 0xCF // Power control B
+
+#define CMD_NVMEMWR 0xD0 // NV Memory Write
+#define CMD_NVMEMPK 0xD1 // NV Memory Protection Key
+#define CMD_NVMEMSR 0xD2 // NV Memory Status Read
+#define CMD_READID4 0xD3 // Read ID4
+
+#define CMD_RDID1 0xDA // Read ID1
+#define CMD_RDID2 0xDB // Read ID2
+#define CMD_RDID3 0xDC // Read ID3
+
+#define CMD_GMCTRP1 0xE0 // Positive Gamma Correction
+#define CMD_GMCTRN1 0xE1 // Negative Gamma Correction
+#define CMD_DGCTRL1 0xE2 // Digital Gamma Control 1
+#define CMD_DGCTRL2 0xE3 // Digital Gamma Control 2
+#define CMD_DRVTMCA 0xE8 // Driver timing control A
+#define CMD_DRVTMCB 0xEA // Driver timing control B
+#define CMD_PWONSC 0xED // Power on sequence control
+
+#define CMD_EN3G 0xF2 // Enable 3 gamma control
+#define CMD_INTCTRL 0xF6 // Interface Control
+#define CMD_PUMPRC 0xF7 // Pump ratio control
+
+// Memory Access Control register bits definitions
+
+#define MADCTL_MY 0x80 // Row Address Order
+#define MADCTL_MX 0x40 // Column Address Order
+#define MADCTL_MV 0x20 // Row / Column Exchange
+#define MADCTL_ML 0x10 // Vertical Refresh Order
+#define MADCTL_BGR 0x08 // BGR Order
+#define MADCTL_RGB 0x00 // RGB Order (No BGR bit)
+#define MADCTL_MH 0x04 // Horizontal Refresh ORDER
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+ILI9341::ILI9341(SPI_HandleTypeDef* in_hspi) : hspi(in_hspi) {};
+
+// *****************************************************************************
+// *** Write byte to SPI ***************************************************
+// *****************************************************************************
+inline void ILI9341::SpiWrite(uint8_t c)
+{
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // Pull down CS
+ HAL_SPI_Transmit(hspi, &c, sizeof(c), 1U);
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); // Pull up CS
+}
+
+// *****************************************************************************
+// *** Write byte stream to SPI ********************************************
+// *****************************************************************************
+void ILI9341::SpiWriteStream(uint8_t* data, uint32_t n)
+{
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // Pull down CS
+ HAL_SPI_Transmit_DMA(hspi, data, n);
+}
+
+// *****************************************************************************
+// *** Write command to SPI ************************************************
+// *****************************************************************************
+inline void ILI9341::WriteCommand(uint8_t c)
+{
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // Command
+ SpiWrite(c);
+}
+
+// *****************************************************************************
+// *** Write data to SPI ***************************************************
+// *****************************************************************************
+inline void ILI9341::WriteData(uint8_t c)
+{
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ SpiWrite(c);
+}
+
+// *****************************************************************************
+// *** Write data steram to SPI ********************************************
+// *****************************************************************************
+void ILI9341::WriteDataStream(uint8_t* data, uint32_t n)
+{
+ // Data
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET);
+ // Pull down CS
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
+ // Send data to screen
+ HAL_SPI_Transmit_DMA(hspi, data, n);
+}
+
+// *****************************************************************************
+// *** Check SPI transfer status *******************************************
+// *****************************************************************************
+bool ILI9341::IsTransferComplete(void)
+{
+ return (hspi->State != HAL_SPI_STATE_BUSY_TX);
+// return (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == SET);
+}
+
+// *****************************************************************************
+// *** Pull up CS line for LCD **********************************************
+// *****************************************************************************
+void ILI9341::StopTransfer(void)
+{
+ // Pull up CS
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
+}
+
+// *****************************************************************************
+// *** Init screen *********************************************************
+// *****************************************************************************
+void ILI9341::Init(void)
+{
+// // Reset sequence. Used only if GPIO pin used as LCD reset.
+// HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
+// HAL_Delay(5);
+// HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
+// HAL_Delay(20);
+// HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
+// HAL_Delay(150);
+
+ // Exit Sleep
+ WriteCommand(CMD_SWRESET);
+ // Delay for execute previous command
+ HAL_Delay(100U);
+
+ // Power control
+ WriteCommand(CMD_PWCTR1);
+ WriteData(0x23); // VRH[5:0] // 25
+
+ // Power control
+ WriteCommand(CMD_PWCTR2);
+ WriteData(0x10); // SAP[2:0]; BT[3:0] // 11
+
+ // VCM control 1
+ WriteCommand(CMD_VMCTR1);
+ WriteData(0x2B);
+ WriteData(0x2B);
+
+ // VCM control 2
+ WriteCommand(CMD_VMCTR2);
+ WriteData(0xC0);
+
+ // Pixel Format Set
+ WriteCommand(CMD_PIXFMT);
+ WriteData(0x55);
+
+ // Frame Control (In Normal Mode)
+ WriteCommand(CMD_FRMCTR1);
+ WriteData(0x00);
+ WriteData(0x18);
+
+ // Power control A
+ WriteCommand(CMD_PWCTRA);
+ WriteData(0x39);
+ WriteData(0x2C);
+ WriteData(0x00);
+ WriteData(0x34);
+ WriteData(0x02);
+
+ // Power control B
+ WriteCommand(CMD_PWCTRB);
+ WriteData(0x00);
+ WriteData(0XC1);
+ WriteData(0X30);
+
+ // Power on sequence control
+ WriteCommand(CMD_PWONSC);
+ WriteData(0x64);
+ WriteData(0x03);
+ WriteData(0X12);
+ WriteData(0X81);
+
+ // Driver timing control A
+ WriteCommand(CMD_DRVTMCA);
+ WriteData(0x85);
+ WriteData(0x00);
+ WriteData(0x78);
+
+ // Driver timing control B
+ WriteCommand(CMD_DRVTMCB);
+ WriteData(0x00);
+ WriteData(0x00);
+
+ // Pump ratio control
+ WriteCommand(CMD_PUMPRC);
+ WriteData(0x20);
+
+ // Memory Access Control
+ WriteCommand(CMD_MADCTL);
+ WriteData(0x48);
+
+ // Display Function Control
+ WriteCommand(CMD_DFUNCTR);
+ WriteData(0x08);
+ WriteData(0x82);
+ WriteData(0x27);
+
+ // Enable 3 gamma control - Disable 3 Gamma Function
+ WriteCommand(CMD_EN3G);
+ WriteData(0x00);
+
+ // Gamma Set - Gamma curve selected
+ WriteCommand(CMD_GAMMASET);
+ WriteData(0x01);
+
+ // Positive Gamma Correction
+ WriteCommand(CMD_GMCTRP1);
+ WriteData(0x0F);
+ WriteData(0x31);
+ WriteData(0x2B);
+ WriteData(0x0C);
+ WriteData(0x0E);
+ WriteData(0x08);
+ WriteData(0x4E);
+ WriteData(0xF1);
+ WriteData(0x37);
+ WriteData(0x07);
+ WriteData(0x10);
+ WriteData(0x03);
+ WriteData(0x0E);
+ WriteData(0x09);
+ WriteData(0x00);
+
+ // Negative Gamma Correction
+ WriteCommand(CMD_GMCTRN1);
+ WriteData(0x00);
+ WriteData(0x0E);
+ WriteData(0x14);
+ WriteData(0x03);
+ WriteData(0x11);
+ WriteData(0x07);
+ WriteData(0x31);
+ WriteData(0xC1);
+ WriteData(0x48);
+ WriteData(0x08);
+ WriteData(0x0F);
+ WriteData(0x0C);
+ WriteData(0x31);
+ WriteData(0x36);
+ WriteData(0x0F);
+
+ // Interface Control
+ WriteCommand(CMD_INTCTRL);
+ WriteData(0x01);
+ WriteData(0x00);
+ WriteData(0x01 << 5);
+
+ // Exit Sleep
+ WriteCommand(CMD_SLPOUT);
+ // Delay for execute previous command
+ HAL_Delay(120U);
+ // Display on
+ WriteCommand(CMD_DISPON);
+}
+
+// *****************************************************************************
+// *** Set output window ***************************************************
+// *****************************************************************************
+void ILI9341::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
+{
+ WriteCommand(CMD_CASET); // Column address set
+ WriteData(x0 >> 8);
+ WriteData(x0 & 0xFF); // XSTART
+ WriteData(x1 >> 8);
+ WriteData(x1 & 0xFF); // XEND
+
+ WriteCommand(CMD_PASET); // Row address set
+ WriteData(y0 >> 8);
+ WriteData(y0); // YSTART
+ WriteData(y1 >> 8);
+ WriteData(y1); // YEND
+
+ WriteCommand(CMD_RAMWR); // write to RAM
+
+ // Prepare for write data
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+}
+
+// *****************************************************************************
+// *** Pass 8-bit (each) R,G,B, get back 16-bit packed color ***************
+// *****************************************************************************
+uint16_t ILI9341::GetColor565(uint8_t r, uint8_t g, uint8_t b)
+{
+ return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
+}
+
+// *****************************************************************************
+// *** Set screen orientation **********************************************
+// *****************************************************************************
+void ILI9341::SetRotation(uint8_t m)
+{
+ WriteCommand(CMD_MADCTL);
+ rotation = m % 4; // can't be higher than 3
+ switch (rotation)
+ {
+ case 0:
+ WriteData(MADCTL_BGR);
+ width = TFT_HEIGHT;
+ height = TFT_WIDTH;
+ break;
+
+ case 1:
+ WriteData(MADCTL_MV | MADCTL_BGR);
+ width = TFT_WIDTH;
+ height = TFT_HEIGHT;
+ break;
+
+ case 2: // Y: up -> down
+ WriteData(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
+ width = TFT_HEIGHT;
+ height = TFT_WIDTH;
+ break;
+
+ case 3: // X: left -> right
+ WriteData(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
+ width = TFT_WIDTH;
+ height = TFT_HEIGHT;
+ break;
+
+ default:
+ break;
+ }
+}
+
+// *****************************************************************************
+// *** Write color to screen ***********************************************
+// *****************************************************************************
+void ILI9341::PushColor(uint16_t color)
+{
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+
+ SpiWrite(color >> 8);
+ SpiWrite(color);
+}
+
+// *****************************************************************************
+// *** Draw one pixel on screen *******************************************
+// *****************************************************************************
+void ILI9341::DrawPixel(int16_t x, int16_t y, uint16_t color)
+{
+ if((x < 0) ||(x >= width) || (y < 0) || (y >= height)) return;
+
+ SetAddrWindow(x,y,x+1,y+1);
+
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+
+ SpiWrite(color >> 8);
+ SpiWrite(color);
+}
+
+// *****************************************************************************
+// *** Draw vertical line **************************************************
+// *****************************************************************************
+void ILI9341::DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
+{
+ // Rudimentary clipping
+ if((x >= width) || (y >= height)) return;
+
+ if((y+h-1) >= height) h = height-y;
+
+ SetAddrWindow(x, y, x, y+h-1);
+
+ uint8_t hi = color >> 8, lo = color;
+
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+
+ while (h--)
+ {
+ SpiWrite(hi);
+ SpiWrite(lo);
+ }
+}
+
+// *****************************************************************************
+// *** Draw horizontal line ************************************************
+// *****************************************************************************
+void ILI9341::DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
+{
+ if((x >= width) || (y >= height)) return;
+ if((x+w-1) >= width) w = width-x;
+
+ SetAddrWindow(x, y, x+w-1, y);
+
+ uint8_t hi = color >> 8, lo = color;
+
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+
+ while (w--)
+ {
+ SpiWrite(hi);
+ SpiWrite(lo);
+ }
+}
+
+// *****************************************************************************
+// *** Fill full screen ****************************************************
+// *****************************************************************************
+void ILI9341::FillScreen(uint16_t color)
+{
+ FillRect(0, 0, width, height, color);
+}
+
+// *****************************************************************************
+// *** Fill rectangle on screen ********************************************
+// *****************************************************************************
+void ILI9341::FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
+{
+ if((x >= width) || (y >= height)) return;
+ if((x + w - 1) >= width) w = width - x;
+ if((y + h - 1) >= height) h = height - y;
+
+ SetAddrWindow(x, y, x+w-1, y+h-1);
+
+ uint8_t hi = color >> 8, lo = color;
+
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // Pull down CS
+ for(y=h; y>0; y--)
+ {
+ for(x=w; x>0; x--)
+ {
+ // Wait until TXE flag is set to send data
+ while(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == RESET);
+ hspi->Instance->DR = hi;
+ while(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == RESET);
+ hspi->Instance->DR = lo;
+ }
+ }
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); // Pull up CS
+}
+
+// *****************************************************************************
+// *** Invert display ******************************************************
+// *****************************************************************************
+void ILI9341::InvertDisplay(bool invert)
+{
+ WriteCommand(invert ? CMD_INVON : CMD_INVOFF);
+}
+
+// *****************************************************************************
+// *** Read data from SPI **************************************************
+// *****************************************************************************
+inline uint8_t ILI9341::SpiRead(void)
+{
+ // Result variable
+ uint8_t r = 0;
+ // Pull down CS
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
+ // Receive data
+ HAL_SPI_Receive(hspi, &r, sizeof(r), 100U);
+ // Pull up CS
+ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
+ // Return result
+ return r;
+}
+
+// *****************************************************************************
+// *** Read data from display **********************************************
+// *****************************************************************************
+inline uint8_t ILI9341::ReadData(void)
+{
+ // Data
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ // Receive data
+ uint8_t r = SpiRead();
+ // Return result
+ return r;
+}
+
+// *****************************************************************************
+// *** Send read command ad read result ************************************
+// *****************************************************************************
+uint8_t ILI9341::ReadCommand(uint8_t c)
+{
+ // Set command mode
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // Command
+ SpiWrite(c);
+
+ // Set data mode
+ HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ // Receive data
+ uint8_t r = SpiRead();
+
+ // Return result
+ return r;
+}
diff --git a/Display/ILI9341.h b/Display/ILI9341.h
new file mode 100644
index 0000000..15712c1
--- /dev/null
+++ b/Display/ILI9341.h
@@ -0,0 +1,258 @@
+//******************************************************************************
+// @file ILI9341.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: ILI9341 Low Level Driver Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef ILI9341_h
+#define ILI9341_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include <DevCfg.h>
+
+// *****************************************************************************
+// *** Enums ***************************************************************
+// *****************************************************************************
+
+// Color definitions
+enum Color
+{
+ COLOR_BLACK = 0x0000, // 0, 0, 0
+ COLOR_VERYDARKGREY = 0xEF7B, // 32, 32, 32
+ COLOR_DARKGREY = 0xEF7B, // 64, 64, 64
+ COLOR_GREY = 0xEF7B, // 128, 128, 128
+ COLOR_LIGHTGREY = 0x18C6, // 192, 192, 192
+ COLOR_WHITE = 0xFFFF, // 255, 255, 255
+
+ COLOR_VERYDARKRED = 0x0018, // 32, 0, 0
+ COLOR_DARKRED = 0x0038, // 64, 0, 0
+ COLOR_MEDIUMRED = 0x0078, // 128, 0, 0
+ COLOR_LIGHTRED = 0x00B8, // 192, 0, 0
+ COLOR_RED = 0x00F8, // 255, 0, 0
+
+ COLOR_VERYDARKGREEN = 0xE000, // 0, 32, 0
+ COLOR_DARKGREEN = 0xE001, // 0, 64, 0
+ COLOR_MEDIUMGREEN = 0xE003, // 0, 128, 0
+ COLOR_LIGHTGREEN = 0xE005, // 0, 192, 0
+ COLOR_GREEN = 0xE007, // 0, 255, 0
+
+ COLOR_VERYDARKBLUE = 0x0300, // 0, 0, 32
+ COLOR_DARKBLUE = 0x0700, // 0, 0, 64
+ COLOR_MEDIUMBLUE = 0x0F00, // 0, 0, 128
+ COLOR_LIGHTBLUE = 0x1700, // 0, 0, 192
+ COLOR_BLUE = 0x1F00, // 0, 0, 255
+
+ COLOR_VERYDARKYELLOW = 0xE018, // 32, 32, 0
+ COLOR_DARKYELLOW = 0xE039, // 64, 64, 0
+ COLOR_MEDIUMYELLOW = 0xE07B, // 128, 128, 0
+ COLOR_LIGHTYELLOW = 0xE0BD, // 192, 192, 0
+ COLOR_YELLOW = 0xE0FF, // 255, 255, 0
+
+ COLOR_VERYDARKCYAN = 0xE300, // 0, 32, 32
+ COLOR_DARKCYAN = 0xE701, // 0, 64, 64
+ COLOR_MEDIUMCYAN = 0xEF03, // 0, 128, 128
+ COLOR_LIGHTCYAN = 0xF705, // 0, 192, 192
+ COLOR_CYAN = 0xFF07, // 0, 255, 255
+
+ COLOR_VERYDARKMAGENTA = 0x0318, // 32, 0, 32
+ COLOR_DARKMAGENTA = 0x0738, // 64, 0, 64
+ COLOR_MEDIUMMAGENTA = 0x0F78, // 128, 0, 128
+ COLOR_LIGHTMAGENTA = 0x17B8, // 192, 0, 192
+ COLOR_MAGENTA = 0x1FF8, // 255, 0, 255
+};
+
+class ILI9341
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ ILI9341(SPI_HandleTypeDef* in_hspi);
+
+ // *************************************************************************
+ // *** Write byte to SPI ***********************************************
+ // *************************************************************************
+ inline void SpiWrite(uint8_t c);
+
+ // *************************************************************************
+ // *** Write byte stream to SPI ****************************************
+ // *************************************************************************
+ void SpiWriteStream(uint8_t* data, uint32_t n);
+
+ // *************************************************************************
+ // *** Write command to SPI ********************************************
+ // *************************************************************************
+ inline void WriteCommand(uint8_t c);
+
+ // *************************************************************************
+ // *** Write data to SPI ***********************************************
+ // *************************************************************************
+ inline void WriteData(uint8_t c);
+
+ // *************************************************************************
+ // *** Write data steram to SPI ****************************************
+ // *************************************************************************
+ void WriteDataStream(uint8_t* data, uint32_t n);
+
+ // *************************************************************************
+ // *** Check SPI transfer status ****************************************
+ // *************************************************************************
+ bool IsTransferComplete(void);
+
+ // *************************************************************************
+ // *** Pull up CS line for LCD ******************************************
+ // *************************************************************************
+ void StopTransfer(void);
+
+ // *************************************************************************
+ // *** Init screen *****************************************************
+ // *************************************************************************
+ void Init(void);
+
+ // *************************************************************************
+ // *** Set output window ***********************************************
+ // *************************************************************************
+ void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
+
+ // *************************************************************************
+ // *** Pass 8-bit (each) R,G,B, get back 16-bit packed color ***********
+ // *************************************************************************
+ uint16_t GetColor565(uint8_t r, uint8_t g, uint8_t b);
+
+ // *************************************************************************
+ // *** Set screen orientation ******************************************
+ // *************************************************************************
+ void SetRotation(uint8_t r);
+
+ // *************************************************************************
+ // *** Write color to screen *******************************************
+ // *************************************************************************
+ void PushColor(uint16_t color);
+
+ // *************************************************************************
+ // *** Draw one pixel on screen ***************************************
+ // *************************************************************************
+ void DrawPixel(int16_t x, int16_t y, uint16_t color);
+
+ // *************************************************************************
+ // *** Draw vertical line **********************************************
+ // *************************************************************************
+ void DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
+
+ // *************************************************************************
+ // *** Draw horizontal line ********************************************
+ // *************************************************************************
+ void DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
+
+ // *************************************************************************
+ // *** Fill full screen ************************************************
+ // *************************************************************************
+ void FillScreen(uint16_t color);
+
+ // *************************************************************************
+ // *** Fill rectangle on screen ****************************************
+ // *************************************************************************
+ void FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
+
+ // *************************************************************************
+ // *** Invert display **************************************************
+ // *************************************************************************
+ void InvertDisplay(bool invert);
+
+ // *************************************************************************
+ // *** Read data from SPI **********************************************
+ // *************************************************************************
+ inline uint8_t SpiRead(void);
+
+ // *************************************************************************
+ // *** Read data from display ******************************************
+ // *************************************************************************
+ inline uint8_t ReadData(void);
+
+ // *************************************************************************
+ // *** Send read command ad read result ********************************
+ // *************************************************************************
+ uint8_t ReadCommand(uint8_t c);
+
+ // *************************************************************************
+ // *** Return screen width *********************************************
+ // *************************************************************************
+ inline int32_t GetWidth(void) {return width;}
+
+ // *************************************************************************
+ // *** Return screen height ********************************************
+ // *************************************************************************
+ inline int32_t GetHeight(void) {return height;}
+
+ // *************************************************************************
+ // *** Return byte(s) per pixel ****************************************
+ // *************************************************************************
+ inline int32_t GetBytesPerPixel(void) {return byte_per_pixel;}
+
+ // *************************************************************************
+ // *** Return max line *************************************************
+ // *************************************************************************
+ static constexpr int32_t GetMaxLine(void) {return TFT_WIDTH > TFT_HEIGHT ? TFT_WIDTH : TFT_HEIGHT;}
+
+ // *************************************************************************
+ // *** Return max line *************************************************
+ // *************************************************************************
+ static constexpr int32_t GetMaxBpp(void) {return TFT_BPP;}
+
+ private:
+
+ // Display width
+ static const int32_t TFT_WIDTH = 320;
+ // Display height
+ static const int32_t TFT_HEIGHT = 240;
+ // Display byte per pixel
+ static const int32_t TFT_BPP = 2;
+
+ // Handle to screen SPI
+ SPI_HandleTypeDef* hspi = nullptr;
+
+ // Width
+ int32_t width = TFT_WIDTH;
+ // Height
+ int32_t height = TFT_HEIGHT;
+ // Byte(s) per pixel
+ int32_t byte_per_pixel = TFT_BPP;
+
+ // Rotation
+ uint32_t rotation = 0U;
+};
+
+#endif
diff --git a/Display/Image.cpp b/Display/Image.cpp
new file mode 100644
index 0000000..cc17e54
--- /dev/null
+++ b/Display/Image.cpp
@@ -0,0 +1,366 @@
+//******************************************************************************
+// @file Image.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Image Visual Object Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "Image.h"
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Image ***************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+Image::Image(int32_t x, int32_t y, const ImageDesc& img_dsc) : img_description(img_dsc)
+{
+ x_start = x;
+ y_start = y;
+ width = img_dsc.width;
+ height = img_dsc.height;
+ x_end = x + width - 1;
+ y_end = y + height - 1;
+ bits_per_pixel = img_dsc.bits_per_pixel;
+ img = img_dsc.img;
+ palette = img_dsc.palette;
+ transparent_color = img_dsc.transparent_color;
+ hor_mirror = false;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Image::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ // Find idx in the image buffer
+ uint32_t idx = (line - y_start) * width;
+ // Find start x position
+ int32_t start = x_start - start_x;
+ // Prevent write in memory before buffer
+ if(start < 0)
+ {
+ // Minus minus - plus
+ idx -= start;
+ start = 0;
+ }
+ // Find start x position
+ int32_t end = x_end - start_x;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Delta for cycle increment/decrement
+ int32_t delta = 1;
+ // Flip horizontally if needed
+ if(hor_mirror)
+ {
+ idx += end - start;
+ // Set delta to minus one for decrement cycle
+ delta = -1;
+ }
+ // Draw image
+ if(bits_per_pixel == 16)
+ {
+ // Get pointer to 16-bit image data
+ uint16_t* p_img = (uint16_t*)img;
+ // Pixels data copy cycle
+ for(int32_t i = start; i <= end; i++)
+ {
+ // Get pixel data
+ uint16_t data = p_img[idx];
+ // Change index
+ idx += delta;
+ // If not transparent - output to buffer
+ if(data != transparent_color) buf[i] = data;
+ }
+ }
+ else
+ {
+ // Get pointer to 8-bit image data
+ uint8_t* p_img = (uint8_t*)img;
+ // Pixels data copy cycle
+ for(int32_t i = start; i <= end; i++)
+ {
+ // Get pixel data
+ uint16_t data = palette[p_img[idx]];
+ // Change index
+ idx += delta;
+ // If not transparent - output to buffer
+ if(data != transparent_color) buf[i] = data;
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Image::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // Draw only if needed
+ if((row >= x_start) && (row <= x_end))
+ {
+ // Find start x position
+ int32_t start = y_start - start_y;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = y_end - start_y;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(end > 0)
+ {
+ // Not implemented yet
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Set Image function **************************************************
+// *****************************************************************************
+void Image::SetImage(const ImageDesc& img_dsc, bool semaphore_taken)
+{
+ if(semaphore_taken == false) LockVisObject();
+ width = img_dsc.width;
+ height = img_dsc.height;
+ x_end = x_start + width - 1;
+ y_end = y_start + height - 1;
+ bits_per_pixel = img_dsc.bits_per_pixel;
+ img = img_dsc.img;
+ palette = img_dsc.palette;
+ transparent_color = img_dsc.transparent_color;
+ if(semaphore_taken == false) UnlockVisObject();
+}
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Image8 **************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+Image8::Image8(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t* p_img, const uint16_t* p_palette)
+{
+ x_start = x;
+ y_start = y;
+ x_end = x + w - 1;
+ y_end = y + h - 1;
+ width = w;
+ height = h;
+ img = p_img;
+ palette = p_palette;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Image8::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ // Find start x position
+ int32_t start = x_start - start_x;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = x_end - start_x;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(x_end > 0)
+ {
+ int idx = (line - y_start) * width;
+ for(int32_t i = start; i <= end; i++)
+ {
+ buf[i] = palette[img[idx++]];
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Image8::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // Draw only if needed
+ if((row >= x_start) && (row <= x_end))
+ {
+ // Find start x position
+ int32_t start = y_start - start_y;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = y_end - start_y;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(end > 0)
+ {
+ // Not implemented yet
+ }
+ }
+}
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Image16 *************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+Image16::Image16(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t* p_img)
+{
+ x_start = x;
+ y_start = y;
+ x_end = x + w - 1;
+ y_end = y + h - 1;
+ width = w;
+ height = h;
+ img = p_img;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Image16::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ // Find start x position
+ int32_t start = x_start - start_x;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = x_end - start_x;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(x_end > 0)
+ {
+ int idx = (line - y_start) * width;
+ for(int32_t i = start; i <= end; i++)
+ {
+ buf[i] = img[idx++];
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Image16::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // Draw only if needed
+ if((row >= x_start) && (row <= x_end))
+ {
+ // Find start x position
+ int32_t start = y_start - start_y;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = y_end - start_y;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(end > 0)
+ {
+ // Not implemented yet
+ }
+ }
+}
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Palettes ************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Palette with 8R-8G-4B levels (bits 3-3-2) ***************************
+// *****************************************************************************
+const uint16_t PALETTE_884[256] = {
+0x0000, 0x0020, 0x0040, 0x0068, 0x0088, 0x00B0, 0x00D0, 0x00F8, 0x0001, 0x0021, 0x0041, 0x0069, 0x0089, 0x00B1, 0x00D1, 0x00F9,
+0x2002, 0x2022, 0x2042, 0x206A, 0x208A, 0x20B2, 0x20D2, 0x20FA, 0x4003, 0x4023, 0x4043, 0x406B, 0x408B, 0x40B3, 0x40D3, 0x40FB,
+0x6004, 0x6024, 0x6044, 0x606C, 0x608C, 0x60B4, 0x60D4, 0x60FC, 0x8005, 0x8025, 0x8045, 0x806D, 0x808D, 0x80B5, 0x80D5, 0x80FD,
+0xA006, 0xA026, 0xA046, 0xA06E, 0xA08E, 0xA0B6, 0xA0D6, 0xA0FE, 0xE007, 0xE027, 0xE047, 0xE06F, 0xE08F, 0xE0B7, 0xE0D7, 0xE0FF,
+0x0A00, 0x0A20, 0x0A40, 0x0A68, 0x0A88, 0x0AB0, 0x0AD0, 0x0AF8, 0x0A01, 0x0A21, 0x0A41, 0x0A69, 0x0A89, 0x0AB1, 0x0AD1, 0x0AF9,
+0x2A02, 0x2A22, 0x2A42, 0x2A6A, 0x2A8A, 0x2AB2, 0x2AD2, 0x2AFA, 0x4A03, 0x4A23, 0x4A43, 0x4A6B, 0x4A8B, 0x4AB3, 0x4AD3, 0x4AFB,
+0x6A04, 0x6A24, 0x6A44, 0x6A6C, 0x6A8C, 0x6AB4, 0x6AD4, 0x6AFC, 0x8A05, 0x8A25, 0x8A45, 0x8A6D, 0x8A8D, 0x8AB5, 0x8AD5, 0x8AFD,
+0xAA06, 0xAA26, 0xAA46, 0xAA6E, 0xAA8E, 0xAAB6, 0xAAD6, 0xAAFE, 0xEA07, 0xEA27, 0xEA47, 0xEA6F, 0xEA8F, 0xEAB7, 0xEAD7, 0xEAFF,
+0x1400, 0x1420, 0x1440, 0x1468, 0x1488, 0x14B0, 0x14D0, 0x14F8, 0x1401, 0x1421, 0x1441, 0x1469, 0x1489, 0x14B1, 0x14D1, 0x14F9,
+0x3402, 0x3422, 0x3442, 0x346A, 0x348A, 0x34B2, 0x34D2, 0x34FA, 0x5403, 0x5423, 0x5443, 0x546B, 0x548B, 0x54B3, 0x54D3, 0x54FB,
+0x7404, 0x7424, 0x7444, 0x746C, 0x748C, 0x74B4, 0x74D4, 0x74FC, 0x9405, 0x9425, 0x9445, 0x946D, 0x948D, 0x94B5, 0x94D5, 0x94FD,
+0xB406, 0xB426, 0xB446, 0xB46E, 0xB48E, 0xB4B6, 0xB4D6, 0xB4FE, 0xF407, 0xF427, 0xF447, 0xF46F, 0xF48F, 0xF4B7, 0xF4D7, 0xF4FF,
+0x1F00, 0x1F20, 0x1F40, 0x1F68, 0x1F88, 0x1FB0, 0x1FD0, 0x1FF8, 0x1F01, 0x1F21, 0x1F41, 0x1F69, 0x1F89, 0x1FB1, 0x1FD1, 0x1FF9,
+0x3F02, 0x3F22, 0x3F42, 0x3F6A, 0x3F8A, 0x3FB2, 0x3FD2, 0x3FFA, 0x5F03, 0x5F23, 0x5F43, 0x5F6B, 0x5F8B, 0x5FB3, 0x5FD3, 0x5FFB,
+0x7F04, 0x7F24, 0x7F44, 0x7F6C, 0x7F8C, 0x7FB4, 0x7FD4, 0x7FFC, 0x9F05, 0x9F25, 0x9F45, 0x9F6D, 0x9F8D, 0x9FB5, 0x9FD5, 0x9FFD,
+0xBF06, 0xBF26, 0xBF46, 0xBF6E, 0xBF8E, 0xBFB6, 0xBFD6, 0xBFFE, 0xFF07, 0xFF27, 0xFF47, 0xFF6F, 0xFF8F, 0xFFB7, 0xFFD7, 0xFFFF};
+
+// *****************************************************************************
+// *** Palette with 7R-7G-5B levels (245 colors) ***************************
+// *****************************************************************************
+const uint16_t PALETTE_775[256] = {
+0x0000, 0x0028, 0x0050, 0x0078, 0x00A0, 0x00C8, 0x00F8, 0x4001, 0x4029, 0x4051, 0x4079, 0x40A1, 0x40C9, 0x40F9, 0xA002, 0xA02A,
+0xA052, 0xA07A, 0xA0A2, 0xA0CA, 0xA0FA, 0xE003, 0xE02B, 0xE053, 0xE07B, 0xE0A3, 0xE0CB, 0xE0FB, 0x4005, 0x402D, 0x4055, 0x407D,
+0x40A5, 0x40CD, 0x40FD, 0x8006, 0x802E, 0x8056, 0x807E, 0x80A6, 0x80CE, 0x80FE, 0xE007, 0xE02F, 0xE057, 0xE07F, 0xE0A7, 0xE0CF,
+0xE0FF, 0x0700, 0x0728, 0x0750, 0x0778, 0x07A0, 0x07C8, 0x07F8, 0x4701, 0x4729, 0x4751, 0x4779, 0x47A1, 0x47C9, 0x47F9, 0xA702,
+0xA72A, 0xA752, 0xA77A, 0xA7A2, 0xA7CA, 0xA7FA, 0xE703, 0xE72B, 0xE753, 0xE77B, 0xE7A3, 0xE7CB, 0xE7FB, 0x4705, 0x472D, 0x4755,
+0x477D, 0x47A5, 0x47CD, 0x47FD, 0x8706, 0x872E, 0x8756, 0x877E, 0x87A6, 0x87CE, 0x87FE, 0xE707, 0xE72F, 0xE757, 0xE77F, 0xE7A7,
+0xE7CF, 0xE7FF, 0x0F00, 0x0F28, 0x0F50, 0x0F78, 0x0FA0, 0x0FC8, 0x0FF8, 0x4F01, 0x4F29, 0x4F51, 0x4F79, 0x4FA1, 0x4FC9, 0x4FF9,
+0xAF02, 0xAF2A, 0xAF52, 0xAF7A, 0xAFA2, 0xAFCA, 0xAFFA, 0xEF03, 0xEF2B, 0xEF53, 0xEF7B, 0xEFA3, 0xEFCB, 0xEFFB, 0x4F05, 0x4F2D,
+0x4F55, 0x4F7D, 0x4FA5, 0x4FCD, 0x4FFD, 0x8F06, 0x8F2E, 0x8F56, 0x8F7E, 0x8FA6, 0x8FCE, 0x8FFE, 0xEF07, 0xEF2F, 0xEF57, 0xEF7F,
+0xEFA7, 0xEFCF, 0xEFFF, 0x1700, 0x1728, 0x1750, 0x1778, 0x17A0, 0x17C8, 0x17F8, 0x5701, 0x5729, 0x5751, 0x5779, 0x57A1, 0x57C9,
+0x57F9, 0xB702, 0xB72A, 0xB752, 0xB77A, 0xB7A2, 0xB7CA, 0xB7FA, 0xF703, 0xF72B, 0xF753, 0xF77B, 0xF7A3, 0xF7CB, 0xF7FB, 0x5705,
+0x572D, 0x5755, 0x577D, 0x57A5, 0x57CD, 0x57FD, 0x9706, 0x972E, 0x9756, 0x977E, 0x97A6, 0x97CE, 0x97FE, 0xF707, 0xF72F, 0xF757,
+0xF77F, 0xF7A7, 0xF7CF, 0xF7FF, 0x1F00, 0x1F28, 0x1F50, 0x1F78, 0x1FA0, 0x1FC8, 0x1FF8, 0x5F01, 0x5F29, 0x5F51, 0x5F79, 0x5FA1,
+0x5FC9, 0x5FF9, 0xBF02, 0xBF2A, 0xBF52, 0xBF7A, 0xBFA2, 0xBFCA, 0xBFFA, 0xFF03, 0xFF2B, 0xFF53, 0xFF7B, 0xFFA3, 0xFFCB, 0xFFFB,
+0x5F05, 0x5F2D, 0x5F55, 0x5F7D, 0x5FA5, 0x5FCD, 0x5FFD, 0x9F06, 0x9F2E, 0x9F56, 0x9F7E, 0x9FA6, 0x9FCE, 0x9FFE, 0xFF07, 0xFF2F,
+0xFF57, 0xFF7F, 0xFFA7, 0xFFCF, 0xFFFF, 0x0000, 0x0028, 0x0050, 0x0078, 0x00A0, 0x00C8, 0x00F8, 0x4001, 0x4029, 0x4051, 0x4079};
+
+// *****************************************************************************
+// *** Palette with 6R-7G-6B levels (252 colors) ***************************
+// *****************************************************************************
+const uint16_t PALETTE_676[256] = {
+0x0000, 0x0030, 0x0060, 0x0090, 0x00C0, 0x00F8, 0x4001, 0x4031, 0x4061, 0x4091, 0x40C1, 0x40F9, 0xA002, 0xA032, 0xA062, 0xA092,
+0xA0C2, 0xA0FA, 0xE003, 0xE033, 0xE063, 0xE093, 0xE0C3, 0xE0FB, 0x4005, 0x4035, 0x4065, 0x4095, 0x40C5, 0x40FD, 0x8006, 0x8036,
+0x8066, 0x8096, 0x80C6, 0x80FE, 0xE007, 0xE037, 0xE067, 0xE097, 0xE0C7, 0xE0FF, 0x0600, 0x0630, 0x0660, 0x0690, 0x06C0, 0x06F8,
+0x4601, 0x4631, 0x4661, 0x4691, 0x46C1, 0x46F9, 0xA602, 0xA632, 0xA662, 0xA692, 0xA6C2, 0xA6FA, 0xE603, 0xE633, 0xE663, 0xE693,
+0xE6C3, 0xE6FB, 0x4605, 0x4635, 0x4665, 0x4695, 0x46C5, 0x46FD, 0x8606, 0x8636, 0x8666, 0x8696, 0x86C6, 0x86FE, 0xE607, 0xE637,
+0xE667, 0xE697, 0xE6C7, 0xE6FF, 0x0C00, 0x0C30, 0x0C60, 0x0C90, 0x0CC0, 0x0CF8, 0x4C01, 0x4C31, 0x4C61, 0x4C91, 0x4CC1, 0x4CF9,
+0xAC02, 0xAC32, 0xAC62, 0xAC92, 0xACC2, 0xACFA, 0xEC03, 0xEC33, 0xEC63, 0xEC93, 0xECC3, 0xECFB, 0x4C05, 0x4C35, 0x4C65, 0x4C95,
+0x4CC5, 0x4CFD, 0x8C06, 0x8C36, 0x8C66, 0x8C96, 0x8CC6, 0x8CFE, 0xEC07, 0xEC37, 0xEC67, 0xEC97, 0xECC7, 0xECFF, 0x1200, 0x1230,
+0x1260, 0x1290, 0x12C0, 0x12F8, 0x5201, 0x5231, 0x5261, 0x5291, 0x52C1, 0x52F9, 0xB202, 0xB232, 0xB262, 0xB292, 0xB2C2, 0xB2FA,
+0xF203, 0xF233, 0xF263, 0xF293, 0xF2C3, 0xF2FB, 0x5205, 0x5235, 0x5265, 0x5295, 0x52C5, 0x52FD, 0x9206, 0x9236, 0x9266, 0x9296,
+0x92C6, 0x92FE, 0xF207, 0xF237, 0xF267, 0xF297, 0xF2C7, 0xF2FF, 0x1800, 0x1830, 0x1860, 0x1890, 0x18C0, 0x18F8, 0x5801, 0x5831,
+0x5861, 0x5891, 0x58C1, 0x58F9, 0xB802, 0xB832, 0xB862, 0xB892, 0xB8C2, 0xB8FA, 0xF803, 0xF833, 0xF863, 0xF893, 0xF8C3, 0xF8FB,
+0x5805, 0x5835, 0x5865, 0x5895, 0x58C5, 0x58FD, 0x9806, 0x9836, 0x9866, 0x9896, 0x98C6, 0x98FE, 0xF807, 0xF837, 0xF867, 0xF897,
+0xF8C7, 0xF8FF, 0x1F00, 0x1F30, 0x1F60, 0x1F90, 0x1FC0, 0x1FF8, 0x5F01, 0x5F31, 0x5F61, 0x5F91, 0x5FC1, 0x5FF9, 0xBF02, 0xBF32,
+0xBF62, 0xBF92, 0xBFC2, 0xBFFA, 0xFF03, 0xFF33, 0xFF63, 0xFF93, 0xFFC3, 0xFFFB, 0x5F05, 0x5F35, 0x5F65, 0x5F95, 0x5FC5, 0x5FFD,
+0x9F06, 0x9F36, 0x9F66, 0x9F96, 0x9FC6, 0x9FFE, 0xFF07, 0xFF37, 0xFF67, 0xFF97, 0xFFC7, 0xFFFF, 0x0000, 0x0030, 0x0060, 0x0090};
diff --git a/Display/Image.h b/Display/Image.h
new file mode 100644
index 0000000..57061bd
--- /dev/null
+++ b/Display/Image.h
@@ -0,0 +1,178 @@
+//******************************************************************************
+// @file Image.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Image Visual Object Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef Images_h
+#define Images_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DevCfg.h"
+#include "VisObject.h"
+
+// *****************************************************************************
+// *** Palettes external ***************************************************
+// *****************************************************************************
+extern const uint16_t PALETTE_884[256];
+extern const uint16_t PALETTE_775[256];
+extern const uint16_t PALETTE_676[256];
+
+// *****************************************************************************
+// *** Image description structure *****************************************
+// *****************************************************************************
+typedef struct typeImageDesc
+{
+ // Image width
+ uint16_t width;
+ // Image height
+ uint16_t height;
+ // Bits per pixel
+ uint8_t bits_per_pixel;
+ // Pointer to image data
+ union
+ {
+ const uint8_t* img8;
+ const uint16_t* img16;
+ const void* img;
+ };
+ // Pointer to palette
+ const uint16_t* palette;
+ // Transparent color (-1 no transparent colors)
+ int32_t transparent_color;
+} ImageDesc;
+
+// *****************************************************************************
+// *** Universal Image Class ***********************************************
+// *****************************************************************************
+class Image : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Image(int32_t x, int32_t y, const ImageDesc& img_dsc);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ // *************************************************************************
+ // *** Set Horizontal Flip function ************************************
+ // *************************************************************************
+ void SetHorizontalFlip(bool flip) {hor_mirror = flip;}
+
+ // *************************************************************************
+ // *** Set Image function **********************************************
+ // *************************************************************************
+ void SetImage(const ImageDesc& img_dsc, bool semaphore_taken = false);
+
+ protected:
+ // Reference to image description structure
+ const ImageDesc& img_description;
+ // Bits per pixel
+ uint8_t bits_per_pixel;
+ // Pointer to the image
+ const void* img;
+ // Pointer to the palette
+ const uint16_t* palette;
+ // Transparent color (-1 no transparent colors)
+ int32_t transparent_color;
+ // Horizontal mirror
+ bool hor_mirror;
+};
+
+// *****************************************************************************
+// *** Image 8-bit Class ***************************************************
+// *****************************************************************************
+class Image8 : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Image8(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t* p_img, const uint16_t* p_palette);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ private:
+ // Pointer to the image
+ const uint8_t* img;
+ // Pointer to the palette
+ const uint16_t* palette;
+};
+
+// *****************************************************************************
+// *** Image 16-bit Class ***************************************************
+// *****************************************************************************
+class Image16 : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Image16(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t* p_img);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ private:
+ // Pointer to the image
+ const uint16_t* img;
+};
+
+#endif
diff --git a/Display/Primitives.cpp b/Display/Primitives.cpp
new file mode 100644
index 0000000..2b7ad57
--- /dev/null
+++ b/Display/Primitives.cpp
@@ -0,0 +1,326 @@
+//******************************************************************************
+// @file Primitives.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Primitives Visual Object Classes(Box, Line, Circle), implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "Primitives.h"
+
+#include <cstdlib> // for abs()
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Box *****************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+Box::Box(int32_t x, int32_t y, int32_t w, int32_t h, int32_t c, bool is_fill)
+{
+ SetParams(x, y, w, h, c, is_fill);
+}
+
+// *****************************************************************************
+// *** SetParams ***********************************************************
+// *****************************************************************************
+void Box::SetParams(int32_t x, int32_t y, int32_t w, int32_t h, int32_t c, bool is_fill)
+{
+ color = c;
+ x_start = x;
+ y_start = y;
+ x_end = x + w - 1;
+ y_end = y + h - 1;
+ width = w;
+ height = h;
+ rotation = 0;
+ fill = is_fill;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Box::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ // Find start x position
+ int32_t start = x_start - start_x;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = x_end - start_x;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(end > 0)
+ {
+ // If fill or first/last line - must be solid
+ if(fill || line == y_start || line == y_end)
+ {
+ for(int32_t i = start; i <= end; i++) buf[i] = color;
+ }
+ else
+ {
+ if(x_start - start_x >= 0) buf[start] = color;
+ if(x_end - start_x < n) buf[end] = color;
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Box::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // Draw only if needed
+ if((row >= x_start) && (row <= x_end))
+ {
+ // Find start x position
+ int32_t start = y_start - start_y;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = y_end - start_y;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+ // Have sense draw only if end pointer in buffer
+ if(end > 0)
+ {
+ // If fill or first/last row - must be solid
+ if(fill || row == x_start || row == x_end)
+ {
+ for(int32_t i = start; i <= end; i++) buf[i] = color;
+ }
+ else
+ {
+ if(y_start - start_y >= 0) buf[start] = color;
+ if(y_end - start_y < n) buf[end] = color;
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Line ****************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+Line::Line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t c)
+{
+ SetParams(x1, y1, x2, y2, c);
+}
+
+// *****************************************************************************
+// *** SetParams ***********************************************************
+// *****************************************************************************
+void Line::SetParams(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t c)
+{
+ color = c;
+ x_start = x1;
+ y_start = y1;
+ x_end = x2;
+ y_end = y2;
+ width = (x1 < x2) ? (x2 - x1) : (x1 - x2);
+ height = (y1 < y2) ? (y2 - y1) : (y1 - y2);
+ rotation = 0;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Line::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ const int32_t deltaX = abs(x_end - x_start);
+ const int32_t deltaY = abs(y_end - y_start);
+ const int32_t signX = x_start < x_end ? 1 : -1;
+ const int32_t signY = y_start < y_end ? 1 : -1;
+
+ int32_t error = deltaX - deltaY;
+
+ int32_t x = x_start - start_x;
+ int32_t y = y_start;
+
+ int32_t end_x = x_end - start_x;
+ while((x != end_x || y != y_end) && (y != line))
+ {
+ const int32_t error2 = error * 2;
+ if(error2 > -deltaY)
+ {
+ error -= deltaY;
+ x += signX;
+ }
+ if(error2 < deltaX)
+ {
+ error += deltaX;
+ y += signY;
+ }
+ }
+
+ while((x != end_x || y != y_end) && (y == line))
+ {
+ if((x >= 0) && (x < n)) buf[x] = color;
+ const int32_t error2 = error * 2;
+ if(error2 > -deltaY)
+ {
+ error -= deltaY;
+ x += signX;
+ }
+ if(error2 < deltaX)
+ {
+ break;
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Line::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // FIX ME: implement for Vertical Update Mode too
+}
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Circle **************************************************************
+// *****************************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+Circle::Circle(int32_t x, int32_t y, int32_t r, int32_t c, bool is_fill)
+{
+ SetParams(x, y, r, c, is_fill);
+}
+
+// *****************************************************************************
+// *** SetParams ***********************************************************
+// *****************************************************************************
+void Circle::SetParams(int32_t x, int32_t y, int32_t r, int32_t c, bool is_fill)
+{
+ color = c;
+ radius = r;
+ x_start = x - r;
+ y_start = y - r;
+ x_end = x + r;
+ y_end = y + r;
+ width = r*2;
+ height = r*2;
+ rotation = 0;
+ fill = is_fill;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Circle::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ int32_t x = 0;
+ int32_t y = radius;
+ int32_t x0 = x_start + radius - start_x;
+ int32_t y0 = y_start + radius;
+ int32_t delta = 1 - 2 * radius;
+ int32_t error = 0;
+ bool line_drawed = false;
+
+ while(y >= 0)
+ {
+ if( (y0 + y == line) || (y0 - y == line) )
+ {
+ if(fill)
+ {
+ int32_t i = x0 - x;
+ if(i < 0) i = 0;
+ if(x0 + x < n) n = x0 + x;
+ for(;i < n; i++)
+ {
+ buf[i] = color;
+ }
+ break;
+ }
+ else
+ {
+ int32_t xl = x0 - x;
+ int32_t xr = x0 + x;
+ if((xl > 0) && (xl < n)) buf[xl] = color;
+ if((xr > 0) && (xr < n)) buf[xr] = color;
+ }
+ line_drawed = true;
+ }
+ else
+ {
+ if(line_drawed == true) break;
+ }
+ error = 2 * (delta + y) - 1;
+ if(delta < 0 && error <= 0)
+ {
+ ++x;
+ delta += 2 * x + 1;
+ continue;
+ }
+ error = 2 * (delta - x) - 1;
+ if(delta > 0 && error > 0)
+ {
+ --y;
+ delta += 1 - 2 * y;
+ continue;
+ }
+ ++x;
+ delta += 2 * (x - y);
+ --y;
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void Circle::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ if((row >= x_start) && (row <= x_end))
+ {
+ // Find start x position
+ int32_t start = y_start - start_y;
+ // Prevent write in memory before buffer
+ if(start < 0) start = 0;
+ // Find start x position
+ int32_t end = y_end - start_y;
+ // Prevent buffer overflow
+ if(end > n) end = n;
+ // Have sense draw only if end pointer in buffer
+ if(end > 0)
+ {
+ for(int32_t i = start; i < end; i++) buf[i] = color;
+ }
+ }
+}
diff --git a/Display/Primitives.h b/Display/Primitives.h
new file mode 100644
index 0000000..2a4e0ee
--- /dev/null
+++ b/Display/Primitives.h
@@ -0,0 +1,161 @@
+//******************************************************************************
+// @file Primitives.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Primitives Visual Object Classes(Box, Line, Circle), header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef Primitives_h
+#define Primitives_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DevCfg.h"
+#include "VisObject.h"
+
+// *****************************************************************************
+// *** Box Class ***********************************************************
+// *****************************************************************************
+class Box : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Box() {};
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Box(int32_t x, int32_t y, int32_t w, int32_t h, int32_t c, bool is_fill = false);
+
+ // *************************************************************************
+ // *** SetParams *******************************************************
+ // *************************************************************************
+ void SetParams(int32_t x, int32_t y, int32_t w, int32_t h, int32_t c, bool is_fill = false);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ private:
+ // Box color
+ uint16_t color = 0U;
+ // Is box fill ?
+ bool fill = false;
+};
+
+// *****************************************************************************
+// *** Line Class **********************************************************
+// *****************************************************************************
+class Line : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Line() {};
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t c);
+
+ // *************************************************************************
+ // *** SetParams *******************************************************
+ // *************************************************************************
+ void SetParams(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t c);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ private:
+ // Line color
+ uint16_t color = 0U;
+};
+
+// *****************************************************************************
+// *** Circle Class ********************************************************
+// *****************************************************************************
+class Circle : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Circle() {};
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ Circle(int32_t x, int32_t y, int32_t r, int32_t c, bool is_fill = false);
+
+ // *************************************************************************
+ // *** SetParams **************************************II***************
+ // *************************************************************************
+ void SetParams(int32_t x, int32_t y, int32_t r, int32_t c, bool is_fill = false);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ private:
+ // Circle color
+ uint16_t color = 0U;
+ // Circle radius
+ int16_t radius = 0;
+ // Is box fill ?
+ bool fill = false;
+};
+
+#endif
diff --git a/Display/Strings.cpp b/Display/Strings.cpp
new file mode 100644
index 0000000..e600867
--- /dev/null
+++ b/Display/Strings.cpp
@@ -0,0 +1,242 @@
+//******************************************************************************
+// @file String.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: String Visual Object Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "Strings.h"
+#include "Fonts.h"
+
+#include <cstring> // for strlen()
+
+// *****************************************************************************
+// *****************************************************************************
+// *** Strings *************************************************************
+// *****************************************************************************
+// *****************************************************************************
+const String::FontProfile String::fonts[FONTS_MAX] =
+// W H BPP Pointer to data
+{ { 4, 6, 6, (const uint8_t*)font4x6},
+ { 6, 8, 8, (const uint8_t*)font6x8},
+ { 8, 8, 8, (const uint8_t*)font8x8},
+ { 8, 12, 12, (const uint8_t*)font8x12},
+ {12, 16, 32, (const uint8_t*)font12x16} };
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+String::String(const char* str, int32_t x, int32_t y, uint32_t tc, FontType ft)
+{
+ SetParams(str, x, y, tc, ft);
+}
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+String::String(const char* str, int32_t x, int32_t y, uint32_t tc, uint32_t bgc, FontType ft)
+{
+ SetParams(str, x, y, tc, bgc, ft);
+}
+
+// *****************************************************************************
+// *** SetParams ***********************************************************
+// *****************************************************************************
+void String::SetParams(const char* str, int32_t x, int32_t y, uint32_t tc, FontType ft)
+{
+ string = (const uint8_t*)str;
+ x_start = x;
+ y_start = y;
+ txt_color = tc;
+ bg_color = 0;
+ font_type = ft;
+ transpatent_bg = true;
+ width = fonts[ft].w * strlen(str);
+ height = fonts[ft].h;
+ x_end = x + width - 1;
+ y_end = y + height - 1;
+ rotation = 0;
+}
+
+// *****************************************************************************
+// *** SetParams ***********************************************************
+// *****************************************************************************
+void String::SetParams(const char* str, int32_t x, int32_t y, uint32_t tc, uint32_t bgc, FontType ft)
+{
+ string = (const uint8_t*)str;
+ x_start = x;
+ y_start = y;
+ txt_color = tc;
+ bg_color = bgc;
+ font_type = ft;
+ transpatent_bg = false;
+ width = fonts[ft].w * strlen(str);
+ height = fonts[ft].h;
+ x_end = x + width - 1;
+ y_end = y + height - 1;
+ rotation = 0;
+}
+
+// *****************************************************************************
+// *** SetColor ************************************************************
+// *****************************************************************************
+void String::SetColor(uint32_t tc, uint32_t bgc, bool is_trnsp)
+{
+ txt_color = tc;
+ bg_color = bgc;
+ transpatent_bg = is_trnsp;
+}
+
+// *****************************************************************************
+// *** SetString ***********************************************************
+// *****************************************************************************
+void String::SetString(const char* str)
+{
+ // Lock object for changes
+ LockVisObject();
+ //Set new pointer to string
+ string = (const uint8_t*)str;
+ width = fonts[font_type].w * strlen(str);
+ x_end = x_start + width - 1;
+ // Unlock object after changes
+ UnlockVisObject();
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void String::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end) && (string != nullptr))
+ {
+ // Current symbol X position
+ int32_t x = x_start;
+ // Number of bytes need skipped for draw line
+ uint32_t skip_bytes = (line - y_start) * fonts[font_type].bytes_per_char / fonts[font_type].h;
+ // Pointer to string. Will increment for get characters.
+ const uint8_t* str = string;
+
+ // While we have symbols
+ while(*str != '\0')
+ {
+ uint32_t b = 0;
+ uint32_t w = 0;
+ // Get all symbol line
+ for(uint32_t i = 0; i < fonts[font_type].bytes_per_char; i++)
+ {
+ b |= fonts[font_type].font_data[((uint32_t)(*str)) * fonts[font_type].bytes_per_char + skip_bytes + i] << (i*8);
+ }
+ // Output symbol line
+ while(w < fonts[font_type].w)
+ {
+ // Put color in buffer only if visible
+ if((x >= start_x) && (x < start_x+n))
+ {
+ if((b&1) == 1)
+ {
+ buf[x] = txt_color;
+ }
+ else if(transpatent_bg == false)
+ {
+ buf[x] = bg_color;
+ }
+ else
+ {
+ // Empty statement
+ }
+ }
+ b >>= 1;
+ w++;
+ x++;
+ }
+ str++;
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void String::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // Draw only if needed
+ if((row >= x_start) && (row <= x_end) && (string != nullptr))
+ {
+ // Find line in symbol
+ int16_t start = y_start - start_y;
+ // Find line in symbol
+ int16_t line = (row - x_start);
+
+ if(line >= 0)
+ {
+ // Get symbol
+ uint8_t c = string[line / fonts[font_type].w];
+ // Find line in symbol
+ line %= fonts[font_type].w;
+ // Index to symbol in data array
+ uint16_t s_idx = c * fonts[font_type].bytes_per_char;
+ // Index to symbol in data array
+ uint16_t bytes_per_line = fonts[font_type].bytes_per_char / fonts[font_type].h;
+ // Get symbols lines
+ for(int32_t i = 0; i < fonts[font_type].h; i++)
+ {
+ uint32_t b = *(uint32_t *)(&fonts[font_type].font_data[s_idx + i*bytes_per_line]);
+ if(b & (1U<<line))
+ {
+ if((start+i > 0) && (start+i < n))
+ {
+ buf[start+i] = txt_color;
+ }
+ }
+ }
+ }
+ }
+}
+
+// *****************************************************************************
+// *** GetFontW ************************************************************
+// *****************************************************************************
+uint32_t String::GetFontW(FontType ft)
+{
+ // Zero my default
+ uint32_t font_w = 0U;
+ // If provided valid font number
+ if(ft < FONTS_MAX)
+ {
+ // Get font width
+ font_w = fonts[ft].w;
+ }
+ // Return result
+ return font_w;
+};
+
+// *****************************************************************************
+// *** GetFontH ************************************************************
+// *****************************************************************************
+uint32_t String::GetFontH(FontType ft)
+{
+ // Zero my default
+ uint32_t font_h = 0U;
+ // If provided valid font number
+ if(ft < FONTS_MAX)
+ {
+ // Get font height
+ font_h = fonts[ft].h;
+ }
+ // Return result
+ return font_h;
+};
diff --git a/Display/Strings.h b/Display/Strings.h
new file mode 100644
index 0000000..4dd5633
--- /dev/null
+++ b/Display/Strings.h
@@ -0,0 +1,146 @@
+//******************************************************************************
+// @file String.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: String Visual Object Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef Strings_h
+#define Strings_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DevCfg.h"
+#include "VisObject.h"
+
+// *****************************************************************************
+// *** String Class ********************************************************
+// *****************************************************************************
+class String : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Enum with all fonts types ***************************************
+ // *************************************************************************
+ typedef enum
+ {
+ FONT_4x6,
+ FONT_6x8,
+ FONT_8x8,
+ FONT_8x12,
+ FONT_12x16,
+ FONTS_MAX
+ } FontType;
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ String() {};
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ String(const char* str, int32_t x, int32_t y, uint32_t tc, FontType ft = FONT_8x8);
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ String(const char* str, int32_t x, int32_t y, uint32_t tc, uint32_t bgc, FontType ft = FONT_8x8);
+
+ // *************************************************************************
+ // *** SetParams *******************************************************
+ // *************************************************************************
+ void SetParams(const char* str, int32_t x, int32_t y, uint32_t tc, FontType ft);
+
+ // *************************************************************************
+ // *** SetParams *******************************************************
+ // *************************************************************************
+ void SetParams(const char* str, int32_t x, int32_t y, uint32_t tc, uint32_t bgc, FontType ft);
+
+ // *************************************************************************
+ // *** SetString *******************************************************
+ // *************************************************************************
+ void SetString(const char* str);
+
+ // *************************************************************************
+ // *** SetColor ********************************************************
+ // *************************************************************************
+ void SetColor(uint32_t tc, uint32_t bgc = 0U, bool is_trnsp = true);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ // *************************************************************************
+ // *** GetFontW ********************************************************
+ // *************************************************************************
+ static uint32_t GetFontW(FontType ft);
+
+ // *************************************************************************
+ // *** GetFontH ********************************************************
+ // *************************************************************************
+ static uint32_t GetFontH(FontType ft);
+
+ private:
+ // Pointer to string
+ // FIX ME: must be changed for prevent changing string during drawing
+ const uint8_t* string = nullptr;
+ // Text color
+ uint16_t txt_color = 0;
+ // Background color
+ uint16_t bg_color = 0;
+ // Font type
+ FontType font_type = FONT_8x8;
+ // Is background transparent ?
+ bool transpatent_bg = false;
+
+ typedef struct
+ {
+ uint8_t w; // Width of character
+ uint8_t h; // Height of character
+ uint8_t bytes_per_char; // Bytes Per Char
+ const uint8_t* font_data; // Pointer to font data
+ } FontProfile;
+
+ // Fonts structures. One for all String classes.
+ static const FontProfile fonts[FONTS_MAX];
+};
+
+#endif
diff --git a/Display/TiledMap.cpp b/Display/TiledMap.cpp
new file mode 100644
index 0000000..8b59e42
--- /dev/null
+++ b/Display/TiledMap.cpp
@@ -0,0 +1,179 @@
+//******************************************************************************
+// @file TiledMap.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Tiled Map Class, implementation
+//
+// @copyright Copyright (c) 2017, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "TiledMap.h"
+
+// *****************************************************************************
+// *** Constructor *********************************************************
+// *****************************************************************************
+TiledMap::TiledMap(int32_t x, int32_t y, int32_t w, int32_t h,
+ uint8_t* map, uint32_t map_w, uint32_t map_h, uint8_t bitmask,
+ const ImageDesc* tiles, uint32_t n, int32_t def_color)
+{
+ x_start = x;
+ y_start = y;
+ width = w;
+ height = h;
+ x_end = x_start + width - 1;
+ y_end = y_start + height - 1;
+ tiles_map = map;
+ map_width = map_w;
+ map_height = map_h;
+ tile_bitmask = bitmask;
+ tiles_img = tiles;
+ tiles_cnt = n;
+ tile_width = tiles->width;
+ tile_height = tiles->height;
+ bg_color = def_color;
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void TiledMap::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
+{
+ // Draw only if needed
+ if((line >= y_start) && (line <= y_end))
+ {
+ int32_t start_offset = 0;
+ // Find start x position
+ int32_t start = x_start - start_x;
+ // Prevent write in memory before buffer
+ if(start < 0)
+ {
+ start_offset = -start;
+ start = 0;
+ }
+ // Find end x position
+ int32_t end = x_end - start_x;
+ // Prevent buffer overflow
+ if(end >= n) end = n - 1;
+
+ // Find start tile index and offsets
+ int32_t x_tile_idx = (x_pos + start_x + start_offset) / tile_width;
+ int32_t y_tile_idx = (y_pos + line - y_start) / tile_height;
+ int32_t tile_idx = y_tile_idx * map_width + x_tile_idx;
+ int32_t x_tile_offset = (x_pos + start_x + start_offset) % tile_width;
+ int32_t y_tile_offset = ((y_pos + line - y_start) % tile_height) * tile_width;
+
+ // If default color is 0 or greater
+ if(bg_color >= 0)
+ {
+ // Fill buffer by default color
+ for(int32_t i = start; i < end; i++)
+ {
+ buf[i] = bg_color;
+ }
+ }
+ // Prepare variables for first cycle
+ int32_t pix_idx = start;
+ int32_t tile_pix_idx = x_tile_offset;
+ // Draw line with tiles
+ while(pix_idx < n)
+ {
+ // Get tile value
+ uint8_t tile_val = tiles_map[tile_idx] & tile_bitmask;
+ // Skip empty tiles
+ if(tile_val >= tiles_cnt)
+ {
+ pix_idx += tile_width - tile_pix_idx;
+ tile_idx++;
+ tile_pix_idx = 0;
+ continue;
+ }
+ // Get pointer to the current tile image
+ const uint8_t* tile_ptr = &tiles_img[tile_val].img8[y_tile_offset];
+ // Get pointer to the current tile palette
+ const uint16_t* palette_ptr = tiles_img[tile_val].palette;
+ // Get transparent color
+ const int32_t transparent_color = tiles_img[tile_val].transparent_color;
+ // Draw tile
+ for(;(tile_pix_idx < (int32_t)tile_width) && (pix_idx <= end); tile_pix_idx++)
+ {
+ // Get pixel data
+ uint16_t data = palette_ptr[tile_ptr[tile_pix_idx]];
+ // If not transparent - output to buffer
+ if(data != transparent_color) buf[pix_idx] = data;
+ pix_idx++;
+ }
+ // Increase tile index
+ tile_idx++;
+ // Clear tile pixel counter
+ tile_pix_idx = 0;
+ }
+ }
+}
+
+// *****************************************************************************
+// *** Put line in buffer **************************************************
+// *****************************************************************************
+void TiledMap::DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y)
+{
+ // Not implemented yet
+}
+
+// *****************************************************************************
+// *** Scroll tiled map ****************************************************
+// *****************************************************************************
+void TiledMap::ScrollView(int32_t dx, int32_t dy)
+{
+ LockVisObject();
+ x_pos += dx;
+ if(x_pos < 0) x_pos = 0;
+ y_pos += dy;
+ if(y_pos < 0) y_pos = 0;
+ UnlockVisObject();
+}
+
+// *****************************************************************************
+// *** GetLvlIdxByXY *******************************************************
+// *****************************************************************************
+int32_t TiledMap::GetLvlIdxByXY(uint32_t x, uint32_t y)
+{
+ uint32_t result = -1;
+ // Calculate tiles indexes
+ uint32_t x_tile = x/tile_width;
+ uint32_t y_tile = y/tile_height;
+ // Set result only if x & y valid values
+ if(x_tile < map_width && y_tile < map_height)
+ {
+ result = y_tile*map_width + x_tile;
+ }
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** GetLvlDataByXY ******************************************************
+// *****************************************************************************
+int8_t TiledMap::GetLvlDataByXY(uint32_t x, uint32_t y)
+{
+ uint32_t result = 0U;
+ // Calculate tiles indexes
+ uint32_t x_tile = x/tile_width;
+ uint32_t y_tile = y/tile_height;
+ // Set result only if x & y valid values
+ if(x_tile < map_width && y_tile < map_height)
+ {
+ result = tiles_map[y_tile*map_width + x_tile];
+ }
+ // Return result
+ return result;
+}
diff --git a/Display/TiledMap.h b/Display/TiledMap.h
new file mode 100644
index 0000000..fc4bb74
--- /dev/null
+++ b/Display/TiledMap.h
@@ -0,0 +1,131 @@
+//******************************************************************************
+// @file TiledMap.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Tiled Map Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2017, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef TilesMap_h
+#define TilesMap_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DevCfg.h"
+#include "VisObject.h"
+#include "Image.h"
+
+// *****************************************************************************
+// *** Tile Map Class ******************************************************
+// *****************************************************************************
+class TiledMap : public VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ TiledMap(int32_t x, int32_t y, int32_t w, int32_t h,
+ uint8_t* map, uint32_t map_w, uint32_t map_h, uint8_t bitmask,
+ const ImageDesc* tiles, uint32_t n, int32_t def_color);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t y = 0);
+
+ // *************************************************************************
+ // *** Put line in buffer **********************************************
+ // *************************************************************************
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t x = 0);
+
+ // *************************************************************************
+ // *** Scroll tiled map ************************************************
+ // *************************************************************************
+ void ScrollView(int32_t dx, int32_t dy = 0);
+
+ // *************************************************************************
+ // *** GetMapPosX ******************************************************
+ // *************************************************************************
+ int32_t GetLvlIdxByXY(uint32_t x, uint32_t y);
+
+ // *************************************************************************
+ // *** GetMapPosX ******************************************************
+ // *************************************************************************
+ int8_t GetLvlDataByXY(uint32_t x, uint32_t y);
+
+ // *************************************************************************
+ // *** GetMapPosX ******************************************************
+ // *************************************************************************
+ int32_t GetMapPosX(void) {return x_pos;}
+
+ // *************************************************************************
+ // *** GetMapPosY ******************************************************
+ // *************************************************************************
+ int32_t GetMapPosY(void) {return y_pos;}
+
+ // *************************************************************************
+ // *** GetPixWidth *****************************************************
+ // *************************************************************************
+ int32_t GetPixWidth() {return (tile_width * map_width);}
+
+ // *************************************************************************
+ // *** GetPixHeight ****************************************************
+ // *************************************************************************
+ int32_t GetPixHeight() {return (tile_height * map_height);}
+
+ private:
+ // Pointer to the tiles map
+ uint8_t* tiles_map;
+ // Map width in tiles
+ uint32_t map_width;
+ // Map height in tiles
+ uint32_t map_height;
+ // Bitmask for tiles
+ uint8_t tile_bitmask;
+ // Image descriptions of tiles picture
+ const ImageDesc* tiles_img;
+ // Image descriptions of tiles picture
+ uint32_t tiles_cnt;
+ // Tiles width in pixels
+ uint32_t tile_width;
+ // Tiles height in pixels
+ uint32_t tile_height;
+ // Background color (-1 - transparent)
+ int32_t bg_color;
+ // X position of tiled map in the viewport
+ int32_t x_pos = 0;
+ // Y position of tiled map in the viewport
+ int32_t y_pos = 0;
+};
+
+#endif
diff --git a/Display/VisObject.cpp b/Display/VisObject.cpp
new file mode 100644
index 0000000..3b206ea
--- /dev/null
+++ b/Display/VisObject.cpp
@@ -0,0 +1,125 @@
+//******************************************************************************
+// @file VisObject.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Visual Object Base Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "VisObject.h"
+#include "DisplayDrv.h" // for DelVisObjectFromList()
+
+// *****************************************************************************
+// *** Destructor **********************************************************
+// *****************************************************************************
+VisObject::~VisObject()
+{
+ // Remove object from object list before delete
+ DisplayDrv::GetInstance().DelVisObjectFromList(this);
+}
+
+// *****************************************************************************
+// *** Lock Visual Object ***************************************************
+// *****************************************************************************
+void VisObject::LockVisObject()
+{
+ // Lock line
+ DisplayDrv::GetInstance().LockDisplayLine();
+};
+
+// *****************************************************************************
+// *** Unlock Visual Object ************************************************
+// *****************************************************************************
+void VisObject::UnlockVisObject()
+{
+ // Unlock line
+ DisplayDrv::GetInstance().UnlockDisplayLine();
+};
+
+// *****************************************************************************
+// *** Show Visual Object **************************************************
+// *****************************************************************************
+void VisObject::Show(uint32_t z_pos)
+{
+ // Z position is 0 by default. In this case we can use 0 here as "no pos" flag
+ if(z_pos != 0)
+ {
+ z = z_pos;
+ }
+ // Add to VisObject List
+ DisplayDrv::GetInstance().AddVisObjectToList(this, z);
+}
+
+// *****************************************************************************
+// *** Hide Visual Object **************************************************
+// *****************************************************************************
+void VisObject::Hide(void)
+{
+ // Delete from VisObject List
+ DisplayDrv::GetInstance().DelVisObjectFromList(this);
+}
+
+// *****************************************************************************
+// *** Check status of Show Visual Object **********************************
+// *****************************************************************************
+bool VisObject::IsShow(void)
+{
+ // Return false by default
+ bool ret = false;
+ // If any pointer is not null - object in list
+ if( (p_next != nullptr) || (p_prev != nullptr) )
+ {
+ ret = true;
+ }
+ // Return result
+ return ret;
+}
+
+// *****************************************************************************
+// *** Move Visual Object **************************************************
+// *****************************************************************************
+void VisObject::Move(int32_t x, int32_t y, bool is_delta)
+{
+ // Lock object for changes
+ LockVisObject();
+ // Make changes
+ if(is_delta == true)
+ {
+ // Move object in delta coordinates
+ x_start += x;
+ y_start += y;
+ x_end += x;
+ y_end += y;
+ }
+ else
+ {
+ // Move object in absolute coordinates
+ x_start = x;
+ y_start = y;
+ x_end = x + width - 1;
+ y_end = y + height - 1;
+ }
+ // Unlock object after changes
+ UnlockVisObject();
+}
+
+// *****************************************************************************
+// *** Action **************************************************************
+// *****************************************************************************
+void VisObject::Action(ActionType action, int32_t tx, int32_t ty)
+{
+ // Empty function. We can do active object without custom Action function
+ // for cover active object with lower Z.
+}
diff --git a/Display/VisObject.h b/Display/VisObject.h
new file mode 100644
index 0000000..a8b5439
--- /dev/null
+++ b/Display/VisObject.h
@@ -0,0 +1,199 @@
+//******************************************************************************
+// @file VisObject.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Visual Object Base Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef VisObject_h
+#define VisObject_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DevCfg.h"
+
+// *****************************************************************************
+// * VisObject class. This class implements base Visual Objects properties.
+class VisObject
+{
+ public:
+ // *************************************************************************
+ // *** Action **********************************************************
+ // *************************************************************************
+ typedef enum
+ {
+ ACT_TOUCH, // When object touched
+ ACT_UNTOUCH, // When object detouched
+ ACT_MOVE, // When object moved on object
+ ACT_MOVEIN, // When object moved in to object
+ ACT_MOVEOUT, // When object moved out of object
+ ACT_MAX // Total possible actions
+ } ActionType;
+
+ // *************************************************************************
+ // *** VisObject *******************************************************
+ // *************************************************************************
+ VisObject() {};
+
+ // *************************************************************************
+ // *** ~VisObject ******************************************************
+ // *************************************************************************
+ // * Destructor. Call DelVisObjectFromList() from DisplayDrv class for
+ // * remove from list before delete and delete semaphore.
+ virtual ~VisObject();
+
+ // *************************************************************************
+ // *** LockVisObject ***************************************************
+ // *************************************************************************
+ void LockVisObject();
+
+ // *************************************************************************
+ // *** UnlockVisObject *************************************************
+ // *************************************************************************
+ void UnlockVisObject();
+
+ // *************************************************************************
+ // *** Show ************************************************************
+ // *************************************************************************
+ // * Show VisObject on screen. This function call AddVisObjectToList() from
+ // * DisplayDrv class. When this function calls first time, user must
+ // * provide Z level. In future user can call this function without
+ // * parameters - previously set Z will be used.
+ virtual void Show(uint32_t z_pos = 0);
+
+ // *************************************************************************
+ // *** Hide ************************************************************
+ // *************************************************************************
+ // * Hide VisObject from screen. This function call DelVisObjectFromList()
+ // * from DisplayDrv class.
+ virtual void Hide(void);
+
+ // *************************************************************************
+ // *** IsShow **********************************************************
+ // *************************************************************************
+ // * Check status of Show Visual Object. Return true if object in DisplayDrv list.
+ virtual bool IsShow(void);
+
+ // *************************************************************************
+ // *** Move ************************************************************
+ // *************************************************************************
+ // * Move object on screen. Set new x and y coordinates. If flag is set -
+ // * move is relative, not absolute.
+ virtual void Move(int32_t x, int32_t y, bool is_delta = false);
+
+ // *************************************************************************
+ // *** DrawInBufH ******************************************************
+ // *************************************************************************
+ // * Draw one horizontal line of object in specified buffer.
+ // * Each derived class must implement this function.
+ virtual void DrawInBufH(uint16_t* buf, int32_t n, int32_t row, int32_t start_y = 0) = 0;
+
+ // *************************************************************************
+ // *** DrawInBufW ******************************************************
+ // *************************************************************************
+ // * Draw one vertical line of object in specified buffer.
+ // * Each derived class must implement this function.
+ virtual void DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x = 0) = 0;
+
+ // *************************************************************************
+ // *** Action **********************************************************
+ // *************************************************************************
+ virtual void Action(ActionType action, int32_t tx, int32_t ty);
+
+ // *************************************************************************
+ // *** Return Start X coordinate ***************************************
+ // *************************************************************************
+ virtual int32_t GetStartX(void) {return x_start;};
+
+ // *************************************************************************
+ // *** Return Start Y coordinate ***************************************
+ // *************************************************************************
+ virtual int32_t GetStartY(void) {return y_start;};
+
+ // *************************************************************************
+ // *** Return End X coordinate *****************************************
+ // *************************************************************************
+ virtual int32_t GetEndX(void) {return x_end;};
+
+ // *************************************************************************
+ // *** Return End Y coordinate *****************************************
+ // *************************************************************************
+ virtual int32_t GetEndY(void) {return y_end;};
+
+ // *************************************************************************
+ // *** Return Width of object ******************************************
+ // *************************************************************************
+ virtual int32_t GetWidth(void) {return width;};
+
+ // *************************************************************************
+ // *** Return Height of object *****************************************
+ // *************************************************************************
+ virtual int32_t GetHeight(void) {return height;};
+
+ protected:
+ // *************************************************************************
+ // *** Object parameters ***********************************************
+ // *************************************************************************
+
+ // X and Y start coordinates of object
+ int16_t x_start = 0, y_start = 0;
+ // X and Y end coordinates of object
+ int16_t x_end = 0, y_end = 0;
+ // Width and Height of object
+ int16_t width = 0, height = 0;
+ // Rotation of object
+ int8_t rotation = 0;
+ // Object active
+ bool active = false;
+
+ private:
+ // *************************************************************************
+ // *** Object parameters ***********************************************
+ // *************************************************************************
+ // * Only base class and DisplayDrv have access to this parameters
+
+ // Z position of object
+ uint16_t z = 0;
+ // Pointer to next object. This pointer need to maker object list. Object
+ // can be added only to one list.
+ VisObject* p_next = nullptr;
+ // Pointer to next object. This pointer need to maker object list. Object
+ // can be added only to one list.
+ VisObject* p_prev = nullptr;
+
+ // DisplayDrv is friend for access to pointers and Z
+ friend class DisplayDrv;
+};
+
+#endif
diff --git a/Display/XPT2046.cpp b/Display/XPT2046.cpp
new file mode 100644
index 0000000..0e7f396
--- /dev/null
+++ b/Display/XPT2046.cpp
@@ -0,0 +1,145 @@
+//******************************************************************************
+// @file XPT2046.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: XPT2046 Low Level Driver Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include <XPT2046.h>
+
+// *****************************************************************************
+// *** Init touchscreen ****************************************************
+// *****************************************************************************
+void XPT2046::Init(void)
+{
+ // Pull down CS
+ HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
+ // Send ON command
+ SpiWrite(TON);
+ // Send empty byte for skip answer
+ SpiWrite(EMP);
+ // Send empty byte for skip answer
+ SpiWrite(EMP);
+ // Pull up CS
+ HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_SET);
+}
+
+// *****************************************************************************
+// *** If touched - return true. *******************************************
+// *****************************************************************************
+bool XPT2046::IsTouch(void)
+{
+ // Check T_IRQ input and return state
+ return(HAL_GPIO_ReadPin(T_IRQ_GPIO_Port, T_IRQ_Pin) == GPIO_PIN_RESET);
+}
+
+// *****************************************************************************
+// *** Get X and Y coordinates. If touched - return true. ******************
+// *****************************************************************************
+bool XPT2046::GetRawXY(int32_t& x, int32_t& y)
+{
+ // Return value
+ bool ret = false;
+ // If touch present
+ if(HAL_GPIO_ReadPin(T_IRQ_GPIO_Port, T_IRQ_Pin) == GPIO_PIN_RESET)
+ {
+ // Pull down CS
+ HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
+ // Request X coordinate
+ SpiWrite(CHX);
+ // Receive High byte for X
+ x = SpiWriteRead(EMP) << 8;
+ // Receive Low byte for X
+ x |= SpiWriteRead(EMP);
+ // Shift, because result have only 12 bits, 3 because answer started from
+ // second rise edge
+ x >>= 3;
+ // Pull up CS
+ HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_SET);
+
+ // Pull down CS
+ HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
+ // Request Y coordinate
+ SpiWrite(CHY);
+ // Receive High byte for Y
+ y = SpiWriteRead(EMP) << 8;
+ // Receive Low byte for Y
+ y |= SpiWriteRead(EMP);
+ // Shift, because result have only 12 bits, 3 because answer started from
+ // second rise edge
+ y >>= 3;
+ // Pull up CS
+ HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_SET);
+
+ // Touch present
+ ret = true;
+ }
+ // Return result
+ return ret;
+}
+
+// *****************************************************************************
+// *** Get X and Y coordinates. If touched - return true. ******************
+// *****************************************************************************
+bool XPT2046::GetXY(int32_t& x, int32_t& y)
+{
+ // Return value
+ bool ret = GetRawXY(x, y);
+ // If touch present
+ if(ret)
+ {
+ // Calculate X
+ x = ((x * COEF) / kx) + bx;
+ // Calculate Y
+ y = ((y * COEF) / ky) + by;
+ }
+ // Return touch state
+ return ret;
+}
+
+// *****************************************************************************
+// *** SetCalibrationConsts ************************************************
+// *****************************************************************************
+void XPT2046::SetCalibrationConsts(int32_t nkx, int32_t nky, int32_t nbx, int32_t nby)
+{
+ // Save calibration constants
+ kx = nkx;
+ ky = nky;
+ bx = nbx;
+ by = nby;
+}
+
+// *****************************************************************************
+// *** Write byte to SPI ***************************************************
+// *****************************************************************************
+inline void XPT2046::SpiWrite(uint8_t c)
+{
+ // Call HAL function for send byte by SPI
+ (void) HAL_SPI_Transmit(hspi, &c, sizeof(c), 1U);
+}
+
+// *****************************************************************************
+// *** Write and read byte to/from SPI *************************************
+// *****************************************************************************
+inline uint8_t XPT2046::SpiWriteRead(uint8_t c)
+{
+ // Temporary variable for receive byte
+ uint8_t rcv;
+ // Call HAL function for send/receive byte by SPI
+ (void) HAL_SPI_TransmitReceive(hspi, &c, &rcv, sizeof(uint8_t), 1U);
+ // Return received byte
+ return rcv;
+}
diff --git a/Display/XPT2046.h b/Display/XPT2046.h
new file mode 100644
index 0000000..51b35a5
--- /dev/null
+++ b/Display/XPT2046.h
@@ -0,0 +1,129 @@
+//******************************************************************************
+// @file XPT2046.h
+// @author Nicolai Shlapunov
+//
+// @details DevCore: XPT2046 Low Level Driver Class, header
+//
+// @section LICENSE
+//
+// Software License Agreement (BSD License)
+//
+// Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the Devtronic nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY DEVTRONIC ''AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL DEVTRONIC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//******************************************************************************
+
+#ifndef XPT2046_h
+#define XPT2046_h
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "DevCfg.h"
+
+// *****************************************************************************
+// *** Defines *************************************************************
+// *****************************************************************************
+
+// *****************************************************************************
+// * XPT2046 class. Implements work with XPT2046 resistive touchscreen.
+class XPT2046
+{
+ public:
+ // Coefficient for calibration
+ const static int32_t COEF = 100;
+
+ // *************************************************************************
+ // *** Constructor *****************************************************
+ // *************************************************************************
+ // * This class hasn't task inside. For use this class user must provide
+ // * handle to SPI. Previously I think shape SPI between TFT and Touch.
+ // * But now it is two different SPI. Anyway main idea it is use this class
+ // * in DisplayDrv class for find pressed VisObjects.
+ XPT2046(SPI_HandleTypeDef* in_hspi) : hspi(in_hspi) {};
+
+ // *************************************************************************
+ // *** Init ************************************************************
+ // *************************************************************************
+ // * Init function. Send init sequence to touchscreen controller.
+ void Init(void);
+
+ // *************************************************************************
+ // *** IsTouch *********************************************************
+ // *************************************************************************
+ // * Check touched or not by T_IRQ pin. Return true if touched.
+ bool IsTouch(void);
+
+ // *************************************************************************
+ // *** GetRawXY ********************************************************
+ // *************************************************************************
+ // * Return raw X and Y coordinates. If touched - return true.
+ bool GetRawXY(int32_t& x, int32_t& y);
+
+ // *************************************************************************
+ // *** GetXY ***********************************************************
+ // *************************************************************************
+ // * Return recalculated using calibration constants X and Y coordinates.
+ // * If touched - return true. Can be used for second calibration.
+ bool GetXY(int32_t& x, int32_t& y);
+
+ // *************************************************************************
+ // *** SetCalibrationConsts ********************************************
+ // *************************************************************************
+ // * Set calibration constants. Must be call for calibration touchscreen.
+ void SetCalibrationConsts(int32_t nkx, int32_t nky, int32_t nbx, int32_t nby);
+
+ private:
+ // Turn touchscreen ON
+ const static uint8_t TON = 0x80;
+ // Empty byte
+ const static uint8_t EMP = 0x00;
+ // Request X coordinate
+ const static uint8_t CHX = 0x90;
+ // Request Y coordinate
+ const static uint8_t CHY = 0xD0;
+
+ // Handle to SPI used for touchscreen
+ SPI_HandleTypeDef* hspi = nullptr;
+
+ // Display width and height offset
+ int32_t kx = -1097, ky = -1499;
+ // Display width and height coefficient
+ int32_t bx = 334, by = 259;
+
+ // *************************************************************************
+ // *** SpiWrite ********************************************************
+ // *************************************************************************
+ // * Write byte to SPI
+ inline void SpiWrite(uint8_t c);
+
+ // *************************************************************************
+ // *** SpiWriteRead ****************************************************
+ // *************************************************************************
+ // * Write/read byte from/to SPI
+ inline uint8_t SpiWriteRead(uint8_t c);
+};
+
+#endif