├── ST7789_pin_out_12.png ├── ST7789_pin_out_13.jpg ├── ST7789_pin_out_13_8.png ├── README.md ├── st7789 ├── IMG_to_HEX_converter.py ├── fonts.h ├── st7789.h ├── example.txt ├── bitmap.h └── st7789.c └── analog_scale ├── analog_scale.h └── analog_scale.c /ST7789_pin_out_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GolinskiyKonstantin/STM32_Lib_TFT_ST7789/HEAD/ST7789_pin_out_12.png -------------------------------------------------------------------------------- /ST7789_pin_out_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GolinskiyKonstantin/STM32_Lib_TFT_ST7789/HEAD/ST7789_pin_out_13.jpg -------------------------------------------------------------------------------- /ST7789_pin_out_13_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GolinskiyKonstantin/STM32_Lib_TFT_ST7789/HEAD/ST7789_pin_out_13_8.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STM32_Lib_TFT_ST7789 2 | STM32 Display ST7789 135x240 240x240 172x320 240x280 240x320 76x284 3 | 4 | Данная библиотека для работы с дисплеем ST7789 ( ST7789V ). 5 | 6 | Работает с разрешением экрана 135x240 240x240 172x320 240x280 240x320 76x284 7 | 8 | Данная библиотека поддерживает кириллицу. 9 | 10 | Конфигурация в файле st7789.h 11 | 12 | Инициализация и примеры работы в файле example.txt 13 | 14 | IMG_to_HEX_converter.py - конвертор цветного изображения в массив. 15 | 16 | По всем вопросам пишите: golinskiy.konstantin@gmail.com 17 | -------------------------------------------------------------------------------- /st7789/IMG_to_HEX_converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Цветное изображение конвертируем спомощью файла IMG_to_HEX_converter.py 4 | # запускаем командную строку CMD 5 | # устанавливаем если нет модуль Image -> pip3 install image 6 | # кидаем фаил IMG_to_HEX_converter.py и картинку в одну папку 7 | # потом в командной строке переходим в эту папку и пишем: 8 | # > python IMG_to_HEX_converter.py (имя файла)logo.jpg (ширина)85 (высота)80 9 | # 10 | # например: D:\IMG>python IMG_to_HEX_converter.py logo.jpg 85 80 11 | # 12 | # и в этой же папке пояаиться фаил с нашим массивом picFile.txt 13 | # 14 | # ГЕНЕРИРУЕТ В ФОРМАТЕ RGB565 ( 16bit ) 15 | 16 | 17 | from PIL import Image 18 | import sys 19 | import os 20 | 21 | 22 | 23 | if len(sys.argv) != 4: 24 | print("Usage: {} ".format(sys.argv[0])) 25 | sys.exit(1) 26 | 27 | fname = sys.argv[1] 28 | 29 | W = sys.argv[2] 30 | print("\r\n") 31 | print(" " + str(W)) 32 | 33 | H = sys.argv[3] 34 | print(" " + str(H)) 35 | 36 | img = Image.open(fname) 37 | if img.width != int(W) or img.height != int(H): 38 | print("Error: Разрешение указано не верно ( должно совпадать с картинкой )!!!"); 39 | sys.exit(2) 40 | 41 | f=open("picFile.txt", "a") 42 | 43 | f.write("// size " + str(W) + " x " + str(H) + " \n"); 44 | f.write("const unsigned short img[] = { \n "); 45 | 46 | for y in range(0, img.height): 47 | s = "" 48 | for x in range(0, img.width): 49 | (r, g, b) = img.getpixel( (x, y) ) 50 | color565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 51 | # for right endiness, so ST7735_DrawImage would work 52 | color565 = ((color565 & 0xFF00) >> 8) | ((color565 & 0xFF) << 8) 53 | s += "0x{:04X},".format(color565) 54 | s += " \n" 55 | f.write(s) 56 | 57 | f.write("}; \r\n") 58 | f.close() 59 | print("\r\n Готово !!! OK \r\n") 60 | -------------------------------------------------------------------------------- /st7789/fonts.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | * @file ( фаил ): fonts.h 4 | * @brief ( описание ): 5 | ****************************************************************************** 6 | * @attention ( внимание ): author: Golinskiy Konstantin e-mail: golinskiy.konstantin@gmail.com 7 | ****************************************************************************** 8 | 9 | */ 10 | #ifndef _FONTS_H 11 | #define _FONTS_H 12 | 13 | 14 | //############################################################################################################## 15 | 16 | //---- для экономии памяти шрифты которые не используються закоментировать ------------------------------------- 17 | // Шрифт имеет кирилицу и латиницу 18 | #define FONT_6x8 // 6 x 8 pixels font size structure 19 | #define FONT_7x9 // 7 x 9 pixels font size structure 20 | #define FONT_11x18 // 11 x 18 pixels font size structure 21 | #define FONT_16x26 // 16 x 26 pixels font size structure 22 | // Только цифры -- only numbers 23 | #define FONT_16x28 // 16 x 28 pixels font size structure only numbers 24 | //-------------------------------------------------------------------------------------------------------------- 25 | 26 | //############################################################################################################## 27 | 28 | 29 | /* C++ detection */ 30 | #ifdef __cplusplus 31 | extern C { 32 | #endif 33 | 34 | /** 35 | * 36 | * Default fonts library. It is used in all LCD based libraries. 37 | * 38 | * \par Supported fonts 39 | * 40 | */ 41 | // Обязательно нужен #include "main.h" 42 | // чтоб отдельно не подключать файлы связанные с МК и стандартными библиотеками 43 | #include "main.h" 44 | 45 | #include "string.h" 46 | #include "stdlib.h" 47 | 48 | /** 49 | * @defgroup LIB_Typedefs 50 | * @brief Library Typedefs 51 | * @{ 52 | */ 53 | 54 | /** 55 | * @brief Font structure used on my LCD libraries 56 | */ 57 | typedef struct { 58 | uint8_t FontWidth; /*!< Font width in pixels */ 59 | uint8_t FontHeight; /*!< Font height in pixels */ 60 | const uint16_t *data; /*!< Pointer to data font data array */ 61 | } FontDef_t; 62 | 63 | /** 64 | * @brief String length and height 65 | */ 66 | typedef struct { 67 | uint16_t Length; /*!< String length in units of pixels */ 68 | uint16_t Height; /*!< String height in units of pixels */ 69 | } FONTS_SIZE_t; 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** 76 | * @defgroup FONTS_FontVariables 77 | * @brief Library font variables 78 | * @{ 79 | */ 80 | 81 | /** 82 | * @brief 6 x 8 pixels font size structure 83 | */ 84 | #ifdef FONT_6x8 85 | extern FontDef_t Font_6x8; 86 | #endif 87 | 88 | /** 89 | * @brief 7 x 9 pixels font size structure 90 | */ 91 | #ifdef FONT_7x9 92 | extern FontDef_t Font_7x9; 93 | #endif 94 | 95 | /** 96 | * @brief 11 x 18 pixels font size structure 97 | */ 98 | #ifdef FONT_11x18 99 | extern FontDef_t Font_11x18; 100 | #endif 101 | 102 | /** 103 | * @brief 16 x 26 pixels font size structure 104 | */ 105 | #ifdef FONT_16x26 106 | extern FontDef_t Font_16x26; 107 | #endif 108 | 109 | /** 110 | * @brief 16 x 28 pixels font size structure only numbers 111 | */ 112 | #ifdef FONT_16x28 113 | // Только цифры -- only numbers 114 | extern FontDef_t Font_16x28; 115 | #endif 116 | 117 | /** 118 | * @} 119 | */ 120 | 121 | /** 122 | * @defgroup FONTS_Functions 123 | * @brief Library functions 124 | * @{ 125 | */ 126 | 127 | /** 128 | * @brief Calculates string length and height in units of pixels depending on string and font used 129 | * @param *str: String to be checked for length and height 130 | * @param *SizeStruct: Pointer to empty @ref FONTS_SIZE_t structure where informations will be saved 131 | * @param *Font: Pointer to @ref FontDef_t font used for calculations 132 | * @retval Pointer to string used for length and height 133 | */ 134 | char* FONTS_GetStringSize(char* str, FONTS_SIZE_t* SizeStruct, FontDef_t* Font); 135 | 136 | /** 137 | * @} 138 | */ 139 | 140 | 141 | /** 142 | * @} 143 | */ 144 | 145 | /** 146 | * @} 147 | */ 148 | 149 | /* C++ detection */ 150 | #ifdef __cplusplus 151 | } 152 | #endif 153 | 154 | 155 | #endif /* _FONTS_H */ 156 | 157 | /************************ (C) COPYRIGHT GKP *****END OF FILE****/ 158 | -------------------------------------------------------------------------------- /analog_scale/analog_scale.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ****************************************************************************** 4 | * @file ( фаил ): analog_scale.h 5 | * @brief ( описание ): 6 | ****************************************************************************** 7 | * @attention ( внимание ): author: Golinskiy Konstantin e-mail: golinskiy.konstantin@gmail.com 8 | ****************************************************************************** 9 | 10 | для работы подключаем в проект #include "analog_scale.h" 11 | 12 | /////////// рисуем циферблат в виде окружности ////////////////////////// 13 | 14 | analogMeter(); // рисуем интерфейс циферблата ( 1 раз при старте ) 15 | 16 | HAL_Delay (1500); 17 | 18 | // вызываем функцию plotNeedle(); 19 | // передаем 1 параметр само значение от 0 до 100 20 | // передаем 2 параметр задержку ( задержку можно ставить 0 тогда ее делать отдельно ) 21 | for( int i = 0; i<100; i++){ 22 | plotNeedle(i, 0); 23 | HAL_Delay (10); 24 | } 25 | for( int i = 100; i>=0; i--){ 26 | plotNeedle(i, 10); 27 | //HAL_Delay (10); 28 | } 29 | 30 | ////////////////////////////////////////////////////////////////////////// 31 | 32 | 33 | //// рисуем продолговатые от1 до 6 индикаторы ////////////////////////////////////////////////////////////////////////////// 34 | 35 | uint8_t d = 40; // смещение каждого нового циферблата на 40 пикселей по координате х 36 | plotLinear("A1", d*0, 10 ); // создаем и проресовываем 1 раз при старте циферблат с названием "A1" смещаем его по х на d*0 и по у на 10 37 | plotLinear("A2", d*1, 10 ); // создаем и проресовываем 1 раз при старте циферблат с названием "A2" смещаем его по х на d*1 и по у на 10 38 | plotLinear("A3", d*2, 10 ); // создаем и проресовываем 1 раз при старте циферблат с названием "A3" смещаем его по х на d*2 и по у на 10 39 | plotLinear("A4", d*3, 10 ); // создаем и проресовываем 1 раз при старте циферблат с названием "A4" смещаем его по х на d*3 и по у на 10 40 | plotLinear("A5", d*4, 10 ); // создаем и проресовываем 1 раз при старте циферблат с названием "A5" смещаем его по х на d*4 и по у на 10 41 | plotLinear("A6", d*5, 10 ); // создаем и проресовываем 1 раз при старте циферблат с названием "A6" смещаем его по х на d*5 и по у на 10 42 | // также при смещении по у или х ( для первого значения ) устанавливаем смещение и кол-во циферблатов в функции void plotPointer(void) 43 | //int x = 0; // устанавливаем смещение начального индикатора относительно х 44 | //int y = 10; // устанавливаем смещение начального индикатора относительно у 45 | //int count = 6; // устанавливаем кол-во индикаторов от 1 до 6 46 | // далее заполняем массив value[] данными и потом выводим их на дисплей командой plotPointer(); 47 | 48 | for( int i = 0; i<101; i++){ 49 | value[0] = i; 50 | value[1] = 100-i; 51 | value[2] = i; 52 | value[3] = 100-i; 53 | value[4] = i; 54 | value[5] = 100-i; 55 | plotPointer(); 56 | HAL_Delay (10); 57 | } 58 | 59 | HAL_Delay (1500); 60 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 61 | 62 | 63 | */ 64 | 65 | #ifndef _ANALOG_SCALE_H 66 | #define _ANALOG_SCALE_H 67 | 68 | #ifdef __cplusplus 69 | extern "C" { 70 | #endif 71 | 72 | /* Includes ----------------------------------------------------------*/ 73 | 74 | // Обязательно нужен #include "main.h" 75 | // чтоб отдельно не подключать файлы связанные с МК и стандартными библиотеками 76 | #include "main.h" 77 | 78 | extern int value[6]; 79 | 80 | // ######################################################################### 81 | // Обновление данных стрелки и значения на цифербладе ( функцию вызываем с задержкой не менее 10 мс ) 82 | // первый параметр передаем наше значение ( от -10 до 110 гнаницы ) 83 | // чтоб попадал в диапазон разметки на циферблате передаем от 0 до 100 84 | // второй переметр время для следущего обновления, рекомендуеться ставить 0 и делать вызов функции с интервалом не менее 10 мс 85 | // ######################################################################### 86 | void plotNeedle(int8_t value, uint8_t ms_delay); 87 | 88 | // ######################################################################### 89 | // рисуем сам циферблат ( вызываем функцию 1 раз в начале ) 90 | // ######################################################################### 91 | void analogMeter(void); 92 | 93 | // ######################################################################### 94 | // рисуем вертикальную шкалу ( значение для показа от 0 до 100 ) 95 | // первый параметр название шкалы ( например "A1" ) 96 | // второй параметр координата х ( ширина шкалы 40 ) тоесть следующую шкалу рисуем х + 40 97 | // третий параметр координата у 98 | // ######################################################################### 99 | void plotLinear(char *label, int x, int y); 100 | 101 | // ######################################################################### 102 | // функция опрашивает массив с данными и выводит их на экран 103 | // ######################################################################### 104 | void plotPointer(void); 105 | 106 | //------------------------------------------------------------------------------------ 107 | 108 | 109 | #ifdef __cplusplus 110 | } 111 | #endif 112 | 113 | #endif /* _ANALOG_SCALE_H */ 114 | 115 | /************************ (C) COPYRIGHT GKP *****END OF FILE****/ 116 | -------------------------------------------------------------------------------- /analog_scale/analog_scale.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ****************************************************************************** 4 | * @file ( фаил ): analog_scale.c 5 | * @brief ( описание ): 6 | ****************************************************************************** 7 | * @attention ( внимание ): author: Golinskiy Konstantin e-mail: golinskiy.konstantin@gmail.com 8 | ****************************************************************************** 9 | 10 | */ 11 | 12 | /* Includes ----------------------------------------------------------*/ 13 | #include "analog_scale.h" 14 | 15 | #include "math.h" 16 | #include "stdio.h" 17 | #include "ST7789.h" 18 | #include "fonts.h" 19 | 20 | int value[6] = {0, 0, 0, 0, 0, 0}; 21 | int old_value[6] = { -1, -1, -1, -1, -1, -1}; 22 | 23 | int old_analog = -999; // Value last displayed 24 | 25 | float ltx = 0; // Saved x coord of bottom of needle 26 | uint16_t osx = 120, osy = 120; // Saved x & y coords 27 | 28 | /* 29 | ****************************************************************************** 30 | * @brief ( описание ): 31 | * @param ( параметры ): 32 | * @return ( возвращает ): 33 | 34 | ****************************************************************************** 35 | */ 36 | static long map(long x, long in_min, long in_max, long out_min, long out_max) 37 | { 38 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 39 | } 40 | //---------------------------------------------------------------------------------- 41 | 42 | // ######################################################################### 43 | // Обновление данных стрелки и значения на цифербладе ( функцию вызываем с задержкой не менее 10 мс ) 44 | // первый параметр передаем наше значение ( от -10 до 110 гнаницы ) 45 | // чтоб попадал в диапазон разметки на циферблате передаем от 0 до 100 46 | // второй переметр время для следущего обновления, рекомендуеться ставить 0 и делать вызов функции с интервалом не менее 10 мс 47 | // ######################################################################### 48 | void plotNeedle(int8_t value, uint8_t ms_delay) 49 | { 50 | // формеруем и печатаем текущее значение в левом нижнем углу циферблата 51 | char buff_value[5]; // ставим на +1 чем нужно для \0 52 | sprintf( buff_value, "% 4d", value ); // 4 знакоместа выравнивание по правому краю 53 | ST7789_print( 10, 119 - 20, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, buff_value ); 54 | 55 | // проверяем границы входных данных 56 | if (value < -10){ 57 | value = -10; // Limit value to emulate needle end stops 58 | } 59 | if (value > 110){ 60 | value = 110; 61 | } 62 | 63 | // Move the needle util new value reached 64 | while (!(value == old_analog)) { 65 | if (old_analog < value){ 66 | old_analog++; 67 | } 68 | else{ 69 | old_analog--; 70 | } 71 | 72 | if (ms_delay == 0){ 73 | old_analog = value; // Update immediately id delay is 0 74 | } 75 | 76 | float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 77 | // Calcualte tip of needle coords 78 | float sx = cos((double)sdeg * 0.0174532925); 79 | float sy = sin((double)sdeg * 0.0174532925); 80 | 81 | // Calculate x delta of needle start (does not start at pivot point) 82 | float tx = tan((double)(sdeg + 90) * 0.0174532925); 83 | 84 | // Erase old needle image 85 | ST7789_DrawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, RGB565(255, 255, 255)); 86 | ST7789_DrawLine(120 + 20 * ltx, 140 - 20, osx, osy, RGB565(255, 255, 255)); 87 | ST7789_DrawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, RGB565(255, 255, 255)); 88 | 89 | // Re-plot text under needle 90 | ST7789_print( 104, 70, RGB565(200, 200, 200) , RGB565(255, 255, 255) , 1, &Font_11x18, 1, "%RH" ); // надпись по середине индикатора 91 | 92 | // Store new needle end coords for next erase 93 | ltx = tx; 94 | osx = sx * 98 + 120; 95 | osy = sy * 98 + 140; 96 | 97 | // Draw the needle in the new postion, magenta makes needle a bit bolder 98 | // draws 3 lines to thicken needle 99 | // рисуем стрелку циферблата 100 | ST7789_DrawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, RGB565(255, 0, 0)); 101 | ST7789_DrawLine(120 + 20 * ltx, 140 - 20, osx, osy, RGB565(255, 50, 50)); 102 | ST7789_DrawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, RGB565(255, 0, 0)); 103 | 104 | // Slow needle down slightly as it approaches new postion 105 | if (abs(old_analog - value) < 10){ 106 | ms_delay += ms_delay / 5; 107 | } 108 | 109 | // Wait before next update 110 | HAL_Delay (ms_delay); 111 | } 112 | } 113 | 114 | // ######################################################################### 115 | // рисуем сам циферблат ( вызываем функцию 1 раз в начале ) 116 | // ######################################################################### 117 | void analogMeter(void) 118 | { 119 | // размер всего окна 240 на 126 120 | // Meter outline 121 | ST7789_FillRect(0, 0, 240, 126, RGB565(80, 80, 80) ); // первичная ( внешняя ) рамка циферблата 122 | ST7789_FillRect(5, 3, 230, 120, RGB565(255, 255, 255) ); // внутренее поле циферблата 123 | 124 | // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing) 125 | for (int i = -50; i < 51; i += 5) { 126 | // Long scale tick length 127 | int tl = 15; 128 | 129 | // Coodinates of tick to draw 130 | float sx = cos((i - 90) * 0.0174532925); 131 | float sy = sin((i - 90) * 0.0174532925); 132 | uint16_t x0 = sx * (100 + tl) + 120; 133 | uint16_t y0 = sy * (100 + tl) + 140; 134 | uint16_t x1 = sx * 100 + 120; 135 | uint16_t y1 = sy * 100 + 140; 136 | 137 | // Coordinates of next tick for zone fill 138 | float sx2 = cos((i + 5 - 90) * 0.0174532925); 139 | float sy2 = sin((i + 5 - 90) * 0.0174532925); 140 | int x2 = sx2 * (100 + tl) + 120; 141 | int y2 = sy2 * (100 + tl) + 140; 142 | int x3 = sx2 * 100 + 120; 143 | int y3 = sy2 * 100 + 140; 144 | 145 | // Yellow zone limits 146 | //if (i >= -50 && i < 0) { 147 | // ST7789_DrawFilledTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW); 148 | // ST7789_DrawFilledTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW); 149 | //} 150 | 151 | // Green zone limits зона зеленая 152 | if (i >= 0 && i < 25) { 153 | ST7789_DrawFilledTriangle(x0, y0, x1, y1, x2, y2, RGB565(100, 255, 100) ); 154 | ST7789_DrawFilledTriangle(x1, y1, x2, y2, x3, y3, RGB565(100, 255, 100) ); 155 | } 156 | 157 | // Orange zone limits зона красная 158 | if (i >= 25 && i < 50) { 159 | ST7789_DrawFilledTriangle(x0, y0, x1, y1, x2, y2, RGB565(255, 100, 100) ); 160 | ST7789_DrawFilledTriangle(x1, y1, x2, y2, x3, y3, RGB565(255, 100, 100) ); 161 | } 162 | 163 | // Short scale tick length 164 | if (i % 25 != 0){ 165 | tl = 8; 166 | } 167 | 168 | // Recalculate coords incase tick lenght changed 169 | x0 = sx * (100 + tl) + 120; 170 | y0 = sy * (100 + tl) + 140; 171 | x1 = sx * 100 + 120; 172 | y1 = sy * 100 + 140; 173 | 174 | // Draw tick линии и цвет делений между значениями циферблата 175 | ST7789_DrawLine(x0, y0, x1, y1, RGB565(0, 0, 0) ); 176 | 177 | // Check if labels should be drawn, with position tweaks 178 | if (i % 25 == 0) { 179 | // Calculate label positions 180 | x0 = sx * (100 + tl + 10) + 120; 181 | y0 = sy * (100 + tl + 10) + 140; 182 | 183 | // печать цифр индикатора 184 | switch (i / 25) { 185 | case -2: 186 | ST7789_print( x0-9, y0 - 10, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "0" ); 187 | break; 188 | case -1: 189 | ST7789_print( x0-8, y0 - 7, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "25" ); 190 | break; 191 | case 0: 192 | ST7789_print( x0-7, y0 - 4, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "50" ); 193 | break; 194 | case 1: 195 | ST7789_print( x0-8, y0 - 7, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "75" ); 196 | break; 197 | case 2: 198 | ST7789_print( x0-9, y0 - 10, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "100" ); 199 | break; 200 | } 201 | } 202 | 203 | // Now draw the arc of the scale 204 | sx = cos((i + 5 - 90) * 0.0174532925); 205 | sy = sin((i + 5 - 90) * 0.0174532925); 206 | x0 = sx * 100 + 120; 207 | y0 = sy * 100 + 140; 208 | 209 | // Draw scale arc, don't draw the last part 210 | if (i < 50){ 211 | ST7789_DrawLine(x0, y0, x1, y1, RGB565(0, 0, 0) ); // рисуем дугу циферблата 212 | } 213 | } 214 | 215 | ST7789_print( 5 + 230 - 40, 119 - 20, RGB565(50, 150, 50) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "%RH" ); // надпись в провам нижнем углу 216 | ST7789_DrawRectangle(6, 4, 233, 121, RGB565(0, 0, 0) ); // тоненькая рамка индикатора 217 | 218 | plotNeedle(0, 0); // Put meter needle at 0 219 | } 220 | 221 | 222 | 223 | 224 | 225 | 226 | // ######################################################################### 227 | // рисуем вертикальную шкалу ( значение для показа от 0 до 100 ) 228 | // первый параметр название шкалы ( например "A1" ) 229 | // второй параметр координата х ( ширина шкалы 40 ) тоесть следующую шкалу рисуем х + 40 230 | // третий параметр координата у 231 | // ######################################################################### 232 | void plotLinear(char *label, int x, int y) 233 | { 234 | int w = 36; 235 | ST7789_DrawRectangle(x, y, x + w, y + 155, RGB565(150, 150, 150)); // внешняя тонкая рамка 236 | ST7789_FillRect(x + 2, y + 19, w - 3, 155 - 38, RGB565(255, 255, 255)); // фон самого индикатора 237 | ST7789_print( x + w / 2 - 15, y + 3, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, label ); // вывод надписи над индикатором 238 | 239 | // рисуем короткие линии на индикаторе 240 | for (int i = 0; i < 110; i += 10) 241 | { 242 | ST7789_DrawLine(x + 20, y + 27 + i, x + 20 + 5, y + 27 + i, RGB565(0, 0, 0)); 243 | } 244 | // рисуем длинные линии на индикаторе 245 | for (int i = 0; i < 110; i += 50) 246 | { 247 | ST7789_DrawLine(x + 20, y + 27 + i, x + 20 + 11, y + 27 + i, RGB565(0, 0, 0)); 248 | } 249 | 250 | // рисуем стрелки индикатора 251 | ST7789_DrawFilledTriangle(x + 3, y + 127, x + 3 + 16, y + 127, x + 3, y + 127 - 5, RGB565(255, 0, 0) ); 252 | ST7789_DrawFilledTriangle(x + 3, y + 127, x + 3 + 16, y + 127, x + 3, y + 127 + 5, RGB565(255, 0, 0) ); 253 | 254 | ST7789_print( x + w / 2 - 15, y + 155 - 16, RGB565(50, 150, 50) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, "----" ); 255 | } 256 | 257 | // ######################################################################### 258 | // функция опрашивает массив с данными и выводит их на экран 259 | // ######################################################################### 260 | void plotPointer(void) 261 | { 262 | int x = 0; // устанавливаем смещение начального индикатора относительно х 263 | int y = 10; // устанавливаем смещение начального индикатора относительно у 264 | int count = 6; // устанавливаем кол-во индикаторов от 1 до 6 265 | 266 | int dy = 0; 267 | uint8_t pw = 16; 268 | 269 | // указываем кол-во индикаторов 270 | for (int i = 0; i < count; i++) 271 | { 272 | // формеруем и печатаем текущее значение в левом нижнем углу циферблата 273 | char buff_value[5]; // ставим на +1 чем нужно для \0 274 | sprintf( buff_value, "% 4d", value[i] ); // 4 знакоместа выравнивание по правому краю 275 | 276 | // выводим в низу индикатора данные с массивов 277 | ST7789_print( i * 40 + x + 36/2 -15, y + 27 - 27 + 155 - 16, RGB565(0, 0, 0) , RGB565(255, 255, 255) , 1, &Font_7x9, 1, buff_value ); 278 | 279 | int dx = 3 + 40 * i; 280 | // проверка на границы данных 281 | if (value[i] < 0){ 282 | value[i] = 0; // Limit value to emulate needle end stops 283 | } 284 | if (value[i] > 100){ 285 | value[i] = 100; 286 | } 287 | 288 | while (!(value[i] == old_value[i])) { 289 | dy = 27 + y + 100 - old_value[i]; 290 | if (old_value[i] > value[i]) 291 | { 292 | ST7789_DrawLine(x + dx, dy - 5, x + dx + pw, dy, RGB565(255, 255, 255)); 293 | old_value[i]--; 294 | ST7789_DrawLine(x + dx, dy + 6, x + dx + pw, dy + 1, RGB565(255, 0, 0)); 295 | } 296 | else 297 | { 298 | ST7789_DrawLine(x + dx, dy + 5, x + dx + pw, dy, RGB565(255, 255, 255)); 299 | old_value[i]++; 300 | ST7789_DrawLine(x + dx, dy - 6, x + dx + pw, dy - 1, RGB565(255, 0, 0)); 301 | } 302 | } 303 | } 304 | } 305 | 306 | //---------------------------------------------------------------------------------- 307 | 308 | /************************ (C) COPYRIGHT GKP *****END OF FILE****/ 309 | -------------------------------------------------------------------------------- /st7789/st7789.h: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | * @file ( фаил ): ST7789.h 4 | * @brief ( описание ): 5 | ****************************************************************************** 6 | * @attention ( внимание ): author: Golinskiy Konstantin e-mail: golinskiy.konstantin@gmail.com 7 | ****************************************************************************** 8 | 9 | */ 10 | 11 | 12 | #ifndef _ST7789_H 13 | #define _ST7789_H 14 | 15 | 16 | /* C++ detection */ 17 | #ifdef __cplusplus 18 | extern C { 19 | #endif 20 | 21 | // Обязательно нужен #include "main.h" 22 | // чтоб отдельно не подключать файлы связанные с МК и стандартными библиотеками 23 | 24 | #include "main.h" 25 | #include "fonts.h" 26 | 27 | #include "stdlib.h" 28 | #include "string.h" 29 | #include "math.h" 30 | 31 | 32 | 33 | //####### SETUP ############################################################################################## 34 | 35 | //==== выбераем через что будем отправлять через HAL или CMSIS(быстрее) ================== 36 | //-- нужное оставляем другое коментируем ( важно должно быть только один выбран )--------- 37 | 38 | // указываем порт SPI для CMSIS ( быстро )------- 39 | // так как у разных МК разные регистры то в функциях корректируем под свой МК 40 | // на данный момент есть реализация на серию F1 F4 H7 для выбора серии в функциях 41 | // void ST7789_SendCmd(uint8_t Cmd); 42 | // void ST7789_SendData(uint8_t Data ); 43 | // void ST7789_SendDataMASS(uint8_t* buff, size_t buff_size); 44 | // комментируем и раскомментируем то что нам нужно, также там же редактируем под свой МК если не работает 45 | //#define ST7789_SPI_CMSIS SPI2 46 | //----------------------------------------------- 47 | 48 | // указываем порт SPI для HAL ( медлено )-------- 49 | #define ST7789_SPI_HAL hspi1 50 | //----------------------------------------------- 51 | 52 | //============================================================================ 53 | 54 | // выбираем как выводить информацию через буфер кадра или попиксельно ( 1-буфер кадра, 0-попиксельный вывод ) ----- 55 | // через буфер быстре если много информации обнавлять за один раз ( требует много оперативки для массива ) 56 | // по пиксельно рисует онлайн буз буферра если информация обновляеться немного то выгодно испотзовать данный режим 57 | #define FRAME_BUFFER 0 58 | //----------------------------------------------------------------------------------------------------------------- 59 | 60 | 61 | //=== указываем порты ( если в кубе назвали их DC RES CS то тогда нечего указывать не нужно ) 62 | #if defined (DC_GPIO_Port) 63 | #else 64 | #define DC_GPIO_Port GPIOC 65 | #define DC_Pin GPIO_PIN_5 66 | #endif 67 | 68 | #if defined (RST_GPIO_Port) 69 | #else 70 | #define RST_GPIO_Port GPIOB 71 | #define RST_Pin GPIO_PIN_14 72 | #endif 73 | 74 | //-- Cесли используем порт CS для выбора устройства тогда раскомментировать ------------ 75 | // если у нас одно устройство лучше пин CS притянуть к земле( или на порту подать GND ) 76 | 77 | #define CS_PORT 78 | 79 | //---------------------------------------------------------------------------------------- 80 | #ifdef CS_PORT 81 | #if defined (CS_GPIO_Port) 82 | #else 83 | #define CS_GPIO_Port GPIOB 84 | #define CS_Pin GPIO_PIN_12 85 | #endif 86 | #endif 87 | 88 | //============================================================================= 89 | 90 | //== выбираем дисплей: ======================================================= 91 | //-- нужное оставляем другое коментируем ( важно должно быть только один выбран )--------- 92 | 93 | //#define ST7789_IS_76X284 // 2.25" 76 x 284 ST7789 94 | //#define ST7789_IS_135X240 // 1.14" 135 x 240 ST7789 95 | #define ST7789_IS_240X240 // 1.3" 240 x 240 ST7789 96 | //#define ST7789_IS_172X320 // 1.47" 172 x 320 ST7789 97 | //#define ST7789_IS_240X280 // 1.69" 240 x 280 ST7789 98 | //#define ST7789_IS_240X320 // 2" 240 x 320 ST7789 99 | 100 | //============================================================================= 101 | 102 | 103 | //############################################################################################################## 104 | 105 | #ifdef ST7789_SPI_HAL 106 | extern SPI_HandleTypeDef ST7789_SPI_HAL; 107 | #endif 108 | 109 | extern uint16_t ST7789_Width, ST7789_Height; 110 | 111 | extern uint16_t ST7789_X_Start; 112 | extern uint16_t ST7789_Y_Start; 113 | 114 | #define RGB565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)) 115 | 116 | #define PI 3.14159265 117 | 118 | //--- готовые цвета ------------------------------ 119 | #define ST7789_BLACK 0x0000 120 | #define ST7789_BLUE 0x001F 121 | #define ST7789_RED 0xF800 122 | #define ST7789_GREEN 0x07E0 123 | #define ST7789_CYAN 0x07FF 124 | #define ST7789_MAGENTA 0xF81F 125 | #define ST7789_YELLOW 0xFFE0 126 | #define ST7789_WHITE 0xFFFF 127 | //------------------------------------------------ 128 | 129 | //-- Битовые маски настройки цветности ST7789 ---- 130 | #define ST7789_ColorMode_65K 0x50 131 | #define ST7789_ColorMode_262K 0x60 132 | #define ST7789_ColorMode_12bit 0x03 133 | #define ST7789_ColorMode_16bit 0x05 134 | #define ST7789_ColorMode_18bit 0x06 135 | #define ST7789_ColorMode_16M 0x07 136 | //------------------------------------------------ 137 | 138 | #define ST7789_MADCTL_MY 0x80 139 | #define ST7789_MADCTL_MX 0x40 140 | #define ST7789_MADCTL_MV 0x20 141 | #define ST7789_MADCTL_ML 0x10 142 | #define ST7789_MADCTL_RGB 0x00 143 | #define ST7789_MADCTL_BGR 0x08 144 | #define ST7789_MADCTL_MH 0x04 145 | //------------------------------------------------- 146 | 147 | 148 | #define ST7789_SWRESET 0x01 149 | #define ST7789_SLPIN 0x10 150 | #define ST7789_SLPOUT 0x11 151 | #define ST7789_NORON 0x13 152 | #define ST7789_INVOFF 0x20 153 | #define ST7789_INVON 0x21 154 | #define ST7789_DISPOFF 0x28 155 | #define ST7789_DISPON 0x29 156 | #define ST7789_CASET 0x2A 157 | #define ST7789_RASET 0x2B 158 | #define ST7789_RAMWR 0x2C 159 | #define ST7789_COLMOD 0x3A 160 | #define ST7789_MADCTL 0x36 161 | //----------------------------------------------- 162 | 163 | #define DELAY 0x80 164 | 165 | 166 | //### параметры дисплея 1.3" 240 x 240 ST7789 ################################### 167 | 168 | // 1.3" 240 x 240 ST7789 display, default orientation 169 | 170 | #ifdef ST7789_IS_240X240 171 | 172 | #define ST7789_WIDTH 240 173 | #define ST7789_HEIGHT 240 174 | #define ST7789_XSTART 0 175 | #define ST7789_YSTART 0 176 | #define ST7789_ROTATION (ST7789_MADCTL_RGB) 177 | #define ST7789_INVERSION ST7789_INVON 178 | 179 | #endif 180 | 181 | //############################################################################## 182 | 183 | //############################################################################## 184 | 185 | //### параметры дисплея 2.25" 76 x 284 ST7789 ################################### 186 | 187 | // 2.25" 76 x 284 ST7789 display, default orientation 188 | 189 | #ifdef ST7789_IS_76X284 190 | 191 | #define ST7789_WIDTH 76 192 | #define ST7789_HEIGHT 284 193 | #define ST7789_XSTART 82 194 | #define ST7789_YSTART 18 195 | #define ST7789_ROTATION (ST7789_MADCTL_RGB) 196 | #define ST7789_INVERSION ST7789_INVOFF 197 | 198 | #endif 199 | 200 | //############################################################################## 201 | 202 | //############################################################################## 203 | 204 | //### параметры дисплея 1.14" 135 x 240 ST7789 ################################### 205 | 206 | // 1.14" 135 x 240 ST7789 display, default orientation 207 | 208 | #ifdef ST7789_IS_135X240 209 | 210 | #define ST7789_WIDTH 135 211 | #define ST7789_HEIGHT 240 212 | #define ST7789_XSTART 52 213 | #define ST7789_YSTART 40 214 | #define ST7789_ROTATION (ST7789_MADCTL_RGB) 215 | #define ST7789_INVERSION ST7789_INVON 216 | 217 | #endif 218 | 219 | //############################################################################## 220 | 221 | 222 | //############################################################################## 223 | 224 | 225 | //### параметры дисплея 1.47" 172 x 320 ST7789 ################################### 226 | 227 | // 1.47" 172 x 320 ST7789 display, default orientation 228 | 229 | #ifdef ST7789_IS_172X320 230 | 231 | #define ST7789_WIDTH 320 232 | #define ST7789_HEIGHT 172 233 | #define ST7789_XSTART 0 234 | #define ST7789_YSTART 34 235 | #define ST7789_ROTATION (ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB) 236 | #define ST7789_INVERSION ST7789_INVON 237 | 238 | #endif 239 | 240 | //############################################################################## 241 | 242 | 243 | //############################################################################## 244 | 245 | 246 | //### параметры дисплея 1.69" 240 x 280 ST7789 ################################### 247 | 248 | // 1.69" 240 x 280 ST7789 display, default orientation 249 | 250 | #ifdef ST7789_IS_240X280 251 | 252 | #define ST7789_WIDTH 240 253 | #define ST7789_HEIGHT 280 254 | #define ST7789_XSTART 0 255 | #define ST7789_YSTART 20 256 | #define ST7789_ROTATION (ST7789_MADCTL_RGB) 257 | #define ST7789_INVERSION ST7789_INVON 258 | 259 | #endif 260 | 261 | //############################################################################## 262 | 263 | 264 | //############################################################################## 265 | 266 | 267 | //### параметры дисплея 2" 240 x 320 ST7789 ################################### 268 | 269 | // 2" 240 x 320 ST7789 display, default orientation 270 | 271 | #ifdef ST7789_IS_240X320 272 | 273 | #define ST7789_WIDTH 240 274 | #define ST7789_HEIGHT 320 275 | #define ST7789_XSTART 0 276 | #define ST7789_YSTART 0 277 | #define ST7789_ROTATION (ST7789_MADCTL_RGB) 278 | #define ST7789_INVERSION ST7789_INVON 279 | 280 | #endif 281 | 282 | //############################################################################## 283 | //############################################################################## 284 | 285 | 286 | void ST7789_Init(void); 287 | void ST7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data); 288 | void ST7789_HardReset(void); 289 | void ST7789_SleepModeEnter( void ); 290 | void ST7789_SleepModeExit( void ); 291 | void ST7789_ColorModeSet(uint8_t ColorMode); 292 | void ST7789_MemAccessModeSet(uint8_t Rotation, uint8_t VertMirror, uint8_t HorizMirror, uint8_t IsBGR); 293 | void ST7789_InversionMode(uint8_t Mode); 294 | void ST7789_FillScreen(uint16_t color); 295 | void ST7789_Clear(void); 296 | void ST7789_FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 297 | void ST7789_SetBL(uint8_t Value); 298 | void ST7789_DisplayPower(uint8_t On); 299 | void ST7789_DrawRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); 300 | void ST7789_DrawRectangleFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t fillcolor); 301 | void ST7789_DrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); 302 | void ST7789_DrawLineWithAngle(int16_t x, int16_t y, uint16_t length, double angle_degrees, uint16_t color); 303 | void ST7789_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color); 304 | void ST7789_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color); 305 | void ST7789_DrawPixel(int16_t x, int16_t y, uint16_t color); 306 | void ST7789_DrawCircleFilled(int16_t x0, int16_t y0, int16_t radius, uint16_t fillcolor); 307 | void ST7789_DrawCircle(int16_t x0, int16_t y0, int16_t radius, uint16_t color); 308 | void ST7789_DrawEllipse(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, uint16_t color); 309 | void ST7789_DrawEllipseFilled(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, uint16_t color); 310 | void ST7789_DrawEllipseFilledWithAngle(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, float angle_degrees, uint16_t color); 311 | void ST7789_DrawEllipseWithAngle(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, float angle_degrees, uint16_t color); 312 | void ST7789_DrawChar(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, unsigned char ch); 313 | void ST7789_DrawCharWithAngle(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, double angle_degrees, unsigned char ch); 314 | void ST7789_print(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, char *str); 315 | void ST7789_printWithAngle(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, double angle_degrees, char *str); 316 | void ST7789_rotation( uint8_t rotation ); 317 | void ST7789_DrawBitmap(int16_t x, int16_t y, const unsigned char* bitmap, int16_t w, int16_t h, uint16_t color); 318 | void ST7789_DrawBitmapWithAngle(int16_t x, int16_t y, const unsigned char* bitmap, int16_t w, int16_t h, uint16_t color, double angle_degrees); 319 | void ST7789_DrawCircleHelper(int16_t x0, int16_t y0, int16_t radius, int8_t quadrantMask, uint16_t color); 320 | void ST7789_DrawFillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta, uint16_t color); 321 | void ST7789_DrawFillRoundRect(int16_t x, int16_t y, uint16_t width, uint16_t height, int16_t cornerRadius, uint16_t color); 322 | void ST7789_DrawRoundRect(int16_t x, int16_t y, uint16_t width, uint16_t height, int16_t cornerRadius, uint16_t color); 323 | void ST7789_DrawArc(int16_t x0, int16_t y0, int16_t radius, int16_t startAngle, int16_t endAngle, uint16_t color, uint8_t thick); 324 | void ST7789_DrawLineThick(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color, uint8_t thick); 325 | void ST7789_DrawLineThickWithAngle(int16_t x, int16_t y, int16_t length, double angle_degrees, uint16_t color, uint8_t thick); 326 | 327 | #if FRAME_BUFFER 328 | void ST7789_Update(void); 329 | void ST7789_ClearFrameBuffer(void); 330 | #endif 331 | 332 | 333 | /* C++ detection */ 334 | #ifdef __cplusplus 335 | } 336 | #endif 337 | 338 | #endif /* _ST7789_H */ 339 | 340 | /************************ (C) COPYRIGHT GKP *****END OF FILE****/ 341 | -------------------------------------------------------------------------------- /st7789/example.txt: -------------------------------------------------------------------------------- 1 | /* сохраняем данный файл в кодировке UTF-8 */ 2 | 3 | 4 | author: Golinskiy Konstantin e-mail: golinskiy.konstantin@gmail.com 5 | 6 | 7 | //=================================================== 8 | 9 | //----- SPI2 parameter configuration ---------------------------------------- 10 | 11 | // SPI включаем только передача ( MOSI SCK ) 12 | // настройка SPI, скорость максимальная, 1 Line (TX only), Polarity High, Phase 2Edge: 13 | // частота SPI должна быть меньше 50 МГц 14 | 15 | hspi2.Instance = SPI2; 16 | hspi2.Init.Mode = SPI_MODE_MASTER; 17 | hspi2.Init.Direction = SPI_DIRECTION_2LINES; 18 | hspi2.Init.DataSize = SPI_DATASIZE_8BIT; 19 | hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; 20 | hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; 21 | hspi2.Init.NSS = SPI_NSS_SOFT; 22 | hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; 23 | hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; 24 | hspi2.Init.TIMode = SPI_TIMODE_DISABLE; 25 | hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; 26 | hspi2.Init.CRCPolynomial = 7; 27 | 28 | //----------------------------------------------------------------------------- 29 | 30 | 31 | 32 | в файле fonts.h нужно выбрать шрифты: 33 | 34 | //---- для экономии памяти шрифты которые не используються закоментировать ------------------------------------- 35 | // Шрифт имеет кирилицу и латиницу 36 | #define FONT_6x8 // 6 x 8 pixels font size structure 37 | #define FONT_7x9 // 7 x 9 pixels font size structure 38 | #define FONT_11x18 // 11 x 18 pixels font size structure 39 | #define FONT_16x26 // 16 x 26 pixels font size structure 40 | // Только цифры -- only numbers 41 | #define FONT_16x28 // 16 x 28 pixels font size structure only numbers 42 | //-------------------------------------------------------------------------------------------------------------- 43 | 44 | в файле ST7789.h указываем настройки: 45 | 46 | //####### SETUP ############################################################################################## 47 | 48 | //==== выбераем через что будем отправлять через HAL или CMSIS(быстрее) ================== 49 | //-- нужное оставляем другое коментируем ( важно должно быть только один выбран )--------- 50 | 51 | // указываем порт SPI для CMSIS ( быстро )------- 52 | // так как у разных МК разные регистры то в функциях корректируем под свой МК 53 | // на данный момент есть реализация на серию F1 F4 H7 для выбора серии в функциях 54 | // void ST7789_SendCmd(uint8_t Cmd); 55 | // void ST7789_SendData(uint8_t Data ); 56 | // void ST7789_SendDataMASS(uint8_t* buff, size_t buff_size); 57 | // комментируем и раскомментируем то что нам нужно, также там же редактируем под свой МК если не работает 58 | #define ST7789_SPI_CMSIS SPI2 59 | //----------------------------------------------- 60 | 61 | // указываем порт SPI для HAL ( медлено )-------- 62 | //#define ST7789_SPI_HAL hspi2 63 | //----------------------------------------------- 64 | 65 | //============================================================================ 66 | 67 | // выбираем как выводить информацию через буфер кадра или попиксельно ( 1-буфер кадра, 0-попиксельный вывод ) ----- 68 | // через буфер быстре если много информации обнавлять за один раз ( требует много оперативки для массива ) 69 | // по пиксельно рисует онлайн буз буферра если информация обновляеться немного то выгодно испотзовать данный режим 70 | #define FRAME_BUFFER 0 71 | //----------------------------------------------------------------------------------------------------------------- 72 | 73 | //=== указываем порты ( если в кубе назвали их DC RES CS то тогда нечего указывать не нужно ) 74 | #if defined (DC_GPIO_Port) 75 | #else 76 | #define DC_GPIO_Port GPIOA 77 | #define DC_Pin GPIO_PIN_11 78 | #endif 79 | 80 | #if defined (RES_GPIO_Port) 81 | #else 82 | #define RES_GPIO_Port GPIOA 83 | #define RES_Pin GPIO_PIN_12 84 | #endif 85 | 86 | //-- Cесли используем порт CS для выбора устройства тогда раскомментировать ------------ 87 | // если у нас одно устройство лучше пин CS притянуть к земле( или на порту подать GND ) 88 | 89 | //#define CS_PORT 90 | 91 | //---------------------------------------------------------------------------------------- 92 | #ifdef CS_PORT 93 | #if defined (CS_GPIO_Port) 94 | #else 95 | #define CS_GPIO_Port GPIOA 96 | #define CS_Pin GPIO_PIN_14 97 | #endif 98 | #endif 99 | 100 | //============================================================================= 101 | 102 | //== выбираем дисплей: ======================================================= 103 | //-- нужное оставляем другое коментируем ( важно должно быть только один выбран )--------- 104 | 105 | //#define ST7789_IS_135X240 // 1.14" 135 x 240 ST7789 106 | #define ST7789_IS_240X240 // 1.3" 240 x 240 ST7789 107 | //#define ST7789_IS_240X320 // 2" 240 x 320 ST7789 108 | 109 | //============================================================================= 110 | 111 | 112 | //############################################################################################################## 113 | 114 | 115 | 116 | 117 | 118 | //========================================================= 119 | 120 | 121 | #include 122 | 123 | #include "bitmap.h" 124 | #include "fonts.h" 125 | 126 | 127 | #include "stdio.h" 128 | ......... 129 | ......... 130 | 131 | main()============================================================================================================================= 132 | 133 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 134 | 135 | // включаем подсветку дисплея BLK 136 | HAL_GPIO_WritePin( BLK_GPIO_Port, BLK_Pin, GPIO_PIN_SET ); 137 | 138 | // Процедура инициализации дисплея ST7789 139 | ST7789_Init(); 140 | 141 | // установка ротации дисплея не обязательно так как по умолчанию стоит режим 1 ( всего 4 режима 1,2,3,4 ) 142 | ST7789_rotation( 1 ); 143 | 144 | // очистка только буфера кадра ( при етом сам экран не очищаеться ) 145 | // #if FRAME_BUFFER // если включен буфер кадра 146 | // ST7789_ClearFrameBuffer(); 147 | // #endif 148 | 149 | // закрашиваем весь экран указаным цветом 150 | ST7789_FillScreen( RGB565(255, 0, 0) ); 151 | //#if FRAME_BUFFER // если включен буфер кадра 152 | // ST7789_Update(); 153 | //#endif 154 | HAL_Delay (2000); 155 | // закрашиваем весь экран указаным цветом 156 | ST7789_FillScreen( RGB565(0, 255, 0) ); 157 | //#if FRAME_BUFFER // если включен буфер кадра 158 | // ST7789_Update(); 159 | //#endif 160 | HAL_Delay (2000); 161 | // закрашиваем весь экран указаным цветом 162 | ST7789_FillScreen( RGB565(0, 0, 255) ); 163 | //#if FRAME_BUFFER // если включен буфер кадра 164 | // ST7789_Update(); 165 | //#endif 166 | HAL_Delay (2000); 167 | 168 | // прямоугольник закрашеный ( координата X и Y ( начиная с 0 ) ширина и высота в пикселях ) 169 | ST7789_DrawRectangleFilled(0, 0, 240, 240, RGB565(255, 255, 255)) ; 170 | //#if FRAME_BUFFER // если включен буфер кадра 171 | // ST7789_Update(); 172 | //#endif 173 | HAL_Delay (1000); 174 | 175 | for( uint8_t i = 0; i< 240; i+=3){ 176 | // прямоугольник закрашеный ( координата X и Y ( начиная с 0 ) ширина и высота в пикселях ) 177 | ST7789_DrawRectangleFilled(i, i, 240-i, 240-i, RGB565(i/2, 255-i, 0+i)) ; 178 | } 179 | //#if FRAME_BUFFER // если включен буфер кадра 180 | // ST7789_Update(); 181 | //#endif 182 | 183 | for( uint8_t i = 0; i< 120; i+=3){ 184 | // прямоугольник пустотелый ( координата X и Y ( начиная с 0 ) ширина и высота в пикселях ) 185 | ST7789_DrawRectangle(i, i, 240-i, 240-i, RGB565(255, 0, 0)) ; 186 | } 187 | //#if FRAME_BUFFER // если включен буфер кадра 188 | // ST7789_Update(); 189 | //#endif 190 | 191 | HAL_Delay (2000); 192 | 193 | 194 | // рисуем цветную иконку. параметры координаты х и у ( начиная с 0 ), размер иконки шир и выс, имя иконки ( массив ) 195 | // ST7789_DrawImage( 80, 80, 85, 53, logoRGB ); 196 | //#if FRAME_BUFFER // если включен буфер кадра 197 | // ST7789_Update(); 198 | //#endif 199 | 200 | // закрашиваем весь экран указаным цветом 201 | ST7789_FillScreen( RGB565(0, 10, 100) ); 202 | //#if FRAME_BUFFER // если включен буфер кадра 203 | // ST7789_Update(); 204 | //#endif 205 | 206 | // печатаем символ ( один ) параметры: х, у, ( начиная с 0 ), цвет символа, цвет фона, вкл/выкл фон, размер шрифта, множитель шрифта (увеличивает в х раз шрифт ), сам символ ( поддерживает кириллицу ) 207 | // ST7789_DrawChar( 20, 20, RGB565( 255, 255, 255 ) , RGB565( 0, 10, 10 ) , 0, &Font_16x26, 3, 'F' ); 208 | //#if FRAME_BUFFER // если включен буфер кадра 209 | // ST7789_Update(); 210 | //#endif 211 | 212 | // печатаем строку параметры: х, у, ( начиная с 0 ), цвет строки, цвет фона, вкл/выкл фон, размер шрифта, множитель шрифта (увеличивает в х раз шрифт ), сама строка ( поддерживает кириллицу ) 213 | ST7789_print( 50, 20, RGB565(255, 255, 255) , RGB565(0, 10, 100) , 1, &Font_16x26, 1, "STM32 TFT" ); 214 | //#if FRAME_BUFFER // если включен буфер кадра 215 | // ST7789_Update(); 216 | //#endif 217 | 218 | // печатаем строку параметры: х, у, ( начиная с 0 ), цвет строки, цвет фона, вкл/выкл фон, размер шрифта, множитель шрифта (увеличивает в х раз шрифт ), сама строка ( поддерживает кириллицу ) 219 | ST7789_print( 10, 160, RGB565(255, 0, 0) , RGB565(0, 10, 100) , 1, &Font_11x18, 1, "Классный дисплей !!!" ); 220 | //#if FRAME_BUFFER // если включен буфер кадра 221 | // ST7789_Update(); 222 | //#endif 223 | 224 | // печатаем строку параметры: х, у, ( начиная с 0 ), цвет строки, цвет фона, вкл/выкл фон, размер шрифта, множитель шрифта (увеличивает в х раз шрифт ), сама строка ( поддерживает кириллицу ) 225 | ST7789_print( 8, 200, RGB565(0, 255, 0) , RGB565(0, 10, 100) , 1, &Font_7x9, 2, "ST7789 : 240x320" ); 226 | //#if FRAME_BUFFER // если включен буфер кадра 227 | // ST7789_Update(); 228 | //#endif 229 | 230 | // печатаем символ с указаным углом, параметры: х, у, ( начиная с 0 ), цвет строки, цвет фона, вкл/выкл фон, размер шрифта, множитель шрифта (увеличивает в х раз шрифт ), угол поворота (0.0 - 360.0), самсимвол ( поддерживает кириллицу ) 231 | ST7789_DrawCharWithAngle( 50, 50, RGB565(255, 255, 255) , RGB565(0, 10, 100) , 1, &Font_11x18, 1, 90.0, 'R' ); 232 | //#if FRAME_BUFFER // если включен буфер кадра 233 | // ST7789_Update(); 234 | //#endif 235 | 236 | // печатаем строку с указаным углом, параметры: х, у, ( начиная с 0 ), цвет строки, цвет фона, вкл/выкл фон, размер шрифта, множитель шрифта (увеличивает в х раз шрифт ), угол поворота (0.0 - 360.0), сама строка ( поддерживает кириллицу ) 237 | ST7789_printWithAngle( 100, 100, RGB565(255, 255, 255) , RGB565(0, 10, 100) , 1, &Font_11x18, 1, 180.0, "STM32 TFT" ); 238 | //#if FRAME_BUFFER // если включен буфер кадра 239 | // ST7789_Update(); 240 | //#endif 241 | 242 | // рисуем цветную иконку. параметры координаты х и у ( начиная с 0 ), размер иконки шир и выс, имя иконки ( массив ) 243 | ST7789_DrawImage( 0, 0, 85, 53, logoRGB ); 244 | //#if FRAME_BUFFER // если включен буфер кадра 245 | // ST7789_Update(); 246 | //#endif 247 | 248 | // очистка экрана - закрашивает экран цветом черный 249 | //ST7789_Clear(); 250 | // очистка только буфера кадра ( при етом сам экран не очищаеться ) 251 | // #if FRAME_BUFFER // если включен буфер кадра 252 | // ST7789_ClearFrameBuffer(); 253 | // #endif 254 | 255 | // рисуем монохромную иконку. параметры координаты х и у ( начиная с 0 ), имя иконки ( массив ), размер иконки шир и выс, цвет отображения 256 | //ST7789_DrawBitmap( 60, 200, logo, 128, 27, RGB565(255, 0, 0) ); 257 | //#if FRAME_BUFFER // если включен буфер кадра 258 | // ST7789_Update(); 259 | //#endif 260 | 261 | // рисуем монохромную иконку с указаным углом поворота, параметры координаты х и у ( начиная с 0 ), имя иконки ( массив ), размер иконки шир и выс, цвет отображения, угол поворота (0-360) 262 | ST7789_DrawBitmapWithAngle( 60, 150, logo, 128, 27, RGB565(255, 255, 255), 10.0 ); 263 | //#if FRAME_BUFFER // если включен буфер кадра 264 | // ST7789_Update(); 265 | //#endif 266 | 267 | // очистка экрана - закрашивает экран цветом черный 268 | //ST7789_Clear(); 269 | 270 | // круг пустотелый 271 | //ST7789_DrawCircle(50, 100, 50, RGB565(255, 0, 255)); 272 | //#if FRAME_BUFFER // если включен буфер кадра 273 | // ST7789_Update(); 274 | //#endif 275 | 276 | // круг закрашеный 277 | //ST7789_DrawCircleFilled(50, 290, 20, RGB565(255, 40, 255)) ; 278 | 279 | // рисуем элипс ( координаты центра, радиус по Х радиус по У, цвет ) 280 | ST7789_DrawEllipse( 150, 150, 20, 80, RGB565(0, 0, 255) ); 281 | 282 | // рисуем элипс закрашенный ( координаты центра, радиус по Х радиус по У, цвет ) 283 | ST7789_DrawEllipseFilled( 150, 150, 80, 20, RGB565(0, 0, 255) ); 284 | 285 | // рисуем элипс под указаным углом наклона ( координаты центра, радиус по Х радиус по У, угол поворота (0-360), цвет ) 286 | ST7789_DrawEllipseWithAngle( 150, 150, 80, 20, 45.0, RGB565(0, 0, 255) ); 287 | 288 | // рисуем элипс закрашенный под указаным углом наклона ( координаты центра, радиус по Х радиус по У, угол поворота (0-360), цвет ) 289 | ST7789_DrawEllipseFilledWithAngle( 150, 150, 80, 20, 200.0, RGB565(0, 255, 0) ); 290 | 291 | // линия 292 | //ST7789_DrawLine(1, 319, 239, 319, RGB565(255, 255, 0)); 293 | 294 | // рисуем линию с указаным углом и длиной ( начальные координаты, длина линии, угол поворота (0-360), и цвет линии ) 295 | ST7789_DrawLineWithAngle(100, 100, 50, 45.0, RGB565(255, 255, 255)); 296 | 297 | // прямоугольник закрашеный 298 | //ST7789_DrawRectangleFilled(90, 265, 140, 310, RGB565(0, 255, 0)) ; 299 | 300 | // прямоугольник пустотелый 301 | //ST7789_DrawRectangle(160, 265, 220, 309, RGB565(255, 255, 255)) ; 302 | 303 | // рисуем треугольник пустотелый 304 | //ST7789_DrawTriangle(60, 40, 150, 100, 200, 200, RGB565(100, 255, 150) ); 305 | 306 | // рисуем треугольник закрашеный 307 | //ST7789_DrawFilledTriangle(20, 40, 150, 100, 200, 200, RGB565(100, 255, 150) ); 308 | 309 | // рисуем прямоугольник с закругленными краями ( закрашенный ) 310 | //ST7789_DrawFillRoundRect(10, 10, 50, 50, 10, RGB565(100, 255, 150)); 311 | 312 | // рисуем прямоугольник с закругленными краями ( пустотелый ) 313 | //ST7789_DrawRoundRect(10, 10, 50, 50, 10, RGB565(100, 255, 150)); 314 | 315 | // рисуем полукруг ( правое или левое полушарие (параметр 1 или 2) ) закрашенный 316 | //ST7789_DrawFillCircleHelper(30, 30, 20 , 1, 0, RGB565(100, 255, 150)); 317 | 318 | // рисуем дугу ( четверть круга (параметр 1, 2, 4, 8) ) шириной 1 пиксель 319 | //ST7789_DrawCircleHelper(30, 30, 20 , 1, RGB565(100, 255, 150)); 320 | //#if FRAME_BUFFER // если включен буфер кадра 321 | // ST7789_Update(); 322 | //#endif 323 | 324 | // переход в спящий режим 325 | //ST7789_SleepModeEnter(); 326 | 327 | // выход их спящего режима 328 | //ST7789_SleepModeExit(); 329 | 330 | // вкл/выкл дисплея 0-выкл 1- вкл 331 | //ST7789_DisplayPower( 1 ); 332 | 333 | // инверсия цветов 0-вкл 1-выкл 334 | //ST7789_InversionMode(1); 335 | 336 | // рисованиe дуга толстая ( часть круга ) ( координаты центра, радиус, начальный и конечный угол (0-360), цвет линии, толщина линии) 337 | // если нужно нарисовать наоборот другую часть то меняем начальный угол и конечный местами 338 | ST7789_DrawArc(100, 100, 50, 320, 220, RGB565(255, 255, 0), 5); 339 | ST7789_DrawArc(100, 100, 50, 220, 320, RGB565(255, 0, 255), 5); 340 | //#if FRAME_BUFFER // если включен буфер кадра 341 | // ST7789_Update(); 342 | //#endif 343 | 344 | // линия толстая ( последний параметр толшина ) 345 | ST7789_DrawLineThick(10, 120, 200, 140, RGB565(255, 255, 0), 5); 346 | //#if FRAME_BUFFER // если включен буфер кадра 347 | // ST7789_Update(); 348 | //#endif 349 | 350 | // линия толстая нужной длины и указаным углом поворота (0-360) ( последний параметр толшина ) 351 | ST7789_DrawLineThickWithAngle( 100, 100, 80, 90.0, RGB565(255, 255, 0), 10 ); 352 | //#if FRAME_BUFFER // если включен буфер кадра 353 | // ST7789_Update(); 354 | //#endif 355 | 356 | /////////////////////////////////////////////////////////////////////////////////////////////////// 357 | 358 | 359 | ......... 360 | ......... 361 | ......... 362 | 363 | while(1)=========================================================================================================================== 364 | 365 | ......... 366 | ......... 367 | ......... 368 | ......... 369 | 370 | === end while(1) ================================================================================================================== 371 | === end main() ==================================================================================================================== 372 | -------------------------------------------------------------------------------- /st7789/bitmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bitmap.h 3 | 4 | Онлайн генератор картинок при генерайии ставим галочку Invert image colors 5 | 6 | Online generator https://javl.github.io/image2cpp/ 7 | 8 | */ 9 | 10 | #ifndef BITMAP_H_ 11 | #define BITMAP_H_ 12 | 13 | // данный логотип расширением 128 на 27 14 | 15 | const unsigned char logo[]= 16 | { 17 | 18 | 0x02, 0x49, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19 | 0x02, 0x49, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 20 | 0x02, 0x49, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 | 0x0f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 22 | 0x1f, 0xff, 0xff, 0x80, 0x00, 0x7c, 0x00, 0x3e, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 23 | 0x5c, 0x19, 0x93, 0xe0, 0x03, 0xff, 0xf8, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 | 0xfc, 0x11, 0x13, 0xe0, 0x0f, 0xff, 0xf8, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 25 | 0x1c, 0x11, 0x13, 0x00, 0x3f, 0xff, 0xfc, 0x3d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 26 | 0xfd, 0xe2, 0x13, 0xe0, 0x7f, 0x81, 0xfc, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 27 | 0xfd, 0x04, 0x13, 0xe0, 0x7f, 0x00, 0xfc, 0x3f, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x00, 0xc6, 0x00, 28 | 0x1d, 0x38, 0xe3, 0x00, 0xff, 0x00, 0x78, 0x1f, 0xe0, 0x79, 0xb9, 0xff, 0xbc, 0x5d, 0xf3, 0x2e, 29 | 0xff, 0x29, 0x03, 0xe0, 0xff, 0x00, 0x00, 0x3f, 0xf0, 0xdf, 0xfb, 0xae, 0x6d, 0xfc, 0xe7, 0x7e, 30 | 0xfc, 0x6a, 0x73, 0xe1, 0xfe, 0x00, 0x00, 0x3c, 0xf8, 0xdd, 0x99, 0xce, 0x0c, 0xcc, 0xc7, 0x76, 31 | 0x1c, 0x32, 0x53, 0x01, 0xff, 0x00, 0x00, 0x3e, 0x7c, 0xcd, 0x98, 0xee, 0x6c, 0xcc, 0xc7, 0x76, 32 | 0xfc, 0x04, 0x73, 0xe1, 0xff, 0x07, 0xff, 0x7e, 0x7e, 0xf9, 0xdb, 0xef, 0xfe, 0xee, 0xf7, 0x77, 33 | 0xff, 0xf8, 0x23, 0xe1, 0xff, 0x0f, 0xff, 0xbe, 0x1e, 0x71, 0x99, 0xc7, 0x34, 0xcc, 0x67, 0x77, 34 | 0x1c, 0x03, 0x23, 0x00, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 | 0xfc, 0x05, 0xa3, 0xe0, 0xff, 0x81, 0xfc, 0x00, 0xf7, 0x00, 0x01, 0xe0, 0xe0, 0x00, 0x00, 0x00, 36 | 0x7c, 0x7c, 0x93, 0xe0, 0x7f, 0xc1, 0xfc, 0x0c, 0x70, 0x02, 0x1c, 0xec, 0x03, 0x20, 0x00, 0x00, 37 | 0x1f, 0xc3, 0x13, 0x00, 0x7f, 0xf3, 0xf8, 0x3e, 0x77, 0x7f, 0x36, 0xec, 0xe7, 0x60, 0x00, 0x00, 38 | 0xfc, 0x00, 0x13, 0xe0, 0x3f, 0xff, 0xf8, 0x77, 0x73, 0x33, 0x38, 0xf8, 0x67, 0xc0, 0x00, 0x00, 39 | 0x5d, 0xff, 0xd3, 0xa0, 0x0f, 0xff, 0xe0, 0x77, 0x73, 0x33, 0x1e, 0xfc, 0x63, 0xc0, 0x00, 0x00, 40 | 0x1f, 0xff, 0xff, 0x80, 0x07, 0xff, 0xc0, 0x3e, 0x77, 0xbb, 0xae, 0xef, 0xf1, 0x80, 0x00, 0x00, 41 | 0x0f, 0xff, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x73, 0x33, 0x38, 0xc0, 0x65, 0x80, 0x00, 0x00, 42 | 0x02, 0x49, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 43 | 0x02, 0x49, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 | 0x02, 0x49, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 45 | 46 | }; 47 | 48 | 49 | 50 | //################################################################################################################################################ 51 | /* 52 | 53 | Цветное изображение конвертируем спомощью файла IMG_to_HEX_converter.py 54 | запускаем командную строку CMD 55 | кидаем фаил IMG_to_HEX_converter.py и картинку в одну папку 56 | потом в командной строке переходим в эту папку и пишем: 57 | > python IMG_to_HEX_converter.py (имя файла)logo.jpg (ширина)85 (высота)53 58 | 59 | например: D:\IMG>python IMG_to_HEX_converter.py logo.jpg 85 53 60 | 61 | и в этой же папке пояаиться фаил с нашим массивом picFile.txt 62 | 63 | ГЕНЕРИРУЕТ В ФОРМАТЕ RGB565 ( 16bit ) 64 | 65 | */ 66 | 67 | 68 | // size 85 x 53 69 | const unsigned short logoRGB[] = { 70 | 0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x7B01,0x7B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x7C01,0x7C01,0x7C01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x9B01,0x7B01,0x9C01,0x9C01,0x9B01,0xBB01,0x9C01,0x7C01,0x7D01,0x7C01,0x7B01,0x9B01,0x9B01,0xBA01,0xD701,0x9612,0x1323,0x0F23,0x4912,0x0A2B,0x6943,0x053B,0x812A,0x2022,0xC119,0x4011,0xA131,0x0029,0x0141,0xE030,0xA44A,0x8019,0x6019,0x4432,0xA43A,0x2222,0x8422, 71 | 0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0x9C01,0x9C01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0x9B01,0x9C01,0x9C01,0x9C01,0x9C01,0xBB01,0xBB01,0xBB01,0xBB01,0xBB01,0x9C01,0x9C01,0x9C01,0x9C01,0xBC01,0xBB01,0xBC01,0xBB01,0xBC01,0xBB01,0xBC01,0xBB01,0xBC01,0xBB01,0xBC01,0xBB01,0xBC01,0xBB01,0xBC01,0xBB01,0xBB01,0xBC01,0x9C01,0x9C01,0xDC01,0x9B01,0x9B01,0xBC01,0x9D01,0x9B01,0xBA01,0xD901,0xB901,0xB801,0xF601,0x7412,0x7233,0xAF3B,0x4A33,0xA943,0x263B,0x495C,0x075C,0x402A,0xE121,0xC121,0xE129,0x2021,0xC020,0x4031,0xC029,0xC021,0xA119,0x4432,0xC432,0x211A,0x2633, 72 | 0xDB01,0xDB01,0xDB01,0xDB01,0xDB01,0xDC01,0xBC01,0xBC01,0xBC01,0xBC01,0xBC01,0xBC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xBC01,0xBC01,0xBC01,0xBC01,0xBC01,0xBC01,0xDC01,0xDC01,0xDB01,0xDB01,0xDB01,0xDB01,0xDB01,0xDC01,0xDC01,0xDC01,0xBC01,0xDC01,0xBC01,0xDC01,0xBC01,0xDC01,0xBC01,0xDC01,0xBC01,0xDC01,0xBC01,0xDC01,0xBC01,0xDC01,0xBB01,0xDC01,0xDC09,0xDC01,0x9B01,0xDC01,0xBB01,0xBB01,0xBC01,0xB901,0xF601,0xF401,0x360A,0xF509,0x130A,0xD53B,0xD35C,0xA93B,0xE643,0x8B7D,0xAB85,0xA443,0x612A,0x654B,0x2122,0xE021,0x0022,0xC019,0x002A,0x8019,0x4019,0xA121,0x0322,0x2422,0xC532,0x8322,0x8643, 73 | 0xFB01,0xFB01,0xDB01,0xDB01,0xDB01,0xDB01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xFC01,0xFC01,0xFC01,0xFC01,0xFB01,0xFB01,0xFC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDB01,0xDB01,0xDB01,0xDB01,0xDB01,0xDB01,0xDB01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xDC01,0xFC01,0xFC09,0xBA01,0xFA01,0x1A0A,0xF801,0x1702,0xF601,0xD91A,0xF301,0xD21A,0xDD7D,0x963B,0x300A,0xD443,0x6E33,0xC93B,0x833B,0x8D9E,0x845C,0x2133,0xA02A,0xA011,0x6009,0xC011,0x401A,0x0333,0x201A,0x4022,0x4443,0x8011,0x8119,0x2422,0x8109,0x021A,0xA42A,0x253B, 74 | 0x1C02,0x1C02,0x1B02,0x1B02,0x1B0A,0x1B0A,0xFB09,0xFB09,0xFB09,0xFB09,0xFB09,0xFB09,0xFB09,0xFB09,0xFB09,0xFB09,0x1B0A,0x1B02,0x1B02,0x1B0A,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0x1B0A,0x1B0A,0x1B0A,0x1B0A,0x1B0A,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFC09,0xFB09,0x3A0A,0x380A,0x540A,0x510A,0xF022,0x7875,0x566D,0xAE33,0x6F44,0x904C,0x6F2B,0xAB1A,0x8E5C,0xAA5C,0x2765,0x2A8E,0x487D,0x213B,0xC54B,0x201A,0xC019,0x412A,0x401A,0x623B,0x4233,0xC022,0xC022,0xA222,0x421A,0x642A,0x842A,0xA52A,0x041A,0x2422,0x4222, 75 | 0x1C0A,0x1C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3B0A,0x3B0A,0x1B0A,0x1B0A,0x1B0A,0x1B0A,0x1B0A,0x1B0A,0x1C0A,0x1C0A,0x3B0A,0x3B0A,0x3B0A,0x3B0A,0x3B0A,0x1C0A,0x1C0A,0x1C0A,0x1C0A,0x1C0A,0x1C0A,0x3C0A,0x3C0A,0x3B0A,0x3B0A,0x3B0A,0x1C0A,0x3C0A,0x1C0A,0x3C0A,0x1C0A,0x3C0A,0x1C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x1B0A,0x590A,0x792B,0x9533,0xF13B,0xF57D,0xA93B,0x8933,0xA833,0x041B,0xE733,0x892B,0xEE64,0x264C,0x034C,0x0465,0xE885,0xC343,0x8443,0x8222,0xE532,0x2322,0x221A,0x2433,0x054C,0x012B,0xC022,0x212B,0x022B,0x4212,0xA522,0x0312,0x6522,0x872A,0x093B,0x872A, 76 | 0x3C12,0x3C12,0x3C0A,0x3C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5B0A,0x5B0A,0x5B0A,0x5B0A,0x5B0A,0x5C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x3C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5C0A,0x5D0A,0x5A0A,0xF91A,0xD412,0x744C,0x2E44,0x8B54,0xC643,0x873B,0x8733,0x484C,0x4A65,0xE85C,0x664C,0xC33B,0xA23B,0x076D,0xA23B,0x232B,0x4633,0xC62A,0xA72A,0x461A,0xA722,0xC62A,0x663B,0x833B,0x002B,0x8243,0xC02A,0x411A,0xE62A,0x6722,0x681A,0x4712,0x8A22,0x6F1A, 77 | 0x5D12,0x5D12,0x5D12,0x7D12,0x7C12,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7C12,0x7C0A,0x7C0A,0x7C0A,0x7C0A,0x7B0A,0x7B12,0x7B12,0x7C12,0x7C12,0x7C12,0x7D12,0x7D12,0x7D12,0x7D12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C12,0x7C0A,0x7C0A,0x9A0A,0xF71A,0x3644,0x6D2B,0x482B,0x8433,0x833B,0x4012,0x601A,0x4233,0xE33B,0x0344,0x402B,0x801A,0x6654,0x4654,0xA022,0x042B,0x8733,0x683B,0xE82A,0x8E3B,0x6A12,0x0A2B,0xA93B,0x0223,0x4033,0x0033,0x8022,0xA322,0xE72A,0x8B22,0x6C1A,0x8A1A,0x6B1A,0x9122, 78 | 0x9C12,0x9C12,0x9D12,0x9D12,0x9D12,0x9D12,0x9D12,0xBD12,0x9D12,0xBD12,0x9C12,0xBD12,0xBC12,0x7B12,0xBD1A,0x9C12,0xBD12,0xBC12,0xBC12,0xBC12,0x9C12,0xBC12,0xBC12,0x9C12,0x9C12,0x9D12,0x9D12,0x9D12,0x9D12,0x9D12,0x9D12,0x9D12,0x9C12,0x9C12,0x9C12,0x9C12,0x9C12,0x9C12,0x9C12,0x9C12,0x9C12,0x9C12,0xBC12,0xBC12,0xBC12,0xBC12,0xBC12,0xBC12,0x9B12,0xB91A,0x562B,0xCF1A,0x4A2B,0xCC5C,0x2754,0xE02A,0xC02A,0x8A85,0x875C,0x012B,0x4333,0xA022,0xE12A,0x8343,0x633B,0x2754,0x811A,0x853B,0x6533,0x0B44,0xCE1A,0x3223,0xED1A,0xEB3B,0x4323,0x8133,0x801A,0xC12A,0xE522,0xEA22,0xF12A,0x901A,0xCC22,0xAA22,0x6B22, 79 | 0xDC12,0xDC12,0xDC12,0xDC12,0xBC12,0xBC12,0xBC12,0xBC12,0xDD12,0xDD12,0xBC12,0xBC12,0xBC12,0xDD1A,0xBC12,0xBC12,0xBD12,0xBD12,0xDD12,0xDD12,0xDC12,0xDC12,0xDC12,0xBC12,0xDC12,0xDC12,0xDC12,0xDC12,0xBD12,0xBD12,0xBD12,0xBD12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDC12,0xDA1A,0x592B,0x594C,0x3244,0x6E54,0xC843,0x0654,0x413B,0xA66C,0x445C,0xC02A,0xA009,0xE011,0x6001,0x033B,0x201A,0xC653,0x201A,0xC222,0x4333,0xA33B,0x0944,0x1144,0xEF1A,0x4C23,0x0F5D,0xE95C,0xA01A,0xC022,0xA122,0xE622,0xEC2A,0xF32A,0x1333,0xEC2A,0x871A,0x0512, 80 | 0x1C13,0x1C13,0xFC12,0x1C1B,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFD1A,0x1D1B,0xFD1A,0xDC12,0xFD1A,0xFD1A,0xFD1A,0xDD1A,0xDD1A,0xDD1A,0xDD1A,0xFD1A,0xFD1A,0xFC12,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFD1A,0xFD1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFC1A,0xFB1A,0xDC3B,0x1A44,0x942B,0xD133,0xCD3B,0xA833,0x012B,0xC022,0x0033,0xC34B,0x401A,0x001A,0xA011,0x2001,0x0022,0xA019,0xE019,0xA011,0x401A,0xA122,0x823B,0xE543,0xE522,0xAA3B,0x6B4C,0xCA5C,0x465C,0x413B,0x8022,0xC32A,0xC822,0x0D2B,0x3333,0x8F1A,0x4512,0x0523,0x651A, 81 | 0x3D1B,0x3D1B,0x3C1B,0x3C1B,0x3C1B,0x3C1B,0x3C1B,0x3C1B,0x1C1B,0x3D23,0x1C1B,0x3D1B,0x1D1B,0x3E1B,0x3D1B,0x3D1B,0x3D23,0x1D23,0x1D23,0x1D23,0x1D1B,0x3D1B,0x3D1B,0x1C1B,0x3C1B,0x3C1B,0x3C1B,0x3C1B,0x3C1B,0x3C1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3D1B,0x3B1B,0x5A23,0x3623,0x7323,0xD033,0xAD2B,0x6D4C,0x2A4C,0x242B,0xA122,0xE54B,0x433B,0x812A,0xA011,0x043B,0x2022,0x6009,0xC119,0xE219,0xC62A,0x883B,0x242B,0x6533,0x821A,0xA73B,0x0F86,0x264C,0x802A,0x8032,0x4022,0xC32A,0xC722,0x4C2B,0xCC22,0x4812,0xA41A,0xE843,0x482B, 82 | 0x5C1B,0x5C1B,0x5C1B,0x5C1B,0x5C1B,0x7C1B,0x5C1B,0x5C1B,0x7D1B,0x5C1B,0x9D23,0x5C1B,0x7D23,0x5D1B,0x3C1B,0x5D1B,0x3C23,0x3C23,0x3C23,0x5D23,0x3D23,0x3D1B,0x5D23,0x7D1B,0x5D1B,0x7C1B,0x7C1B,0x7C1B,0x5C1B,0x5C1B,0x5C1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5D1B,0x5C1B,0x5B1B,0x7823,0xD52B,0xD02B,0xB56D,0x5044,0xD03B,0x4C2B,0xC622,0xE84B,0xA64B,0x402A,0x013B,0x876C,0x265C,0xA22A,0xA309,0xCB32,0xD13B,0x9033,0x4C23,0x6B33,0xCB43,0xAD64,0xEC6C,0x042B,0x2022,0x202A,0x4022,0xA22A,0xE522,0xE522,0xA21A,0x885C,0xC63B,0xC833,0x2F44, 83 | 0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9C23,0x7C23,0x9C23,0x7B23,0x5A23,0x3923,0x7A2B,0x1C44,0x3923,0x7A2B,0x7A2B,0x7B2B,0x9D2B,0x7D23,0x7D23,0x7D23,0x7D23,0x9D23,0x9C23,0x9C23,0x9C23,0x9C23,0x7C23,0x7D23,0x7D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x9D23,0x7D23,0x7D23,0x7D23,0x9D23,0x7D1B,0xBA23,0xB42B,0xF554,0xD254,0xAE33,0xF143,0x4E33,0xE82A,0xE532,0x2543,0x202A,0x8032,0x6B8D,0x6243,0xC32A,0x6622,0xCB2A,0xED22,0x6E2B,0xEF3B,0xED43,0xED43,0xE82A,0xE62A,0x421A,0x4122,0x0022,0x001A,0xA009,0xA222,0xCE8D,0xC243,0xE664,0xC75C,0x2523,0xCD33, 84 | 0xBD2B,0xBD2B,0xBD23,0xBD23,0xBE23,0xBE23,0xBD23,0xBD23,0xDC2B,0x7A2B,0x592B,0x9F7D,0x3F9E,0x5FC7,0x5FCF,0x3F9E,0x7B54,0xDA33,0x5A23,0x7B23,0xBD2B,0xBE2B,0xBE23,0xBE23,0xBD23,0xDD23,0xDD23,0xBD23,0xBD23,0xBD23,0xBD2B,0xBD2B,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBD23,0xBE2B,0xBB2B,0xD84C,0xCF33,0xEE3B,0x0C3C,0x482B,0x062B,0xC109,0x2009,0x4019,0x6021,0xC008,0x613A,0x454B,0xC011,0xA011,0xC109,0x6112,0x853B,0x853B,0x052B,0xAC3B,0x6B33,0xE72A,0xA42A,0x2122,0xC019,0xC011,0xC232,0x486C,0x6022,0xC243,0xA45C,0xA033,0xE443,0xC51A, 85 | 0xDD2B,0xFD2B,0xFD2B,0xFE2B,0xDE23,0xDE23,0xDD2B,0xDC2B,0x9A2B,0x1F65,0x7F9E,0xBF8D,0xFE9D,0x9FB6,0x1FCF,0x5FCF,0xFFD7,0x5F96,0x7A54,0x9833,0x9A33,0xBC2B,0xDE2B,0xFE23,0xFE23,0xFD23,0xFD23,0xFD2B,0xFD2B,0xDD2B,0xDE2B,0xDE2B,0xDD2B,0xDD2B,0xFD2B,0xFD2B,0xFD2B,0xFD2B,0xDD2B,0xDD2B,0xFD2B,0xDD2B,0xDD2B,0xDD2B,0xDD2B,0xDD2B,0xFD2B,0xDD2B,0xDE2B,0xFA33,0x333C,0x8F4C,0xCA33,0xCC5C,0x6533,0x8543,0x212A,0x222A,0xE229,0x2019,0x0019,0xA021,0x8232,0xC011,0x253B,0xAB6C,0x2754,0x885C,0xC543,0x873B,0xC722,0xA71A,0x651A,0xA42A,0x2222,0xE021,0xE019,0x412A,0x0022,0xC019,0xA34B,0x2033,0xC03B,0x4454,0xE32A, 86 | 0x1D2C,0x1D2C,0x1D2C,0x3E2C,0x1D2C,0x1D2C,0x5E3C,0x3F5D,0x3F65,0xDF85,0xBF8D,0x3F9E,0xFD9D,0xBFBE,0x1FC7,0x3FCF,0x7FD7,0x9FD7,0xFFE7,0xFFD7,0xBE85,0xD93B,0x1D34,0x1E2C,0x1E2C,0x1D24,0x3E2C,0x3D2C,0x3D2C,0x1D2C,0x1D2C,0x1D2C,0x3E2C,0x3E2C,0x1D2C,0x1D2C,0x3D2C,0x3D2C,0x1D2C,0x1D34,0x1D2C,0x1E2C,0x1E2C,0x1E2C,0x1E2C,0x1E2C,0x1D2C,0x1D2C,0x1C34,0x583C,0xB14C,0x8B44,0x0B5D,0x4B75,0x4243,0xA13A,0x6232,0x6232,0x0122,0xC019,0xA021,0x6019,0x4011,0x444B,0x6743,0x8943,0xB064,0x4E4C,0x0C44,0xA93B,0x6843,0xC432,0xC332,0xA32A,0xC119,0x6011,0xE43A,0xA019,0x4009,0x8011,0xE019,0xA02A,0x813B,0x034C,0x8122, 87 | 0x5E34,0x5D34,0x3D2C,0x5E34,0x5D34,0x3D34,0x5C3C,0xFE54,0x7F6D,0x5E75,0xDE8D,0x1E9E,0x5EA6,0x9FB6,0x3FCF,0xDFC6,0x1FD7,0x7FDF,0x9FDF,0x3FCF,0xFFDF,0x1C65,0x1B34,0x5E2C,0x5E2C,0x5E34,0x3D2C,0x7E34,0x3D2C,0x5D34,0x5E2C,0x7E34,0x5E2C,0x5E2C,0x5E34,0x5D34,0x5D2C,0x5D2C,0x5D34,0x5D34,0x5E34,0x5E34,0x3E34,0x3E34,0x5E34,0x5E2C,0x5E34,0x5D34,0x3B34,0x3955,0x6D44,0x7086,0xA854,0xC43B,0x844B,0xC23A,0x8232,0xE43A,0x8122,0x6122,0x412A,0xC019,0xC33A,0x822A,0xE111,0xA201,0x050A,0xED43,0x6E4C,0x893B,0x6543,0x812A,0x033B,0x822A,0x8011,0x442A,0x001A,0x4001,0xC011,0x2001,0x4009,0x802A,0xE44B,0x2233,0xE432, 88 | 0x7E34,0x7E34,0x7D34,0x9D34,0x7D34,0x7D3C,0x9D44,0x3F5D,0x7F65,0xDF7D,0xFF85,0x3E96,0x7FAE,0x1FBF,0x1FCF,0x1FCF,0xFECE,0x1ED7,0xFFEF,0x9FDF,0x9FD7,0x5F9E,0x3B3C,0x9E3C,0x9E3C,0x9E3C,0x5D34,0x9E34,0x9E34,0x9D34,0x9E34,0x5D34,0x7E34,0x7E34,0x7E34,0x7D34,0x7E34,0x7E34,0x7D34,0x7D34,0x7E34,0x7E34,0x7E34,0x7E34,0x7E34,0x7E34,0x7D34,0x7D34,0xDD3C,0x7634,0xF265,0xC94C,0x273C,0x2744,0xC643,0xC643,0xE42A,0x042B,0x853B,0x801A,0x4022,0x201A,0x2312,0x8A43,0xA943,0xC42A,0xC743,0x6533,0xA543,0xC22A,0xC132,0x602A,0xE011,0xA74B,0x031A,0xE632,0x643B,0xE443,0x244C,0x6554,0x423B,0xC009,0xC22A,0xC322,0x0633, 89 | 0x9E3C,0xBE3C,0xBE3C,0xBD3C,0x9D3C,0xBC3C,0xFD4C,0x9F5D,0x7E65,0xDE75,0xFE7D,0x5E96,0x1D96,0x7EAE,0xDFBE,0xBEBE,0xFEC6,0xDDC6,0x7FD7,0x9FDF,0x7FD7,0x1FBF,0x3944,0x7B3C,0x5B3C,0x9C44,0xBD3C,0x9D34,0xDE3C,0xBE34,0x9E34,0xBE3C,0x9E3C,0x9E3C,0xBD3C,0xBE3C,0x9E3C,0xBE34,0xBE34,0xBE34,0xBE34,0xBE34,0xBE34,0xBE34,0xBE34,0x9E3C,0x9D3C,0xBD3C,0xBB34,0xB73C,0x124D,0x6C3C,0xAC4C,0x6A4C,0x2944,0xA833,0xCA33,0xEB3B,0x8633,0x222B,0xE12A,0x4122,0x2412,0x6E54,0xAA3B,0xC943,0x022B,0x2233,0x013B,0x013B,0xC553,0x001A,0xA22A,0x011A,0x8111,0x6743,0x0B75,0x823B,0x0244,0x8775,0x234C,0x6654,0x000A,0xE42A,0x4733, 90 | 0xFE3C,0xFE3C,0xDE3C,0xDE3C,0xFD3C,0xDD3C,0x1D4D,0x5D5D,0xFE75,0x1E7E,0x3E8E,0x7FB7,0xFFAE,0x7E9E,0x7EA6,0x7EA6,0xBEB6,0xDEB6,0xDEB6,0x9FC7,0x3FC7,0x5FC7,0x5F96,0xDB5C,0xDE75,0x7A4C,0x9C44,0xDE44,0xFE3C,0xDE3C,0xBE3C,0xFE44,0xDE3C,0xDE3C,0xDD3C,0xDD3C,0xDD3C,0xDE3C,0xDE3C,0xDE3C,0xDE3C,0xDE3C,0xDE3C,0xDD3C,0xDD3C,0xDD3C,0xDE3C,0xDD3C,0xFB44,0x3A4D,0x5534,0x1655,0xF24C,0x0C34,0xAD4C,0x6D44,0x723C,0x713C,0xE833,0x6433,0x8022,0x822A,0xA322,0x6933,0xB254,0x2F3C,0xA41A,0x0333,0x4443,0xE23A,0xA12A,0xA12A,0x812A,0xA232,0x8019,0xE96B,0xC442,0xC23A,0x0454,0x6033,0xC354,0xE012,0xE122,0xA222,0x0323, 91 | 0x1E45,0xFE3C,0x1E3D,0x1E3D,0x1E3D,0xFD44,0x7E55,0xBE65,0xDE6D,0x7F8E,0x1D86,0x7F96,0x5E96,0x9F9E,0xBF9E,0x7F9E,0x9FA6,0xFFAE,0xDEA6,0xDEAE,0xFFBE,0x3FC7,0x9FA6,0x5FB7,0x1FAF,0x1FA7,0xBF8E,0xBB44,0x1E45,0x1F45,0xFE3C,0x1E45,0x1E3D,0x1E3D,0x1E3D,0x1E45,0xFD44,0x1E45,0x1E45,0x1E3D,0x1E3D,0x1E3D,0x1E3D,0x1E45,0x1D45,0x1D45,0x1E45,0x1D45,0x1C45,0xFB44,0x1C45,0x1A4D,0x154D,0x6F3C,0x1155,0x334D,0x584D,0xB53C,0xEB33,0x0744,0x8022,0x6022,0x663B,0x0C44,0x1555,0x565D,0xA61A,0xA743,0x822A,0xC232,0xC232,0x443B,0xC12A,0x2022,0xC021,0x2032,0x0009,0xC021,0x013B,0x034C,0xA354,0x013C,0x801A,0x443B,0xC53B, 92 | 0x1F45,0x1E45,0x3F45,0x3F45,0x3E45,0x1D45,0xDF5D,0x3F6E,0x3F7E,0xFE75,0x1E7E,0x5F8E,0x3E8E,0x3F8E,0xFFA6,0xDFA6,0x7F9E,0x7F9E,0x9E9E,0x9E9E,0x9EA6,0xBFAE,0x5FBF,0xFFAE,0xFFA6,0x1FA7,0x1FA7,0x1B55,0x1D45,0x5F3D,0x5F45,0x3F3D,0x3E45,0x3E45,0x3F3D,0x3F45,0x3E45,0x3E45,0x3E45,0x3F45,0x3E45,0x3E45,0x5E3D,0x5E3D,0x3D45,0x3D45,0x5E3D,0x5E3D,0x3E45,0x1D45,0x3D3D,0x5B45,0xF544,0x1345,0xD33C,0x784D,0x7B45,0x594D,0xED33,0x4A4C,0x0233,0x643B,0xEA43,0x7465,0x775D,0x323C,0xAC3B,0x062B,0x0433,0xA22A,0xA332,0xE011,0xC02A,0x445C,0x2675,0x445C,0xC011,0xE019,0x2022,0x8664,0x6033,0xA65C,0x423B,0x275C,0x6433, 93 | 0x7F4D,0x5E4D,0x5E45,0x5E45,0x7E4D,0x3D4D,0xBF5D,0xFF6D,0xBD6D,0xDE75,0x1E7E,0x5F8E,0xDD7D,0x1E86,0xFE85,0x9F96,0x3F86,0x5F8E,0x9F96,0x9F9E,0x5E96,0x9FA6,0xBFA6,0xBEA6,0xDFA6,0xBF9E,0xDFA6,0x7F8E,0x1B4D,0x3C4D,0x1C45,0x3D4D,0x5D4D,0x5E4D,0x7E45,0x7E45,0x5E45,0x7E45,0x7F45,0x7E45,0x7E45,0x7E45,0x7F45,0x7F45,0x7E45,0x7E45,0x7E45,0x7F45,0x7F45,0x5E45,0x9F45,0x9C45,0x984D,0xD43C,0x5845,0x7B4D,0x9D45,0xBC4D,0xD023,0x726D,0xC743,0xC643,0xC622,0xB57D,0x355D,0x6E1B,0xEA1A,0xCC3B,0x4C4C,0x6733,0x411A,0xAC8D,0x70BF,0xAB9E,0x046D,0xA46C,0xE45B,0x4032,0xC021,0x2343,0x2A75,0x2654,0x6543,0x0533,0x4B44, 94 | 0xBE55,0x5C4D,0x7D4D,0x5D45,0x5D4D,0x7D4D,0x7D55,0xFE6D,0xBC6D,0xBB75,0x1C86,0x5D8E,0x5D8E,0x1D7E,0x3E7E,0x7F86,0x5F7E,0x7F86,0x7F8E,0x7E8E,0x7F8E,0x7E96,0x5D96,0xFFAE,0x7C96,0xDEA6,0xFEB6,0x7FBF,0x5FB7,0xBE9E,0xDFC7,0x1FAF,0x9C75,0x1B55,0x7D55,0x7D4D,0x9E45,0xBF45,0xBF45,0xBE45,0x9E4D,0x9E45,0xBF4D,0x9F45,0xBF45,0x9F45,0x9F45,0x7F4D,0x9F4D,0x9F45,0xBE45,0x9B45,0xD855,0x153D,0x7B4D,0xBD4D,0x9E45,0xBD4D,0x1945,0xB865,0xAF4C,0x883B,0x4322,0x4D6C,0xCC43,0x0A1B,0xD24C,0x5134,0x7334,0x535D,0x2A6D,0xECA6,0x8996,0x4575,0xA04B,0xE04A,0x2363,0xC35A,0x2142,0xE029,0xC743,0xAF75,0x6C54,0x0A23,0xB85D, 95 | 0x9F7E,0xFF86,0x7F76,0x9F97,0x1F87,0x3E6E,0xFF8E,0x7E86,0x7E8E,0xBFBF,0xDFA6,0x9FBF,0xFFBF,0x3D86,0x5E7E,0x5E7E,0x3F76,0x7F7E,0x3E7E,0x7E86,0x7F8E,0x7F96,0xBE9E,0xFFCF,0x5FB7,0xFEAE,0x9FC7,0x9FC7,0x5FBF,0x3FBF,0xFEBE,0x9FCF,0x9FC7,0x9FB7,0x5E7E,0x9F7E,0xFE55,0xDF4D,0xDF4D,0xDE4D,0xBD55,0xBD55,0x7D4D,0xBF55,0xBF4D,0xBF4D,0xDF55,0xBF55,0xDF4D,0xBF45,0xDE45,0x1D56,0xDA4D,0x994D,0xDD55,0xDF4D,0xDE45,0xDE4D,0xDF55,0xDC5D,0xB65D,0x4D44,0x273B,0xE63A,0xAA43,0x125D,0xB85D,0x984D,0xD955,0x1466,0x0A7E,0x8796,0x0686,0x4154,0xC353,0x403A,0x8039,0xA041,0x8031,0x8021,0xA322,0x430A,0xCF64,0x3044,0x584D, 96 | 0xBD9E,0x9FB7,0x1FA7,0x7FA7,0x5FA7,0xDF96,0xFF9E,0x9FBF,0xBFC7,0x9FC7,0x9FC7,0x9FBF,0xFF9E,0x3E7E,0x3E76,0x3F6E,0x3E6E,0x5E76,0x7E76,0x7E7E,0x9F8E,0xFFA6,0x9FBF,0x1FAF,0xBFBF,0xDE9E,0xDE9E,0x5FB7,0x3FB7,0xFFB6,0xFEB6,0x3FBF,0x7FC7,0xBFCF,0xFFCF,0x7FAF,0x9F9F,0x9D55,0xFF55,0xDE55,0x9C65,0x9B6D,0xDD75,0x9C65,0xDD55,0xBD4D,0x1E56,0x1E56,0xFE4D,0xFE4D,0x1F4E,0xFD4D,0xFD4D,0xDC4D,0xDE4D,0xFF4D,0x1F4E,0x1F4E,0xDF4D,0xDE55,0xFA55,0xB555,0x0C34,0x2B4C,0xA61A,0x7886,0x1A5E,0x3B56,0x1666,0x306E,0xC76D,0x257E,0xC57D,0xE04B,0xA44B,0x254B,0x6029,0x8031,0x2132,0xC019,0x412A,0x4222,0x2412,0x4F4C,0x7EA7, 97 | 0xBD9E,0x9FB7,0x7FAF,0x1F9F,0x7D8E,0x7E8E,0xDF9E,0xDF9E,0xDEA6,0xFFAE,0x3FB7,0x5FB7,0x9FB7,0x3D7E,0x5E76,0x7F76,0x5E76,0x7E7E,0x9E7E,0x7E86,0x5E8E,0x3FAF,0x1FAF,0x1FAF,0x1F9F,0xFE96,0x1F9F,0x1FA7,0xDFA6,0xFFA6,0x5FB7,0x3FB7,0x5FC7,0x9FCF,0x7FC7,0x3FB7,0xBFAF,0xBC65,0xFE55,0xBE55,0x7FAF,0xFFCF,0xFFCF,0x3F9F,0x3955,0xFFA7,0x5F8F,0xDB5D,0xFC5D,0xDC55,0x1E5E,0xFE55,0xFD55,0x5F5E,0x1F56,0x1F4E,0x1F4E,0x3F4E,0xFF4D,0xFF55,0x3D56,0xF955,0x3345,0x5776,0xA912,0x2C23,0x5B6E,0x3866,0xB15D,0x4E76,0x2876,0xE575,0xE364,0x0354,0x0433,0x4322,0xE231,0xC031,0x2122,0x612A,0xC021,0xA33A,0xA94B,0x8201,0xF585, 98 | 0x1C6E,0x3F97,0x1F8F,0x7E7E,0x7E7E,0x7E7E,0x9E7E,0x9E7E,0xBF8E,0xDF8E,0xDF96,0x3F9F,0x5FA7,0x5FA7,0x3F9F,0xDF8E,0x9E86,0xFF96,0x7FAF,0x7FB7,0x5FB7,0xBFA6,0xDF9E,0x1F97,0xFF8E,0xFF8E,0x1F97,0xFF96,0x3FA7,0x5FAF,0x3FA7,0x5FB7,0x7FC7,0xDFD7,0x3EB7,0x7FBF,0x9FB7,0xFB6D,0x3E5E,0xDD55,0x9FB7,0xDFC7,0x1EAF,0x3B8E,0xBFC7,0xDFC7,0x5B96,0xDFBF,0xFFCF,0xFFC7,0xDC6D,0x3E76,0xFFB7,0x3D66,0x1F5E,0x3F56,0x3F56,0x3F56,0x1F4E,0x3F56,0x5E56,0xDB4D,0x3D5E,0x5C6E,0x1A7E,0xAA1A,0x092B,0x3386,0xD06D,0xAC5D,0xA75D,0xC24C,0xE564,0x2654,0xC84B,0x273B,0x4332,0x423A,0x612A,0xA232,0xC021,0xC44A,0xCD7C,0x4743,0x4212, 99 | 0x7F6E,0xBF76,0xBF76,0x5E66,0x7E6E,0x9F6E,0x7E6E,0xBF76,0x7E6E,0xDF7E,0xDF86,0x9E7E,0x7D86,0xFF96,0x5FA7,0xFE96,0x1F97,0xFF96,0xDE96,0x1FAF,0x7FBF,0xBFC7,0xBE96,0x9D86,0xBE86,0xBE86,0x9D8E,0xFF9E,0x3F9F,0x1F9F,0xDE96,0xDE96,0xFEA6,0x3FB7,0xBFBF,0xBFBF,0x5FAF,0xDFB7,0x5D6E,0x5D6E,0x3EA7,0x7FBF,0xFFC7,0xFFC7,0x7FC7,0xBFCF,0x9FC7,0xDFCF,0xFFD7,0x1A8E,0xDFA6,0xBFB7,0x7FAF,0x1C6E,0x1E66,0x3F5E,0x3F5E,0x3E5E,0x3E56,0x5E5E,0x3D56,0x3E56,0x7F5E,0x1E56,0x5D6E,0x397E,0x282B,0x0C6D,0x4C65,0x2E76,0x475D,0x4344,0x086D,0x643B,0x0E6D,0x307D,0x685B,0xA442,0x2122,0x8232,0x4232,0xA021,0x685B,0x9095,0xA422, 100 | 0x9F5E,0x5F5E,0x5F5E,0x7F66,0x7E5E,0x7E66,0x7E66,0x7E66,0x7E66,0x5D66,0x3D66,0x3D6E,0x5C76,0xDE8E,0x9D8E,0x9D86,0x9E7E,0x7D76,0x9E7E,0x3F9F,0x5FAF,0x7FBF,0xFFC7,0x5FAF,0x5B7E,0xDD96,0x7FB7,0x3FAF,0xBE96,0xBE8E,0xDF8E,0xDF8E,0xDE96,0xDE9E,0x3FA7,0x7FAF,0x1EA7,0x3FAF,0xFF9E,0x7FAF,0x9FB7,0xDD9E,0x1F9F,0x9FAF,0x7FAF,0xDD9E,0x9FBF,0x7FBF,0x9FBF,0xDFCF,0xDFCF,0xBFC7,0xBFBF,0x1B7E,0x5E76,0x5E66,0x3D66,0x9E6E,0x1F87,0x9E76,0xBE6E,0x7E66,0x5F5E,0x7F5E,0x5F56,0x7C66,0x967E,0x6E65,0xA21A,0x474C,0x4E8E,0x2554,0xA443,0x8964,0x0B4C,0x96A6,0x4B6C,0x433A,0xE031,0x2232,0xA953,0xAA5B,0x0019,0xCF8C,0x1065, 101 | 0x9F5E,0x9F5E,0x9F66,0xBF66,0x7F5E,0xDF6E,0x9F66,0xBF66,0x1F77,0x9F87,0xFF9F,0xFF7E,0x5F8F,0x9F9F,0x5F97,0x5F97,0xBF76,0xFF7E,0xBF7E,0xFF8E,0xFF9E,0x9FB7,0xFFCF,0x7FB7,0x3F9F,0x5FA7,0x9FB7,0x9FB7,0xDFB7,0xFF8E,0xDF86,0x1F8F,0xFF8E,0xFF96,0x1F97,0xFF96,0x5FA7,0xFFBF,0xFFC7,0x1F9F,0x5FA7,0x7FA7,0x5D7E,0x1F8F,0xDF86,0x9FA7,0x9FAF,0x1FA7,0xFE9E,0xDFBF,0x9FBF,0x3FAF,0x7FAF,0x3F97,0x7F97,0x7F8F,0x1F87,0x9F97,0x3F8F,0xDF7E,0x1F7F,0xFF76,0x9F66,0x9F5E,0x9F56,0x9E5E,0x5766,0xB67E,0xF275,0xEE5C,0xE522,0x2433,0xA96C,0x495C,0x97AE,0xDCD7,0x684B,0xAC84,0x2242,0x033A,0x0833,0x1AB7,0xA942,0x2311,0xF58D, 102 | 0xDF6E,0x1F77,0xFF76,0xFF76,0xDF6E,0x3F7F,0x1F77,0x1F77,0x1F77,0xFF76,0xBF76,0xFF7E,0xDF76,0xFF7E,0xFF86,0x3F8F,0x3F8F,0x9F9F,0x3F8F,0x5F97,0xDF8E,0x7FA7,0x5FA7,0x7FAF,0xFFB7,0x7FA7,0x9F86,0xDF86,0xDF7E,0xBF7E,0x5F8F,0xFF7E,0xBF9F,0x1F8F,0xBF86,0x9F7E,0x3F8F,0xDF86,0x9F7E,0xDF86,0x1F8F,0xFF86,0xDF7E,0xDF7E,0xFF7E,0xFF86,0x1F87,0x1F8F,0xBF7E,0xDF86,0xDF86,0xFF86,0xFF86,0x5F8F,0x9F8F,0x1F7F,0xDF76,0xBF76,0x9F6E,0x9F6E,0x9F66,0xBF66,0xBF66,0xBF66,0xDF66,0xDF66,0x7B5E,0xDC76,0xBC76,0x5A76,0x177E,0x6A33,0xA422,0x642A,0x4E74,0xB39D,0xB4B6,0x0543,0x065B,0x2432,0x8C3B,0xD675,0x3EAF,0xE911,0xC529, 103 | 0x9B3D,0x9B3D,0x9C45,0x7B3D,0x7B3D,0x9B3D,0x7B3D,0x7B3D,0x7B3D,0x7B3D,0x7B3D,0x9B45,0x7B3D,0x7B3D,0x5B3D,0x5B3D,0x9C4D,0x7B4D,0x5B45,0x5B45,0x3B45,0x3A45,0x1945,0x1945,0x1945,0x5A4D,0x7B45,0x7B45,0x5B3D,0x5B3D,0x5B3D,0x3A3D,0x5A3D,0x5A3D,0x7B45,0x3A3D,0x7B45,0x3A3D,0x3A3D,0x5A3D,0x3A35,0x1A35,0xF92C,0xF92C,0x1A35,0x1A35,0x3A35,0x3A35,0x5B35,0xFA2C,0xFA2C,0x3B35,0x1A35,0xD92C,0xFA2C,0xFA2C,0xFA2C,0xFA2C,0xFA24,0x1B25,0x1B25,0x3C2D,0x5C2D,0x3B2D,0x1B2D,0x3A2D,0x392D,0x5A35,0x3A2D,0x1935,0x1745,0x513C,0x4A2B,0xE822,0xC709,0x8501,0x861A,0xA52A,0xA542,0x443A,0x0933,0x9154,0xD45C,0x7364,0x4321, 104 | 0x1B3E,0xFB35,0xFB3D,0xDB35,0xDB35,0xBA2D,0xBB35,0xDB35,0xBB35,0x9B2D,0xBB35,0x7A2D,0x9A2D,0x792D,0x9A35,0x7A2D,0xDB35,0x9A2D,0xBB2D,0x9B2D,0x9B2D,0x5925,0x7A2D,0x9A35,0x7A2D,0x5A2D,0x3925,0xF91C,0xF914,0x191D,0x3925,0x9B35,0x7A2D,0x5A25,0x3925,0x3925,0x5A25,0x5A25,0x7B2D,0x7B2D,0x5A25,0x5A25,0x3A1D,0x3A1D,0x5A25,0x5A25,0x5A25,0x3A1D,0x1A1D,0x1A1D,0x1A1D,0xFA14,0xDA14,0xFA14,0x1B1D,0xD914,0xFA14,0x1A15,0x3A1D,0x1B15,0xFA0C,0xDA0C,0xFA0C,0xFA0C,0xB914,0x980C,0xB904,0x7804,0x7804,0xB814,0x7614,0xF213,0xCA02,0x9234,0xD724,0xD724,0x3124,0xE912,0x241A,0x643A,0x0332,0xC642,0xCC63,0x2F74,0x2E7C, 105 | 0x1E67,0xFD66,0x1E67,0xDD5E,0xFE66,0xBD5E,0xFE5E,0xFE66,0xDE66,0xDE5E,0xFE66,0xDE66,0xFE66,0xDD5E,0xDE66,0xDD5E,0x9C56,0x9C56,0x9D4E,0xBD4E,0x9D4E,0x9D4E,0x9D56,0xBD56,0x5C4E,0x3C46,0xFB3D,0x3C46,0x3C46,0x1C46,0x3B4E,0x3C4E,0x5C4E,0x5D4E,0x5C4E,0x5C4E,0x3C4E,0x3C46,0x7D4E,0x7D4E,0x5D4E,0x5D4E,0x5D4E,0x3C4E,0x3C4E,0x5D4E,0x5D4E,0x3C46,0x1D46,0x1D46,0xFC3D,0xFC3D,0xDC3D,0xDC3D,0xDC3D,0xDC3D,0xDB35,0x9B35,0x9B2D,0xBB35,0xBB35,0x9B2D,0x7B2D,0x7B25,0x7B2D,0x7B2D,0x9C2D,0x9C2D,0xBB35,0xDB3D,0x9A3D,0xB524,0xF11B,0x974D,0xBB35,0xBB2D,0xB94D,0x0F2C,0x861A,0x8953,0x2332,0xE331,0xA742,0xA419,0xE619, 106 | 0x3D8F,0x3D8F,0x3D8F,0x3D8F,0x3D97,0x3C8F,0x3C97,0x3C97,0x5D97,0x1C8F,0x1C8F,0xFC8E,0xFC86,0xDC86,0xFC8E,0x1C8F,0x3C8F,0x3D8F,0x1D87,0x3D87,0x1D87,0x3D87,0xFD86,0xFD86,0xFD86,0xDD7E,0xDD7E,0xBD7E,0xBC7E,0xDC86,0x1D8F,0xDC86,0xDC86,0x1D8F,0xFD86,0x9B7E,0xBC7E,0x9B76,0xBC7E,0x7B76,0xBC7E,0xBC7E,0xBC7E,0x9C7E,0x9B7E,0x9B7E,0x9B7E,0x9C7E,0xBC7E,0x9B76,0x7B76,0x5B6E,0x5B6E,0x1A66,0x1A66,0x3B6E,0x5B6E,0x7B6E,0x9C76,0x9C76,0x7C6E,0x7C6E,0x9C6E,0x9C6E,0xBD6E,0x9C6E,0x7B6E,0x7B6E,0x7B6E,0x7B6E,0xDD7E,0x7C76,0x775D,0xBB7E,0xBD76,0x7C6E,0xBC7E,0xB665,0x270A,0xD06C,0x127D,0xC519,0x0943,0xB9AE,0x1786, 107 | 0x7CBF,0x9CBF,0x9CBF,0xBDC7,0x9CBF,0xBCC7,0xBCC7,0xBCBF,0xBCC7,0x9CBF,0x7CBF,0xBDC7,0x7CBF,0x7CBF,0x5BB7,0x3BB7,0x3BB7,0x3AB7,0x3AAF,0x1BAF,0x1BAF,0x1BA7,0xFBA6,0xFBA6,0x1BAF,0xDAA6,0x1BAF,0xFBAE,0xDAA6,0x1BAF,0xFAAE,0xDAAE,0x1BAF,0x3BB7,0x1BAF,0xDAA6,0x1BAF,0x1BAF,0x5CB7,0x5CB7,0x7CB7,0x7CBF,0x7CBF,0x5CB7,0x5CB7,0x5CB7,0x7CBF,0x7CBF,0x5CB7,0x7CB7,0x5CB7,0x3BAF,0x3BAF,0x3CB7,0x3CB7,0x3CAF,0x3CAF,0x3CAF,0x3CAF,0x1CAF,0x1CAF,0x5CAF,0x3CAF,0xFBA6,0xFB9E,0x1B9F,0x3BA7,0x3CAF,0x7DB7,0x3CAF,0xFCA6,0x3DAF,0xDCA6,0xFCA6,0xBB9E,0xBB9E,0xFC9E,0xDA9E,0x2B33,0x7485,0x1BBF,0x58AE,0x472A,0xA409,0x7154, 108 | 0xD7C6,0xF7C6,0xD7C6,0xD7C6,0xD7C6,0xD7C6,0xD7CE,0xD7C6,0xF8CE,0xD7C6,0xD7C6,0xD7C6,0xD7C6,0xD7C6,0xD7C6,0xD7C6,0xD7CE,0xB7C6,0xB7C6,0xB7C6,0xB7C6,0x97C6,0xB7C6,0xD7CE,0xB7CE,0x96C6,0xD7C6,0xF8CE,0xF8CE,0xF8CE,0xD7CE,0xD7CE,0xD7C6,0xB6C6,0xD7C6,0xD7C6,0x96BE,0x75BE,0x76BE,0xB7C6,0xB7C6,0xB6C6,0x96C6,0x96C6,0xB6C6,0xB6C6,0xB7C6,0xB7C6,0x97C6,0x76BE,0x76BE,0x76BE,0x76BE,0x76BE,0x56BE,0x96C6,0x56BE,0x56BE,0x77BE,0x36B6,0x16AE,0xF5AD,0xF5AD,0xF4A5,0x15A6,0x35AE,0x56BE,0x56BE,0x97BE,0x57B6,0x38B6,0x59B6,0x99BE,0xB9BE,0xBAC6,0xFBCE,0x1BC7,0x7CCF,0x57B6,0x3BD7,0x5CDF,0x5CDF,0x9CEF,0x908C,0x4311, 109 | 0xB8FF,0xB8F7,0x57EF,0x57EF,0x57EF,0x37EF,0x78EF,0x78EF,0x99F7,0x99F7,0xB9F7,0xB9F7,0xB9FF,0xD9FF,0xD9FF,0xB9FF,0x98FF,0x98FF,0x78F7,0x78F7,0x78F7,0x99FF,0x78F7,0x57F7,0x57F7,0x98FF,0x57F7,0x57F7,0x77F7,0x57EF,0x98F7,0x98F7,0xB8FF,0x77F7,0x77F7,0x97F7,0x57F7,0x98FF,0x77F7,0x36EF,0x77F7,0x57EF,0x37EF,0x57EF,0x57EF,0x57EF,0x57EF,0x57EF,0x98F7,0x57EF,0x77F7,0x98F7,0x78F7,0x78F7,0x78F7,0x99FF,0x99F7,0x58EF,0x38EF,0x38EF,0xF7E6,0x95D6,0x75D6,0x75D6,0x54CE,0xB2BD,0x91BD,0xB2BD,0xB2BD,0x92B5,0x73B5,0x32AD,0xAF94,0x0C84,0x4A6B,0xC85A,0x4642,0xE431,0x253A,0x4642,0xE539,0x2542,0x8652,0x086B,0x296B, 110 | 0xF4EE,0xB3E6,0xF4EE,0x15F7,0xD4EE,0xD4EE,0x36F7,0x56FF,0x56FF,0x77FF,0x36F7,0xF5EE,0x36F7,0x36F7,0x15F7,0x36FF,0x55F7,0x55F7,0x96FF,0x76FF,0x15F7,0x56FF,0x35F7,0x35FF,0x15F7,0x35FF,0xF5F6,0x15F7,0x56FF,0x56FF,0x36FF,0x76FF,0x56FF,0x55FF,0x14F7,0xF4EE,0xD3EE,0xF4F6,0x15F7,0x35FF,0x35FF,0x35F7,0x76FF,0x97FF,0x76FF,0x35F7,0xF4EE,0x93E6,0xD3E6,0x34EF,0x14EF,0xD3E6,0xF4EE,0x35F7,0x15F7,0xF5EE,0x15EF,0x15EF,0x14EF,0x15F7,0x56F7,0x56F7,0x56F7,0x77FF,0x98FF,0x98FF,0xD5F6,0x93E6,0xD4F6,0x36F7,0x98FF,0x77F7,0x35EF,0x15EF,0x15F7,0x56F7,0x76F7,0x97F7,0x97FF,0xB8FF,0xD8FF,0xD7FF,0xB7FF,0x96FF,0x56FF, 111 | 0x75FF,0x55FF,0x75FF,0x75FF,0x54FF,0x14FF,0x14FF,0xF3FE,0x14FF,0x55FF,0x55FF,0x34FF,0xD3F6,0x92EE,0x92EE,0xD3F6,0xD2EE,0xB2EE,0x14F7,0x75FF,0x13F7,0xF3F6,0x14F7,0x14F7,0x14FF,0xF4F6,0x35FF,0x96FF,0x75FF,0x55FF,0x35FF,0xF3FE,0x14FF,0x34FF,0x34FF,0x34FF,0x34FF,0x34FF,0x34FF,0x34FF,0xF4F6,0x34FF,0xF4F6,0xB3EE,0xD3EE,0x55FF,0x96FF,0x96FF,0x55FF,0x54FF,0x34FF,0x34FF,0x55FF,0x75FF,0x55FF,0x75FF,0x54FF,0x34FF,0x34FF,0x34FF,0xF3F6,0x13F7,0x55FF,0x55FF,0x56FF,0x56FF,0x56FF,0x55FF,0x34FF,0xF3F6,0xF4EE,0x75FF,0x95FF,0x74FF,0x54FF,0x54FF,0x74FF,0xD6FF,0xB6FF,0x75FF,0xD2EE,0xF2EE,0xF2EE,0xF2EE,0xF3F6, 112 | 0xB2F6,0x0FDE,0x50E6,0x12FF,0xD2F6,0x4FE6,0x4FE6,0x70EE,0xB1F6,0x70EE,0x91EE,0x2FE6,0xAED5,0x91EE,0x75FF,0x13FF,0x75FF,0x34FF,0xB2EE,0xB2F6,0xB2EE,0xD3EE,0x55FF,0x96FF,0xD7FF,0xB7FF,0x75FF,0x34FF,0x33FF,0x33FF,0x13FF,0xD2F6,0x30DE,0x10DE,0x30DE,0x92E6,0xD3F6,0x34FF,0x55FF,0x34FF,0x14F7,0x34FF,0x35FF,0x96FF,0x96FF,0x34F7,0xD3EE,0x14F7,0x35FF,0x35FF,0x55FF,0x35FF,0x14FF,0x14FF,0x35FF,0x55FF,0x54FF,0x75FF,0x74FF,0x33FF,0x13FF,0xF2F6,0xD2F6,0xB2F6,0x93F6,0xD3F6,0xF3FE,0x71EE,0x72EE,0xB2EE,0xB2EE,0xF2F6,0xD1F6,0xD1F6,0xD1FE,0xB1F6,0x2FE6,0xADD5,0xCED5,0x0FD6,0xF3F6,0x54F7,0x95FF,0x75FF,0x34FF, 113 | 0x0FDE,0x50EE,0x50E6,0x0FE6,0x0FE6,0x2FE6,0x0FE6,0x0EDE,0x0FE6,0x0FE6,0x70EE,0xF2FE,0x34FF,0xF3FE,0x91EE,0x71EE,0x71EE,0xD2F6,0xD2F6,0x13FF,0x54FF,0x34FF,0x35F7,0x15F7,0x14F7,0xD3EE,0x14F7,0x54FF,0xF3F6,0x70E6,0xEFD5,0x8DC5,0x10DE,0x71E6,0x72E6,0x92EE,0xF3F6,0x13F7,0x13F7,0x34FF,0x75FF,0x75FF,0x75FF,0x76FF,0x96FF,0x55FF,0x55FF,0x75FF,0xD3FE,0x92F6,0xB3F6,0x34FF,0x14FF,0xB2F6,0xB2F6,0xB2F6,0xD2F6,0xD2F6,0x50EE,0x0FDE,0x2FE6,0x70EE,0xD1F6,0x33FF,0x34FF,0xF3FE,0x50EE,0xB2EE,0x14FF,0x34FF,0x33FF,0xD2F6,0x91F6,0xB1F6,0xB1F6,0xB0F6,0xB1F6,0xD2F6,0x13FF,0x34FF,0x55FF,0x34FF,0xF3F6,0xB2EE,0xB2F6, 114 | 0xF2FE,0xF2FE,0x54FF,0x95FF,0x54FF,0x55FF,0x75FF,0x34FF,0x75FF,0xB6FF,0x75FF,0x13FF,0x14FF,0xF3FE,0x91EE,0x50E6,0x50E6,0x2FE6,0x70EE,0xF2FE,0x13FF,0x34FF,0x35FF,0xF4EE,0xD4EE,0x35FF,0x56FF,0x35FF,0x35FF,0x56FF,0x56FF,0x36FF,0x35FF,0x15FF,0x55FF,0x76FF,0x55FF,0x55FF,0x75FF,0x35FF,0x55FF,0x96FF,0x96FF,0x14FF,0x71E6,0x71E6,0x92EE,0x92EE,0x71EE,0x10E6,0xCFDD,0xAED5,0xCEDD,0x70EE,0x33FF,0x54FF,0x54FF,0x34FF,0x13FF,0xF2FE,0x70EE,0x2FE6,0x2EE6,0x0EE6,0x0FDE,0x8DCD,0x0FDE,0x30E6,0xB2EE,0x14FF,0x91EE,0xF3FE,0x35FF,0x55FF,0x75FF,0x54FF,0x13FF,0x13FF,0x54FF,0x75FF,0x76FF,0x55FF,0x54FF,0x54FF,0x55FF, 115 | 0x50EE,0x30E6,0xEFDD,0xCFDD,0x10E6,0x71EE,0xB3F6,0x14FF,0x14FF,0xD3FE,0xF3FE,0xF4FE,0xB2F6,0xB2F6,0xF3F6,0xD2F6,0xF3F6,0xF3FE,0x34FF,0x34FF,0x14FF,0x34FF,0x76FF,0x96FF,0x76FF,0x76FF,0xF4FE,0xD4FE,0x35FF,0x15FF,0xF4F6,0x56FF,0x56FF,0x96FF,0x76FF,0x35FF,0x14FF,0xD3F6,0x71EE,0x92EE,0x91EE,0x50EE,0x51EE,0x91F6,0x92F6,0xD2FE,0x13FF,0x13FF,0x13FF,0xD2FE,0xB1FE,0x91F6,0x70EE,0x4FE6,0x70EE,0xB1F6,0xF2FE,0xB2F6,0x91F6,0xB1F6,0x91F6,0x90F6,0x70F6,0x70EE,0xD1F6,0x13FF,0x53FF,0x54FF,0x33FF,0x13FF,0x14FF,0x14FF,0xD4FE,0xD4FE,0xF4FE,0x14FF,0xF3FE,0xD2FE,0xD2F6,0xD3F6,0xF4F6,0xB3F6,0x91F6,0x91FE,0x91F6, 116 | 0xF0DD,0x10E6,0x51EE,0xB2F6,0xD3FE,0xF3FE,0xF3FE,0xD3F6,0xD3FE,0xD3F6,0xB3F6,0xF3FE,0x14FF,0xF4FE,0xD3F6,0x35FF,0x36FF,0x56FF,0x35FF,0x15FF,0x76FF,0x55FF,0x55FF,0xD3F6,0x30E6,0xCED5,0xADD5,0xCDDD,0x2FE6,0xF2FE,0x74FF,0x54FF,0xD3FE,0x30E6,0xCFDD,0xCEDD,0x0FE6,0x71F6,0x91F6,0x50F6,0x50F6,0x70F6,0x70F6,0x2FF6,0xCDE5,0xACDD,0xACDD,0xCDDD,0xCDDD,0x2EEE,0x90F6,0xD2FE,0x13FF,0x33FF,0xD2FE,0x70EE,0x70EE,0xD2FE,0xF2FE,0xF3FE,0x34FF,0x13FF,0xD2FE,0xD2FE,0xF2FE,0xB1F6,0x2FE6,0x0FE6,0xEEED,0xEEED,0x50F6,0x71F6,0xB2FE,0xF3FE,0xF3FE,0xB2FE,0xB1F6,0xD2F6,0xF3F6,0xF3F6,0x14F7,0x34FF,0x34FF,0xF3FE,0xB2FE, 117 | 0x34FF,0x35FF,0x34FF,0x34FF,0x14FF,0xF3FE,0xD2FE,0xD2FE,0xD3FE,0xD3FE,0xB2F6,0x92F6,0xD3FE,0x34FF,0x55FF,0x56FF,0x77FF,0x57FF,0x56FF,0x76FF,0xF4FE,0x71EE,0xD3FE,0x71EE,0x30EE,0x0FE6,0x0FEE,0x4FEE,0x4FEE,0x2EEE,0xEEDD,0xCEDD,0x30E6,0x71F6,0x91F6,0x50EE,0xCEE5,0x4CD5,0x2CCD,0x4CD5,0x6CD5,0x6CDD,0x8CDD,0xCDE5,0x2FF6,0x2FF6,0x2FF6,0x4FF6,0x70F6,0x70F6,0x0FE6,0xCEDD,0xCEDD,0xAEDD,0xAEDD,0xCEDD,0x0FE6,0x50EE,0x71F6,0x0FE6,0x6DD5,0x4DD5,0x8EDD,0x8EDD,0xCEE5,0x0FE6,0x50EE,0x70F6,0x50F6,0x50F6,0x70FE,0x71F6,0x91FE,0x91FE,0x91FE,0xB2FE,0xD2FE,0xF3FE,0x14FF,0x34FF,0x55FF,0x34FF,0xB2FE,0x2FEE,0xEFE5, 118 | 0xB2FE,0x70F6,0xEFE5,0xADDD,0xADDD,0xCEE5,0xEEE5,0x0EE6,0x2FEE,0x70F6,0xB2FE,0xD2FE,0xD2FE,0xD2FE,0xF2FE,0xF3FE,0xB2FE,0x71EE,0x10E6,0x0FE6,0xEFE5,0xCEE5,0xEFE5,0x30EE,0x91FE,0xF3FE,0x13FF,0x74FF,0x54FF,0x34FF,0xF3FE,0x71F6,0x0FE6,0x10E6,0xEFE5,0xCFE5,0xEFE5,0xEFE5,0xEFE5,0xEFE5,0x0FE6,0xEFE5,0x10E6,0xEFE5,0xCFE5,0xEFED,0x91FE,0xF3FE,0x34FF,0x14FF,0xF3FE,0xB2FE,0x92F6,0x92F6,0x71F6,0x51F6,0x30EE,0x0FEE,0x10EE,0x30EE,0x51EE,0x31EE,0x31EE,0x10EE,0x10EE,0x30EE,0x30EE,0x30EE,0x2FEE,0x30EE,0x70F6,0x91FE,0xB2FE,0xB2FE,0xB2FE,0x92FE,0xB2F6,0xB2F6,0xD2F6,0xD2FE,0xD2FE,0xD2FE,0xD2FE,0xD2FE,0xF2FE, 119 | 0x8DDD,0xADDD,0xCEE5,0x0EEE,0x0FEE,0xEEED,0xADE5,0x8DDD,0x8DDD,0x8DDD,0x6DD5,0x4CD5,0x2CCD,0x0CCD,0x0BC5,0xEAC4,0xCAC4,0xCAC4,0x0BCD,0x8DDD,0x0FEE,0x70F6,0xB2FE,0xD2FE,0xD2FE,0xF3FE,0xB2FE,0x91FE,0x30EE,0x30EE,0x50F6,0x71F6,0xB1FE,0xD2FE,0xB2FE,0x91FE,0x91FE,0x71F6,0x71F6,0x50F6,0x91F6,0x91F6,0xB2FE,0xD3FE,0xF3FE,0xF3FE,0xF3FE,0xD2FE,0xF3FE,0xD3F6,0xB2F6,0xB3FE,0xD3FE,0xD3FE,0xF3FE,0x13FF,0x13FF,0x13FF,0x13FF,0x33FF,0x14FF,0xF3FE,0xF3FE,0xF4FE,0x34FF,0x14FF,0xF4FE,0x14FF,0xF3FE,0xD2FE,0x91F6,0x70F6,0xB2FE,0xD2FE,0xD3FE,0xB3FE,0x92FE,0x91FE,0xB1FE,0xD1FE,0xB1FE,0x91FE,0x91FE,0x91FE,0x71F6, 120 | 0x2FF6,0x4FFE,0x70FE,0x90FE,0x70FE,0x2FF6,0x0FEE,0x0FEE,0xEFE5,0x0FE6,0x10E6,0x10E6,0x30E6,0x51EE,0x71EE,0x92F6,0xD3FE,0xF3FE,0x14FF,0xF3FE,0x71FE,0x0FEE,0x0FEE,0x0FEE,0x30F6,0x0FEE,0xADDD,0xADDD,0xADDD,0xCDDD,0xCDE5,0xCDE5,0xEDED,0x2EEE,0x4FF6,0x50FE,0x50F6,0x2FF6,0x0EEE,0xEEED,0x0EEE,0xCEE5,0xAEE5,0x8DDD,0xADE5,0xCEED,0x2EF6,0x4FFE,0x50F6,0x50F6,0x71F6,0x91FE,0x50F6,0xAEE5,0x2BD5,0xEACC,0x0ACD,0x0BCD,0x4BD5,0x6CDD,0xADDD,0x2FEE,0xB1FE,0x13FF,0x34FF,0x35FF,0x14FF,0xF4FE,0x14FF,0x34FF,0xF3FE,0x91FE,0x4CD5,0x2CD5,0x0CD5,0x0CD5,0x4DDD,0xAEED,0x0EF6,0x2FF6,0x91FE,0xB1FE,0xB2FE,0xD2FE,0xD2FE, 121 | 0x4CDD,0x4CDD,0x4CDD,0x6CDD,0xADE5,0x0FEE,0x91FE,0xF3FE,0x54FF,0x55FF,0x55FF,0x55FF,0x35FF,0xF4FE,0x72F6,0x10EE,0xAEE5,0x8EE5,0xAEE5,0xCEE5,0x0FF6,0x2FF6,0x0FF6,0xEEED,0xADE5,0xCEE5,0xCEE5,0xCEE5,0xCDE5,0xEEED,0x4FF6,0x90FE,0xD1FE,0x70FE,0x2FF6,0xADE5,0x6CDD,0x8DDD,0xCDE5,0x0EEE,0x2FEE,0x30EE,0x50F6,0x50F6,0x0FEE,0xEEED,0xEDED,0xCDED,0x2FF6,0x50FE,0x50FE,0x0FF6,0x6DE5,0x0BD5,0x4BDD,0x8CE5,0x8CDD,0x8CE5,0xACE5,0xACE5,0x8CDD,0x6CD5,0x6CD5,0x6CCD,0xCFDD,0x51E6,0x92F6,0xB2F6,0xB2F6,0x71F6,0xEFE5,0x4CD5,0x8DDD,0xAEE5,0xCFED,0xCFED,0x8EED,0x6DE5,0x4BDD,0x2BDD,0x2BD5,0x2CD5,0x2CD5,0x4CDD,0x4CDD, 122 | 0x71F6,0xB2FE,0xD3FE,0xD3FE,0xB2FE,0x92F6,0x51F6,0x30EE,0xCFE5,0xCFE5,0x8EDD,0x4CD5,0xCBCC,0xAAC4,0xCACC,0xEBCC,0x0BD5,0x2BD5,0x6CDD,0x8DE5,0xADE5,0x0EEE,0x2FF6,0x4FFE,0x90FE,0x70FE,0x50F6,0x2FF6,0x4FF6,0x70FE,0x70FE,0x4FF6,0x2FEE,0x30EE,0x92FE,0xD2FE,0xD3FE,0xF3FE,0xF3FE,0x13FF,0x14FF,0xF4FE,0x14FF,0xF4FE,0xD3FE,0x91FE,0x2FF6,0xEEED,0x4CDD,0x2BDD,0x0AD5,0xEAD4,0x0BD5,0x2BDD,0x8CE5,0xADED,0x2EF6,0x2FF6,0x4FFE,0x6FFE,0x70FE,0x90FE,0xB1FE,0xB1FE,0x91F6,0x71F6,0x71F6,0x50F6,0x50EE,0x50F6,0x70F6,0x91FE,0x91FE,0x72FE,0x72FE,0x92FE,0xB3FE,0x92FE,0x51FE,0x0FF6,0x8DE5,0x6DDD,0x2CDD,0x2CD5,0x2CD5, 123 | }; 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | #endif /* BITMAP_H_ */ 133 | -------------------------------------------------------------------------------- /st7789/st7789.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ****************************************************************************** 4 | * @file ( фаил ): ST7789.c 5 | * @brief ( описание ): 6 | ****************************************************************************** 7 | * @attention ( внимание ): author: Golinskiy Konstantin e-mail: golinskiy.konstantin@gmail.com 8 | ****************************************************************************** 9 | 10 | */ 11 | 12 | #include 13 | 14 | 15 | uint16_t ST7789_X_Start = ST7789_XSTART; 16 | uint16_t ST7789_Y_Start = ST7789_YSTART; 17 | 18 | uint16_t ST7789_Width = 0; 19 | uint16_t ST7789_Height = 0; 20 | 21 | #if FRAME_BUFFER 22 | // массив буфер кадра 23 | uint16_t buff_frame[ST7789_WIDTH*ST7789_HEIGHT] = { 0x0000, }; 24 | #endif 25 | 26 | static void ST7789_ExecuteCommandList(const uint8_t *addr); 27 | static void ST7789_Unselect(void); 28 | static void ST7789_Select(void); 29 | static void ST7789_SendCmd(uint8_t Cmd); 30 | static void ST7789_SendData(uint8_t Data ); 31 | static void ST7789_SendDataMASS(uint8_t* buff, size_t buff_size); 32 | static void ST7789_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); 33 | static void ST7789_RamWrite(uint16_t *pBuff, uint32_t Len); 34 | static void ST7789_ColumnSet(uint16_t ColumnStart, uint16_t ColumnEnd); 35 | static void ST7789_RowSet(uint16_t RowStart, uint16_t RowEnd); 36 | static void SwapInt16Values(int16_t *pValue1, int16_t *pValue2); 37 | static void ST7789_DrawLine_Slow(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); 38 | 39 | 40 | //==== данные для инициализации дисплея ST7789_240X320 ========== 41 | 42 | // инициализация для всех дисплеев одна, так как драйвер расчитан на максимальный размер 240x320 43 | // для подгона пор свой размер двигаем в функции ротации дисплея 44 | static const uint8_t init_cmds[] = { 45 | 9, // 9 commands in list: 46 | ST7789_SWRESET, DELAY, // 1: Software reset, no args, w/delay 47 | 150, // 150 ms delay 48 | ST7789_SLPOUT , DELAY, // 2: Out of sleep mode, no args, w/delay 49 | 255, // 255 = 500 ms delay 50 | ST7789_COLMOD , 1+DELAY, // 3: Set color mode, 1 arg + delay: 51 | (ST7789_ColorMode_65K | ST7789_ColorMode_16bit), // 16-bit color 0x55 52 | 10, // 10 ms delay 53 | ST7789_MADCTL , 1, // 4: Memory access ctrl (directions), 1 arg: 54 | ST7789_ROTATION, // Row addr/col addr, bottom to top refresh 55 | ST7789_CASET , 4, // 5: Column addr set, 4 args, no delay: 56 | ST7789_XSTART>>8,ST7789_XSTART&0xff, // XSTART = 0>>8, 0&0xff, 57 | (ST7789_WIDTH-1)>>8,(ST7789_WIDTH-1)&0xff, // XEND = (320-1)>>8,(320-1)&0xff, 58 | ST7789_RASET , 4, // 6: Row addr set, 4 args, no delay: 59 | ST7789_YSTART>>8,ST7789_YSTART&0xff, // YSTART = 0>>8, 0&0xff, 60 | (ST7789_HEIGHT-1)>>8,(ST7789_HEIGHT-1)&0xff, // YEND = (320-1)>>8,(320-1)&0xff, 61 | ST7789_INVERSION , DELAY, // 7: Inversion ON 62 | 10, 63 | ST7789_NORON , DELAY, // 8: Normal display on, no args, w/delay 64 | 10, // 10 ms delay 65 | ST7789_DISPON , DELAY, // 9: Main screen turn on, no args, w/delay 66 | 10 67 | }; 68 | //--------------------------------------------------------------------------------------------- 69 | 70 | //=============================================================== 71 | 72 | 73 | //############################################################################## 74 | 75 | 76 | //============================================================================== 77 | 78 | 79 | 80 | //============================================================================== 81 | // Процедура инициализации дисплея 82 | //============================================================================== 83 | void ST7789_Init(void){ 84 | 85 | // Задержка после подачи питания 86 | // если при старте не всегда запускаеться дисплей увеличиваем время задержки 87 | HAL_Delay(200); 88 | 89 | ST7789_Width = ST7789_WIDTH; 90 | ST7789_Height = ST7789_HEIGHT; 91 | 92 | ST7789_Select(); 93 | 94 | ST7789_HardReset(); 95 | ST7789_ExecuteCommandList(init_cmds); 96 | 97 | ST7789_Unselect(); 98 | 99 | #if FRAME_BUFFER 100 | ST7789_ClearFrameBuffer(); 101 | #endif 102 | 103 | } 104 | //============================================================================== 105 | 106 | 107 | //============================================================================== 108 | // Процедура управления SPI 109 | //============================================================================== 110 | static void ST7789_Select(void) { 111 | 112 | #ifdef CS_PORT 113 | 114 | //-- если захотим переделать под HAL ------------------ 115 | #ifdef ST7789_SPI_HAL 116 | HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); 117 | #endif 118 | //----------------------------------------------------- 119 | 120 | //-- если захотим переделать под CMSIS --------------- 121 | #ifdef ST7789_SPI_CMSIS 122 | CS_GPIO_Port->BSRR = ( CS_Pin << 16 ); 123 | #endif 124 | //----------------------------------------------------- 125 | #endif 126 | 127 | } 128 | //============================================================================== 129 | 130 | 131 | //============================================================================== 132 | // Процедура управления SPI 133 | //============================================================================== 134 | static void ST7789_Unselect(void) { 135 | 136 | #ifdef CS_PORT 137 | 138 | //-- если захотим переделать под HAL ------------------ 139 | #ifdef ST7789_SPI_HAL 140 | HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); 141 | #endif 142 | //----------------------------------------------------- 143 | 144 | //-- если захотим переделать под CMSIS --------------- 145 | #ifdef ST7789_SPI_CMSIS 146 | CS_GPIO_Port->BSRR = CS_Pin; 147 | #endif 148 | //----------------------------------------------------- 149 | 150 | #endif 151 | 152 | } 153 | //============================================================================== 154 | 155 | 156 | //============================================================================== 157 | // Процедура отправки данных для инициализации дисплея 158 | //============================================================================== 159 | static void ST7789_ExecuteCommandList(const uint8_t *addr) { 160 | 161 | uint8_t numCommands, numArgs; 162 | uint16_t ms; 163 | 164 | numCommands = *addr++; 165 | while(numCommands--) { 166 | uint8_t cmd = *addr++; 167 | ST7789_SendCmd(cmd); 168 | 169 | numArgs = *addr++; 170 | // If high bit set, delay follows args 171 | ms = numArgs & DELAY; 172 | numArgs &= ~DELAY; 173 | if(numArgs) { 174 | ST7789_SendDataMASS((uint8_t*)addr, numArgs); 175 | addr += numArgs; 176 | } 177 | 178 | if(ms) { 179 | ms = *addr++; 180 | if(ms == 255) ms = 500; 181 | HAL_Delay(ms); 182 | } 183 | } 184 | } 185 | //============================================================================== 186 | 187 | 188 | //============================================================================== 189 | // Процедура вывода цветного изображения на дисплей 190 | //============================================================================== 191 | void ST7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data) { 192 | 193 | if((x >= ST7789_Width) || (y >= ST7789_Height)){ 194 | return; 195 | } 196 | 197 | if((x + w - 1) >= ST7789_Width){ 198 | return; 199 | } 200 | 201 | if((y + h - 1) >= ST7789_Height){ 202 | return; 203 | } 204 | 205 | #if FRAME_BUFFER // если включен буфер кадра 206 | for( uint16_t i = 0; i < h; i++ ){ 207 | for( uint16_t j = 0; j < w; j++ ){ 208 | buff_frame[( y + i ) * ST7789_Width + x + j] = *data; 209 | data++; 210 | } 211 | } 212 | #else //если попиксельный вывод 213 | ST7789_SetWindow(x, y, x+w-1, y+h-1); 214 | 215 | ST7789_Select(); 216 | 217 | ST7789_SendDataMASS((uint8_t*)data, sizeof(uint16_t)*w*h); 218 | 219 | ST7789_Unselect(); 220 | #endif 221 | } 222 | //============================================================================== 223 | 224 | 225 | //============================================================================== 226 | // Процедура аппаратного сброса дисплея (ножкой RESET) 227 | //============================================================================== 228 | void ST7789_HardReset(void){ 229 | 230 | HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_RESET); 231 | HAL_Delay(20); 232 | HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_SET); 233 | 234 | } 235 | //============================================================================== 236 | 237 | 238 | //============================================================================== 239 | // Процедура отправки команды в дисплей 240 | //============================================================================== 241 | __inline static void ST7789_SendCmd(uint8_t Cmd){ 242 | 243 | //-- если захотим переделать под HAL ------------------ 244 | #ifdef ST7789_SPI_HAL 245 | 246 | // pin DC LOW 247 | HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET); 248 | 249 | HAL_SPI_Transmit(&ST7789_SPI_HAL, &Cmd, 1, HAL_MAX_DELAY); 250 | while(HAL_SPI_GetState(&ST7789_SPI_HAL) != HAL_SPI_STATE_READY){}; 251 | 252 | // pin DC HIGH 253 | HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_SET); 254 | 255 | #endif 256 | //----------------------------------------------------- 257 | 258 | //-- если захотим переделать под CMSIS --------------------------------------------- 259 | #ifdef ST7789_SPI_CMSIS 260 | 261 | // pin DC LOW 262 | DC_GPIO_Port->BSRR = ( DC_Pin << 16 ); 263 | 264 | //====== FOR F-SERIES =========================================================== 265 | 266 | // Disable SPI 267 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 &= ~SPI_CR1_SPE; 268 | // Enable SPI 269 | if((ST7789_SPI_CMSIS->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ 270 | // If disabled, I enable it 271 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_SPE; 272 | } 273 | 274 | // Ждем, пока не освободится буфер передатчика 275 | // TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных 276 | while( (ST7789_SPI_CMSIS->SR & SPI_SR_TXE) == RESET ){}; 277 | 278 | // заполняем буфер передатчика 1 байт информации-------------- 279 | *((__IO uint8_t *)&ST7789_SPI_CMSIS->DR) = Cmd; 280 | 281 | // TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных 282 | while( (ST7789_SPI_CMSIS->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE ){}; 283 | 284 | //Ждем, пока SPI освободится от предыдущей передачи 285 | //while((ST7789_SPI_CMSIS->SR&SPI_SR_BSY)){}; 286 | 287 | // Disable SPI 288 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); 289 | 290 | //================================================================================ 291 | 292 | /* //====== FOR H-SERIES =========================================================== 293 | 294 | // Disable SPI 295 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 &= ~SPI_CR1_SPE; 296 | // Enable SPI 297 | // Enable SPI 298 | if((ST7789_SPI_CMSIS->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ 299 | // If disabled, I enable it 300 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_SPE; 301 | } 302 | 303 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_CSTART); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_CSTART; 304 | 305 | // ждем пока SPI будет свободна------------ 306 | //while (!(ST7789_SPI_CMSIS->SR & SPI_SR_TXP)){}; 307 | 308 | // передаем 1 байт информации-------------- 309 | *((__IO uint8_t *)&ST7789_SPI_CMSIS->TXDR ) = Cmd; 310 | 311 | // Ждать завершения передачи--------------- 312 | while (!( ST7789_SPI_CMSIS -> SR & SPI_SR_TXC )){}; 313 | 314 | // Disable SPI 315 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); 316 | 317 | */ //================================================================================ 318 | 319 | // pin DC HIGH 320 | DC_GPIO_Port->BSRR = DC_Pin; 321 | 322 | #endif 323 | //----------------------------------------------------------------------------------- 324 | 325 | } 326 | //============================================================================== 327 | 328 | 329 | //============================================================================== 330 | // Процедура отправки данных (параметров) в дисплей 1 BYTE 331 | //============================================================================== 332 | __inline static void ST7789_SendData(uint8_t Data ){ 333 | 334 | //-- если захотим переделать под HAL ------------------ 335 | #ifdef ST7789_SPI_HAL 336 | 337 | HAL_SPI_Transmit(&ST7789_SPI_HAL, &Data, 1, HAL_MAX_DELAY); 338 | while(HAL_SPI_GetState(&ST7789_SPI_HAL) != HAL_SPI_STATE_READY){}; 339 | 340 | #endif 341 | //----------------------------------------------------- 342 | 343 | 344 | //-- если захотим переделать под CMSIS --------------------------------------------- 345 | #ifdef ST7789_SPI_CMSIS 346 | 347 | //====== FOR F-SERIES =========================================================== 348 | 349 | // Disable SPI 350 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 &= ~SPI_CR1_SPE; 351 | // Enable SPI 352 | if((ST7789_SPI_CMSIS->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ 353 | // If disabled, I enable it 354 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_SPE; 355 | } 356 | 357 | // Ждем, пока не освободится буфер передатчика 358 | // TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных 359 | while( (ST7789_SPI_CMSIS->SR & SPI_SR_TXE) == RESET ){}; 360 | 361 | // передаем 1 байт информации-------------- 362 | *((__IO uint8_t *)&ST7789_SPI_CMSIS->DR) = Data; 363 | 364 | // TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных 365 | while( (ST7789_SPI_CMSIS->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE ){}; 366 | 367 | // Ждем, пока не освободится буфер передатчика 368 | //while((ST7789_SPI_CMSIS->SR&SPI_SR_BSY)){}; 369 | 370 | // Disable SPI 371 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); 372 | 373 | //================================================================================ 374 | 375 | /* //====== FOR H-SERIES =========================================================== 376 | 377 | // Disable SPI 378 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 &= ~SPI_CR1_SPE; 379 | // Enable SPI 380 | if((ST7789_SPI_CMSIS->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ 381 | // If disabled, I enable it 382 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_SPE; 383 | } 384 | 385 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_CSTART); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_CSTART; 386 | 387 | // ждем пока SPI будет свободна------------ 388 | //while (!(ST7789_SPI_CMSIS->SR & SPI_SR_TXP)){}; 389 | 390 | // передаем 1 байт информации-------------- 391 | *((__IO uint8_t *)&ST7789_SPI_CMSIS->TXDR ) = Data; 392 | 393 | // Ждать завершения передачи--------------- 394 | while (!( ST7789_SPI_CMSIS -> SR & SPI_SR_TXC )){}; 395 | 396 | // Disable SPI 397 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); 398 | 399 | */ //================================================================================ 400 | 401 | #endif 402 | //----------------------------------------------------------------------------------- 403 | 404 | } 405 | //============================================================================== 406 | 407 | 408 | //============================================================================== 409 | // Процедура отправки данных (параметров) в дисплей MASS 410 | //============================================================================== 411 | __inline static void ST7789_SendDataMASS(uint8_t* buff, size_t buff_size){ 412 | 413 | //-- если захотим переделать под HAL ------------------ 414 | #ifdef ST7789_SPI_HAL 415 | 416 | if( buff_size <= 0xFFFF ){ 417 | HAL_SPI_Transmit(&ST7789_SPI_HAL, buff, buff_size, HAL_MAX_DELAY); 418 | } 419 | else{ 420 | while( buff_size > 0xFFFF ){ 421 | HAL_SPI_Transmit(&ST7789_SPI_HAL, buff, 0xFFFF, HAL_MAX_DELAY); 422 | buff_size-=0xFFFF; 423 | buff+=0xFFFF; 424 | } 425 | HAL_SPI_Transmit(&ST7789_SPI_HAL, buff, buff_size, HAL_MAX_DELAY); 426 | } 427 | 428 | while(HAL_SPI_GetState(&ST7789_SPI_HAL) != HAL_SPI_STATE_READY){}; 429 | 430 | #endif 431 | //----------------------------------------------------- 432 | 433 | 434 | //-- если захотим переделать под CMSIS --------------------------------------------- 435 | #ifdef ST7789_SPI_CMSIS 436 | 437 | //====== FOR F-SERIES =========================================================== 438 | 439 | // Disable SPI 440 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 &= ~SPI_CR1_SPE; 441 | // Enable SPI 442 | if((ST7789_SPI_CMSIS->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ 443 | // If disabled, I enable it 444 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_SPE; 445 | } 446 | 447 | while( buff_size ){ 448 | 449 | // Ждем, пока не освободится буфер передатчика 450 | // TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных 451 | while( (ST7789_SPI_CMSIS->SR & SPI_SR_TXE) == RESET ){}; 452 | 453 | // передаем 1 байт информации-------------- 454 | *((__IO uint8_t *)&ST7789_SPI_CMSIS->DR) = *buff++; 455 | 456 | buff_size--; 457 | } 458 | 459 | // TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных 460 | while( (ST7789_SPI_CMSIS->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE ){}; 461 | 462 | // Ждем, пока не освободится буфер передатчика 463 | // while((ST7789_SPI_CMSIS->SR&SPI_SR_BSY)){}; 464 | 465 | // Disable SPI 466 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); 467 | 468 | //================================================================================ 469 | 470 | /* //====== FOR H-SERIES =========================================================== 471 | 472 | // Disable SPI 473 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 &= ~SPI_CR1_SPE; 474 | // Enable SPI 475 | if((ST7789_SPI_CMSIS->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE){ 476 | // If disabled, I enable it 477 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_SPE; 478 | } 479 | 480 | SET_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_CSTART); // ST7789_SPI_CMSIS->CR1 |= SPI_CR1_CSTART; 481 | 482 | // ждем пока SPI будет свободна------------ 483 | //while (!(ST7789_SPI_CMSIS->SR & SPI_SR_TXP)){}; 484 | 485 | while( buff_size ){ 486 | 487 | // передаем 1 байт информации-------------- 488 | *((__IO uint8_t *)&ST7789_SPI_CMSIS->TXDR ) = *buff++; 489 | 490 | // Ждать завершения передачи--------------- 491 | while (!( ST7789_SPI_CMSIS -> SR & SPI_SR_TXC )){}; 492 | 493 | buff_size--; 494 | 495 | } 496 | 497 | // Disable SPI 498 | //CLEAR_BIT(ST7789_SPI_CMSIS->CR1, SPI_CR1_SPE); 499 | 500 | */ //================================================================================ 501 | 502 | #endif 503 | //----------------------------------------------------------------------------------- 504 | 505 | } 506 | //============================================================================== 507 | 508 | 509 | //============================================================================== 510 | // Процедура включения режима сна 511 | //============================================================================== 512 | void ST7789_SleepModeEnter( void ){ 513 | 514 | ST7789_Select(); 515 | 516 | ST7789_SendCmd(ST7789_SLPIN); 517 | 518 | ST7789_Unselect(); 519 | 520 | HAL_Delay(250); 521 | } 522 | //============================================================================== 523 | 524 | 525 | //============================================================================== 526 | // Процедура отключения режима сна 527 | //============================================================================== 528 | void ST7789_SleepModeExit( void ){ 529 | 530 | ST7789_Select(); 531 | 532 | ST7789_SendCmd(ST7789_SLPOUT); 533 | 534 | ST7789_Unselect(); 535 | 536 | HAL_Delay(250); 537 | } 538 | //============================================================================== 539 | 540 | 541 | //============================================================================== 542 | // Процедура включения/отключения режима частичного заполнения экрана 543 | //============================================================================== 544 | void ST7789_InversionMode(uint8_t Mode){ 545 | 546 | ST7789_Select(); 547 | 548 | if (Mode){ 549 | ST7789_SendCmd(ST7789_INVON); 550 | } 551 | else{ 552 | ST7789_SendCmd(ST7789_INVOFF); 553 | } 554 | 555 | ST7789_Unselect(); 556 | } 557 | //============================================================================== 558 | 559 | 560 | //============================================================================== 561 | // Процедура закрашивает экран цветом color 562 | //============================================================================== 563 | void ST7789_FillScreen(uint16_t color){ 564 | 565 | ST7789_FillRect(0, 0, ST7789_Width, ST7789_Height, color); 566 | } 567 | //============================================================================== 568 | 569 | 570 | //============================================================================== 571 | // Процедура очистки экрана - закрашивает экран цветом черный 572 | //============================================================================== 573 | void ST7789_Clear(void){ 574 | 575 | ST7789_FillRect(0, 0, ST7789_Width, ST7789_Height, 0); 576 | } 577 | //============================================================================== 578 | 579 | 580 | //============================================================================== 581 | // Процедура заполнения прямоугольника цветом color 582 | //============================================================================== 583 | void ST7789_FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){ 584 | 585 | if ((x >= ST7789_Width) || (y >= ST7789_Height)){ 586 | return; 587 | } 588 | 589 | if ((x + w) > ST7789_Width){ 590 | w = ST7789_Width - x; 591 | } 592 | 593 | if ((y + h) > ST7789_Height){ 594 | h = ST7789_Height - y; 595 | } 596 | 597 | #if FRAME_BUFFER // если включен буфер кадра 598 | if( x >=0 && y >=0 ){ 599 | for( uint16_t i = 0; i < h; i++ ){ 600 | for( uint16_t j = 0; j < w; j++ ){ 601 | buff_frame[( y + i ) * ST7789_Width + x + j] = ((color & 0xFF)<<8) | (color >> 8 ); 602 | } 603 | } 604 | } 605 | #else //если попиксельный вывод 606 | ST7789_SetWindow(x, y, x + w - 1, y + h - 1); 607 | 608 | ST7789_RamWrite(&color, (h * w)); 609 | #endif 610 | } 611 | //============================================================================== 612 | 613 | 614 | //============================================================================== 615 | // Процедура установка границ экрана для заполнения 616 | //============================================================================== 617 | static void ST7789_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){ 618 | 619 | ST7789_Select(); 620 | 621 | ST7789_ColumnSet(x0, x1); 622 | ST7789_RowSet(y0, y1); 623 | 624 | // write to RAM 625 | ST7789_SendCmd(ST7789_RAMWR); 626 | 627 | ST7789_Unselect(); 628 | 629 | } 630 | //============================================================================== 631 | 632 | 633 | //============================================================================== 634 | // Процедура записи данных в дисплей 635 | //============================================================================== 636 | static void ST7789_RamWrite(uint16_t *pBuff, uint32_t Len){ 637 | 638 | ST7789_Select(); 639 | 640 | uint8_t buff[2]; 641 | buff[0] = *pBuff >> 8; 642 | buff[1] = *pBuff & 0xFF; 643 | 644 | while (Len--){ 645 | ST7789_SendDataMASS( buff, 2); 646 | } 647 | 648 | ST7789_Unselect(); 649 | } 650 | //============================================================================== 651 | 652 | 653 | //============================================================================== 654 | // Процедура установки начального и конечного адресов колонок 655 | //============================================================================== 656 | static void ST7789_ColumnSet(uint16_t ColumnStart, uint16_t ColumnEnd){ 657 | 658 | if (ColumnStart > ColumnEnd){ 659 | return; 660 | } 661 | 662 | if (ColumnEnd > ST7789_Width){ 663 | return; 664 | } 665 | 666 | ColumnStart += ST7789_X_Start; 667 | ColumnEnd += ST7789_X_Start; 668 | 669 | ST7789_SendCmd(ST7789_CASET); 670 | ST7789_SendData(ColumnStart >> 8); 671 | ST7789_SendData(ColumnStart & 0xFF); 672 | ST7789_SendData(ColumnEnd >> 8); 673 | ST7789_SendData(ColumnEnd & 0xFF); 674 | 675 | } 676 | //============================================================================== 677 | 678 | 679 | //============================================================================== 680 | // Процедура установки начального и конечного адресов строк 681 | //============================================================================== 682 | static void ST7789_RowSet(uint16_t RowStart, uint16_t RowEnd){ 683 | 684 | if (RowStart > RowEnd){ 685 | return; 686 | } 687 | 688 | if (RowEnd > ST7789_Height){ 689 | return; 690 | } 691 | 692 | RowStart += ST7789_Y_Start; 693 | RowEnd += ST7789_Y_Start; 694 | 695 | ST7789_SendCmd(ST7789_RASET); 696 | ST7789_SendData(RowStart >> 8); 697 | ST7789_SendData(RowStart & 0xFF); 698 | ST7789_SendData(RowEnd >> 8); 699 | ST7789_SendData(RowEnd & 0xFF); 700 | 701 | } 702 | //============================================================================== 703 | 704 | 705 | //============================================================================== 706 | // Процедура управления подсветкой (ШИМ) 707 | //============================================================================== 708 | void ST7789_SetBL(uint8_t Value){ 709 | 710 | // if (Value > 100) 711 | // Value = 100; 712 | 713 | // tmr2_PWM_set(ST77xx_PWM_TMR2_Chan, Value); 714 | 715 | } 716 | //============================================================================== 717 | 718 | 719 | //============================================================================== 720 | // Процедура включения/отключения питания дисплея 721 | //============================================================================== 722 | void ST7789_DisplayPower(uint8_t On){ 723 | 724 | ST7789_Select(); 725 | 726 | if (On){ 727 | ST7789_SendCmd(ST7789_DISPON); 728 | } 729 | else{ 730 | ST7789_SendCmd(ST7789_DISPOFF); 731 | } 732 | 733 | ST7789_Unselect(); 734 | } 735 | //============================================================================== 736 | 737 | 738 | //============================================================================== 739 | // Процедура рисования прямоугольника ( пустотелый ) 740 | //============================================================================== 741 | void ST7789_DrawRectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { 742 | 743 | ST7789_DrawLine(x1, y1, x1, y2, color); 744 | ST7789_DrawLine(x2, y1, x2, y2, color); 745 | ST7789_DrawLine(x1, y1, x2, y1, color); 746 | ST7789_DrawLine(x1, y2, x2, y2, color); 747 | 748 | } 749 | //============================================================================== 750 | 751 | 752 | //============================================================================== 753 | // Процедура вспомогательная для --- Процедура рисования прямоугольника ( заполненый ) 754 | //============================================================================== 755 | static void SwapInt16Values(int16_t *pValue1, int16_t *pValue2){ 756 | 757 | int16_t TempValue = *pValue1; 758 | *pValue1 = *pValue2; 759 | *pValue2 = TempValue; 760 | } 761 | //============================================================================== 762 | 763 | 764 | //============================================================================== 765 | // Процедура рисования прямоугольника ( заполненый ) 766 | //============================================================================== 767 | void ST7789_DrawRectangleFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t fillcolor) { 768 | 769 | if (x1 > x2){ 770 | SwapInt16Values(&x1, &x2); 771 | } 772 | 773 | if (y1 > y2){ 774 | SwapInt16Values(&y1, &y2); 775 | } 776 | 777 | ST7789_FillRect(x1, y1, x2 - x1, y2 - y1, fillcolor); 778 | } 779 | //============================================================================== 780 | 781 | 782 | //============================================================================== 783 | // Процедура вспомогательная для --- Процедура рисования линии 784 | //============================================================================== 785 | static void ST7789_DrawLine_Slow(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { 786 | 787 | const int16_t deltaX = abs(x2 - x1); 788 | const int16_t deltaY = abs(y2 - y1); 789 | const int16_t signX = x1 < x2 ? 1 : -1; 790 | const int16_t signY = y1 < y2 ? 1 : -1; 791 | 792 | int16_t error = deltaX - deltaY; 793 | 794 | ST7789_DrawPixel(x2, y2, color); 795 | 796 | while (x1 != x2 || y1 != y2) { 797 | 798 | ST7789_DrawPixel(x1, y1, color); 799 | const int16_t error2 = error * 2; 800 | 801 | if (error2 > -deltaY) { 802 | 803 | error -= deltaY; 804 | x1 += signX; 805 | } 806 | if (error2 < deltaX){ 807 | 808 | error += deltaX; 809 | y1 += signY; 810 | } 811 | } 812 | } 813 | //============================================================================== 814 | 815 | 816 | //============================================================================== 817 | // Процедура рисования линии 818 | //============================================================================== 819 | void ST7789_DrawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { 820 | 821 | if (x1 == x2){ 822 | 823 | if (y1 > y2){ 824 | ST7789_FillRect(x1, y2, 1, y1 - y2 + 1, color); 825 | } 826 | else{ 827 | ST7789_FillRect(x1, y1, 1, y2 - y1 + 1, color); 828 | } 829 | 830 | return; 831 | } 832 | 833 | if (y1 == y2){ 834 | 835 | if (x1 > x2){ 836 | ST7789_FillRect(x2, y1, x1 - x2 + 1, 1, color); 837 | } 838 | else{ 839 | ST7789_FillRect(x1, y1, x2 - x1 + 1, 1, color); 840 | } 841 | 842 | return; 843 | } 844 | 845 | ST7789_DrawLine_Slow(x1, y1, x2, y2, color); 846 | } 847 | //============================================================================== 848 | 849 | 850 | //============================================================================== 851 | // Процедура рисования линии с указаным углом и длиной 852 | //============================================================================== 853 | void ST7789_DrawLineWithAngle(int16_t x, int16_t y, uint16_t length, double angle_degrees, uint16_t color) { 854 | // Преобразование угла в радианы 855 | double angle_radians = (360.0 - angle_degrees) * PI / 180.0; 856 | 857 | // Вычисление конечных координат 858 | int16_t x2 = x + length * cos(angle_radians) + 0.5; 859 | int16_t y2 = y + length * sin(angle_radians) + 0.5; 860 | 861 | // Используем существующую функцию для рисования линии 862 | ST7789_DrawLine(x, y, x2, y2, color); 863 | } 864 | //============================================================================== 865 | 866 | //============================================================================== 867 | // Процедура рисования треугольника ( пустотелый ) 868 | //============================================================================== 869 | void ST7789_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color){ 870 | /* Draw lines */ 871 | ST7789_DrawLine(x1, y1, x2, y2, color); 872 | ST7789_DrawLine(x2, y2, x3, y3, color); 873 | ST7789_DrawLine(x3, y3, x1, y1, color); 874 | } 875 | //============================================================================== 876 | 877 | 878 | //============================================================================== 879 | // Процедура рисования треугольника ( заполненый ) 880 | //============================================================================== 881 | void ST7789_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color){ 882 | 883 | int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, 884 | yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, 885 | curpixel = 0; 886 | 887 | deltax = abs(x2 - x1); 888 | deltay = abs(y2 - y1); 889 | x = x1; 890 | y = y1; 891 | 892 | if (x2 >= x1) { 893 | xinc1 = 1; 894 | xinc2 = 1; 895 | } 896 | else { 897 | xinc1 = -1; 898 | xinc2 = -1; 899 | } 900 | 901 | if (y2 >= y1) { 902 | yinc1 = 1; 903 | yinc2 = 1; 904 | } 905 | else { 906 | yinc1 = -1; 907 | yinc2 = -1; 908 | } 909 | 910 | if (deltax >= deltay){ 911 | xinc1 = 0; 912 | yinc2 = 0; 913 | den = deltax; 914 | num = deltax / 2; 915 | numadd = deltay; 916 | numpixels = deltax; 917 | } 918 | else { 919 | xinc2 = 0; 920 | yinc1 = 0; 921 | den = deltay; 922 | num = deltay / 2; 923 | numadd = deltax; 924 | numpixels = deltay; 925 | } 926 | 927 | for (curpixel = 0; curpixel <= numpixels; curpixel++) { 928 | ST7789_DrawLine(x, y, x3, y3, color); 929 | 930 | num += numadd; 931 | if (num >= den) { 932 | num -= den; 933 | x += xinc1; 934 | y += yinc1; 935 | } 936 | x += xinc2; 937 | y += yinc2; 938 | } 939 | } 940 | //============================================================================== 941 | 942 | 943 | //============================================================================== 944 | // Процедура окрашивает 1 пиксель дисплея 945 | //============================================================================== 946 | void ST7789_DrawPixel(int16_t x, int16_t y, uint16_t color){ 947 | 948 | if ((x < 0) ||(x >= ST7789_Width) || (y < 0) || (y >= ST7789_Height)){ 949 | return; 950 | } 951 | 952 | #if FRAME_BUFFER // если включен буфер кадра 953 | buff_frame[y * ST7789_Width + x] = ((color & 0xFF)<<8) | (color >> 8 ); 954 | #else //если попиксельный вывод 955 | ST7789_SetWindow(x, y, x, y); 956 | ST7789_RamWrite(&color, 1); 957 | #endif 958 | } 959 | //============================================================================== 960 | 961 | 962 | //============================================================================== 963 | // Процедура рисования круг ( заполненый ) 964 | //============================================================================== 965 | void ST7789_DrawCircleFilled(int16_t x0, int16_t y0, int16_t radius, uint16_t fillcolor) { 966 | 967 | int x = 0; 968 | int y = radius; 969 | int delta = 1 - 2 * radius; 970 | int error = 0; 971 | 972 | while (y >= 0){ 973 | 974 | ST7789_DrawLine(x0 + x, y0 - y, x0 + x, y0 + y, fillcolor); 975 | ST7789_DrawLine(x0 - x, y0 - y, x0 - x, y0 + y, fillcolor); 976 | error = 2 * (delta + y) - 1; 977 | 978 | if (delta < 0 && error <= 0) { 979 | 980 | ++x; 981 | delta += 2 * x + 1; 982 | continue; 983 | } 984 | 985 | error = 2 * (delta - x) - 1; 986 | 987 | if (delta > 0 && error > 0) { 988 | 989 | --y; 990 | delta += 1 - 2 * y; 991 | continue; 992 | } 993 | 994 | ++x; 995 | delta += 2 * (x - y); 996 | --y; 997 | } 998 | } 999 | //============================================================================== 1000 | 1001 | 1002 | //============================================================================== 1003 | // Процедура рисования круг ( пустотелый ) 1004 | //============================================================================== 1005 | void ST7789_DrawCircle(int16_t x0, int16_t y0, int16_t radius, uint16_t color) { 1006 | 1007 | int x = 0; 1008 | int y = radius; 1009 | int delta = 1 - 2 * radius; 1010 | int error = 0; 1011 | 1012 | while (y >= 0){ 1013 | 1014 | ST7789_DrawPixel(x0 + x, y0 + y, color); 1015 | ST7789_DrawPixel(x0 + x, y0 - y, color); 1016 | ST7789_DrawPixel(x0 - x, y0 + y, color); 1017 | ST7789_DrawPixel(x0 - x, y0 - y, color); 1018 | error = 2 * (delta + y) - 1; 1019 | 1020 | if (delta < 0 && error <= 0) { 1021 | 1022 | ++x; 1023 | delta += 2 * x + 1; 1024 | continue; 1025 | } 1026 | 1027 | error = 2 * (delta - x) - 1; 1028 | 1029 | if (delta > 0 && error > 0) { 1030 | 1031 | --y; 1032 | delta += 1 - 2 * y; 1033 | continue; 1034 | } 1035 | 1036 | ++x; 1037 | delta += 2 * (x - y); 1038 | --y; 1039 | } 1040 | } 1041 | //============================================================================== 1042 | 1043 | 1044 | //============================================================================== 1045 | // рисуем элипс 1046 | //============================================================================== 1047 | void ST7789_DrawEllipse(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, uint16_t color) { 1048 | int x, y; 1049 | for (float angle = 0; angle <= 360; angle += 0.1) { 1050 | x = x0 + radiusX * cos(angle * PI / 180); 1051 | y = y0 + radiusY * sin(angle * PI / 180); 1052 | ST7789_DrawPixel(x, y, color); 1053 | } 1054 | } 1055 | //============================================================================== 1056 | 1057 | 1058 | //============================================================================== 1059 | // рисуем элипс под указаным углом наклона 1060 | //============================================================================== 1061 | void ST7789_DrawEllipseWithAngle(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, float angle_degrees, uint16_t color) { 1062 | float cosAngle = cos((360.0 - angle_degrees) * PI / 180); 1063 | float sinAngle = sin((360.0 - angle_degrees) * PI / 180); 1064 | 1065 | for (int16_t t = 0; t <= 360; t++) { 1066 | float radians = t * PI / 180.0; 1067 | int16_t x = radiusX * cos(radians); 1068 | int16_t y = radiusY * sin(radians); 1069 | 1070 | int16_t xTransformed = x0 + cosAngle * x - sinAngle * y; 1071 | int16_t yTransformed = y0 + sinAngle * x + cosAngle * y; 1072 | 1073 | ST7789_DrawPixel(xTransformed, yTransformed, color); 1074 | } 1075 | } 1076 | //============================================================================== 1077 | 1078 | 1079 | //============================================================================== 1080 | // рисуем элипс закрашенный 1081 | //============================================================================== 1082 | void ST7789_DrawEllipseFilled(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, uint16_t color) { 1083 | int x, y; 1084 | 1085 | for (y = -radiusY; y <= radiusY; y++) { 1086 | for (x = -radiusX; x <= radiusX; x++) { 1087 | if ((x * x * radiusY * radiusY + y * y * radiusX * radiusX) <= (radiusX * radiusX * radiusY * radiusY)) { 1088 | ST7789_DrawPixel(x0 + x, y0 + y, color); 1089 | } 1090 | } 1091 | } 1092 | } 1093 | //============================================================================== 1094 | 1095 | 1096 | //============================================================================== 1097 | // рисуем элипс закрашенный под указаным углом наклона 1098 | //============================================================================== 1099 | void ST7789_DrawEllipseFilledWithAngle(int16_t x0, int16_t y0, int16_t radiusX, int16_t radiusY, float angle_degrees, uint16_t color) { 1100 | float cosAngle = cos((360.0 - angle_degrees) * PI / 180.0); 1101 | float sinAngle = sin((360.0 - angle_degrees) * PI / 180.0); 1102 | 1103 | for (int16_t y = -radiusY; y <= radiusY; y++) { 1104 | for (int16_t x = -radiusX; x <= radiusX; x++) { 1105 | float xTransformed = cosAngle * x - sinAngle * y; 1106 | float yTransformed = sinAngle * x + cosAngle * y; 1107 | 1108 | if ((x * x * radiusY * radiusY + y * y * radiusX * radiusX) <= (radiusX * radiusX * radiusY * radiusY)){ 1109 | ST7789_DrawPixel(x0 + xTransformed, y0 + yTransformed, color); 1110 | } 1111 | } 1112 | } 1113 | } 1114 | //============================================================================== 1115 | 1116 | 1117 | //============================================================================== 1118 | // Процедура рисования символа ( 1 буква или знак ) 1119 | //============================================================================== 1120 | void ST7789_DrawChar(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, unsigned char ch){ 1121 | 1122 | uint32_t i, b, j; 1123 | 1124 | uint32_t X = x, Y = y; 1125 | 1126 | uint8_t xx, yy; 1127 | 1128 | if( multiplier < 1 ){ 1129 | multiplier = 1; 1130 | } 1131 | 1132 | /* Check available space in LCD */ 1133 | if (ST7789_Width >= ( x + Font->FontWidth) || ST7789_Height >= ( y + Font->FontHeight)){ 1134 | 1135 | 1136 | /* Go through font */ 1137 | for (i = 0; i < Font->FontHeight; i++) { 1138 | 1139 | if( ch < 127 ){ 1140 | b = Font->data[(ch - 32) * Font->FontHeight + i]; 1141 | } 1142 | 1143 | else if( (uint8_t) ch > 191 ){ 1144 | // +96 это так как латинские символы и знаки в шрифтах занимают 96 позиций 1145 | // и если в шрифте который содержит сперва латиницу и спец символы и потом 1146 | // только кирилицу то нужно добавлять 95 если шрифт 1147 | // содержит только кирилицу то +96 не нужно 1148 | b = Font->data[((ch - 192) + 96) * Font->FontHeight + i]; 1149 | } 1150 | 1151 | else if( (uint8_t) ch == 168 ){ // 168 символ по ASCII - Ё 1152 | // 160 эллемент ( символ Ё ) 1153 | b = Font->data[( 160 ) * Font->FontHeight + i]; 1154 | } 1155 | 1156 | else if( (uint8_t) ch == 184 ){ // 184 символ по ASCII - ё 1157 | // 161 эллемент ( символ ё ) 1158 | b = Font->data[( 161 ) * Font->FontHeight + i]; 1159 | } 1160 | //------------------------------------------------------------------- 1161 | 1162 | //---- Украинская раскладка ---------------------------------------------------- 1163 | else if( (uint8_t) ch == 170 ){ // 168 символ по ASCII - Є 1164 | // 162 эллемент ( символ Є ) 1165 | b = Font->data[( 162 ) * Font->FontHeight + i]; 1166 | } 1167 | else if( (uint8_t) ch == 175 ){ // 184 символ по ASCII - Ї 1168 | // 163 эллемент ( символ Ї ) 1169 | b = Font->data[( 163 ) * Font->FontHeight + i]; 1170 | } 1171 | else if( (uint8_t) ch == 178 ){ // 168 символ по ASCII - І 1172 | // 164 эллемент ( символ І ) 1173 | b = Font->data[( 164 ) * Font->FontHeight + i]; 1174 | } 1175 | else if( (uint8_t) ch == 179 ){ // 184 символ по ASCII - і 1176 | // 165 эллемент ( символ і ) 1177 | b = Font->data[( 165 ) * Font->FontHeight + i]; 1178 | } 1179 | else if( (uint8_t) ch == 186 ){ // 184 символ по ASCII - є 1180 | // 166 эллемент ( символ є ) 1181 | b = Font->data[( 166 ) * Font->FontHeight + i]; 1182 | } 1183 | else if( (uint8_t) ch == 191 ){ // 168 символ по ASCII - ї 1184 | // 167 эллемент ( символ ї ) 1185 | b = Font->data[( 167 ) * Font->FontHeight + i]; 1186 | } 1187 | //----------------------------------------------------------------------------- 1188 | 1189 | for (j = 0; j < Font->FontWidth; j++) { 1190 | 1191 | if ((b << j) & 0x8000) { 1192 | 1193 | for (yy = 0; yy < multiplier; yy++){ 1194 | for (xx = 0; xx < multiplier; xx++){ 1195 | ST7789_DrawPixel(X+xx, Y+yy, TextColor); 1196 | } 1197 | } 1198 | 1199 | } 1200 | else if( TransparentBg ){ 1201 | 1202 | for (yy = 0; yy < multiplier; yy++){ 1203 | for (xx = 0; xx < multiplier; xx++){ 1204 | ST7789_DrawPixel(X+xx, Y+yy, BgColor); 1205 | } 1206 | } 1207 | 1208 | } 1209 | X = X + multiplier; 1210 | } 1211 | X = x; 1212 | Y = Y + multiplier; 1213 | } 1214 | } 1215 | } 1216 | //============================================================================== 1217 | 1218 | 1219 | //============================================================================== 1220 | // Процедура рисования строки 1221 | //============================================================================== 1222 | void ST7789_print(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, char *str){ 1223 | 1224 | if( multiplier < 1 ){ 1225 | multiplier = 1; 1226 | } 1227 | 1228 | unsigned char buff_char; 1229 | 1230 | uint16_t len = strlen(str); 1231 | 1232 | while (len--) { 1233 | 1234 | //--------------------------------------------------------------------- 1235 | // проверка на кириллицу UTF-8, если латиница то пропускаем if 1236 | // Расширенные символы ASCII Win-1251 кириллица (код символа 128-255) 1237 | // проверяем первый байт из двух ( так как UTF-8 ето два байта ) 1238 | // если он больше либо равен 0xC0 ( первый байт в кириллеце будет равен 0xD0 либо 0xD1 именно в алфавите ) 1239 | if ( (uint8_t)*str >= 0xC0 ){ // код 0xC0 соответствует символу кириллица 'A' по ASCII Win-1251 1240 | 1241 | // проверяем какой именно байт первый 0xD0 либо 0xD1--------------------------------------------- 1242 | switch ((uint8_t)*str) { 1243 | case 0xD0: { 1244 | // увеличиваем массив так как нам нужен второй байт 1245 | str++; 1246 | // проверяем второй байт там сам символ 1247 | if ((uint8_t)*str >= 0x90 && (uint8_t)*str <= 0xBF){ buff_char = (*str) + 0x30; } // байт символов А...Я а...п делаем здвиг на +48 1248 | else if ((uint8_t)*str == 0x81) { buff_char = 0xA8; break; } // байт символа Ё ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1249 | else if ((uint8_t)*str == 0x84) { buff_char = 0xAA; break; } // байт символа Є ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1250 | else if ((uint8_t)*str == 0x86) { buff_char = 0xB2; break; } // байт символа І ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1251 | else if ((uint8_t)*str == 0x87) { buff_char = 0xAF; break; } // байт символа Ї ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1252 | break; 1253 | } 1254 | case 0xD1: { 1255 | // увеличиваем массив так как нам нужен второй байт 1256 | str++; 1257 | // проверяем второй байт там сам символ 1258 | if ((uint8_t)*str >= 0x80 && (uint8_t)*str <= 0x8F){ buff_char = (*str) + 0x70; } // байт символов п...я елаем здвиг на +112 1259 | else if ((uint8_t)*str == 0x91) { buff_char = 0xB8; break; } // байт символа ё ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1260 | else if ((uint8_t)*str == 0x94) { buff_char = 0xBA; break; } // байт символа є ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1261 | else if ((uint8_t)*str == 0x96) { buff_char = 0xB3; break; } // байт символа і ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1262 | else if ((uint8_t)*str == 0x97) { buff_char = 0xBF; break; } // байт символа ї ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1263 | break; 1264 | } 1265 | } 1266 | //------------------------------------------------------------------------------------------------ 1267 | // уменьшаем еще переменную так как израсходывали 2 байта для кириллицы 1268 | len--; 1269 | 1270 | ST7789_DrawChar(x, y, TextColor, BgColor, TransparentBg, Font, multiplier, buff_char); 1271 | } 1272 | //--------------------------------------------------------------------- 1273 | else{ 1274 | ST7789_DrawChar(x, y, TextColor, BgColor, TransparentBg, Font, multiplier, *str); 1275 | } 1276 | 1277 | x = x + (Font->FontWidth * multiplier); 1278 | /* Increase string pointer */ 1279 | str++; 1280 | } 1281 | } 1282 | //============================================================================== 1283 | 1284 | 1285 | //============================================================================== 1286 | // Процедура рисования символа с указаным углом ( 1 буква или знак ) 1287 | //============================================================================== 1288 | void ST7789_DrawCharWithAngle(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, double angle_degrees, unsigned char ch){ 1289 | 1290 | uint32_t i, b, j; 1291 | 1292 | uint32_t X = x, Y = y; 1293 | 1294 | uint8_t xx, yy; 1295 | 1296 | // Преобразуем угол в радианы 1297 | double radians = (360.0 - angle_degrees) * PI / 180.0; 1298 | 1299 | // Вычисляем матрицу поворота 1300 | double cosTheta = cos(radians); 1301 | double sinTheta = sin(radians); 1302 | 1303 | // Переменные для преобразованных координат 1304 | double newX, newY; 1305 | 1306 | if( multiplier < 1 ){ 1307 | multiplier = 1; 1308 | } 1309 | 1310 | /* Check available space in LCD */ 1311 | if (ST7789_Width >= ( x + Font->FontWidth) || ST7789_Height >= ( y + Font->FontHeight)){ 1312 | 1313 | /* Go through font */ 1314 | for (i = 0; i < Font->FontHeight; i++) { 1315 | 1316 | if( ch < 127 ){ 1317 | b = Font->data[(ch - 32) * Font->FontHeight + i]; 1318 | } 1319 | 1320 | else if( (uint8_t) ch > 191 ){ 1321 | // +96 это так как латинские символы и знаки в шрифтах занимают 96 позиций 1322 | // и если в шрифте который содержит сперва латиницу и спец символы и потом 1323 | // только кирилицу то нужно добавлять 95 если шрифт 1324 | // содержит только кирилицу то +96 не нужно 1325 | b = Font->data[((ch - 192) + 96) * Font->FontHeight + i]; 1326 | } 1327 | 1328 | else if( (uint8_t) ch == 168 ){ // 168 символ по ASCII - Ё 1329 | // 160 эллемент ( символ Ё ) 1330 | b = Font->data[( 160 ) * Font->FontHeight + i]; 1331 | } 1332 | 1333 | else if( (uint8_t) ch == 184 ){ // 184 символ по ASCII - ё 1334 | // 161 эллемент ( символ ё ) 1335 | b = Font->data[( 161 ) * Font->FontHeight + i]; 1336 | } 1337 | //------------------------------------------------------------------- 1338 | 1339 | //---- Украинская раскладка ---------------------------------------------------- 1340 | else if( (uint8_t) ch == 170 ){ // 168 символ по ASCII - Є 1341 | // 162 эллемент ( символ Є ) 1342 | b = Font->data[( 162 ) * Font->FontHeight + i]; 1343 | } 1344 | else if( (uint8_t) ch == 175 ){ // 184 символ по ASCII - Ї 1345 | // 163 эллемент ( символ Ї ) 1346 | b = Font->data[( 163 ) * Font->FontHeight + i]; 1347 | } 1348 | else if( (uint8_t) ch == 178 ){ // 168 символ по ASCII - І 1349 | // 164 эллемент ( символ І ) 1350 | b = Font->data[( 164 ) * Font->FontHeight + i]; 1351 | } 1352 | else if( (uint8_t) ch == 179 ){ // 184 символ по ASCII - і 1353 | // 165 эллемент ( символ і ) 1354 | b = Font->data[( 165 ) * Font->FontHeight + i]; 1355 | } 1356 | else if( (uint8_t) ch == 186 ){ // 184 символ по ASCII - є 1357 | // 166 эллемент ( символ є ) 1358 | b = Font->data[( 166 ) * Font->FontHeight + i]; 1359 | } 1360 | else if( (uint8_t) ch == 191 ){ // 168 символ по ASCII - ї 1361 | // 167 эллемент ( символ ї ) 1362 | b = Font->data[( 167 ) * Font->FontHeight + i]; 1363 | } 1364 | //----------------------------------------------------------------------------- 1365 | 1366 | for (j = 0; j < Font->FontWidth; j++) { 1367 | if ((b << j) & 0x8000) { 1368 | // Применяем поворот к координатам 1369 | newX = cosTheta * (X - x) - sinTheta * (Y - y) + x; 1370 | newY = sinTheta * (X - x) + cosTheta * (Y - y) + y; 1371 | 1372 | for (yy = 0; yy < multiplier; yy++) { 1373 | for (xx = 0; xx < multiplier; xx++) { 1374 | ST7789_DrawPixel(newX + xx, newY + yy, TextColor); 1375 | } 1376 | } 1377 | } else if (TransparentBg) { 1378 | // Аналогично для фона 1379 | newX = cosTheta * (X - x) - sinTheta * (Y - y) + x + 0.5; 1380 | newY = sinTheta * (X - x) + cosTheta * (Y - y) + y + 0.5; 1381 | 1382 | for (yy = 0; yy < multiplier; yy++) { 1383 | for (xx = 0; xx < multiplier; xx++) { 1384 | ST7789_DrawPixel(newX + xx, newY + yy, BgColor); 1385 | } 1386 | } 1387 | } 1388 | X = X + multiplier; 1389 | } 1390 | X = x; 1391 | Y = Y + multiplier; 1392 | } 1393 | } 1394 | } 1395 | //============================================================================== 1396 | 1397 | 1398 | //============================================================================== 1399 | // Процедура рисования строки с указаным углом 1400 | //============================================================================== 1401 | void ST7789_printWithAngle(uint16_t x, uint16_t y, uint16_t TextColor, uint16_t BgColor, uint8_t TransparentBg, FontDef_t* Font, uint8_t multiplier, double angle_degrees, char *str){ 1402 | 1403 | if( multiplier < 1 ){ 1404 | multiplier = 1; 1405 | } 1406 | 1407 | unsigned char buff_char; 1408 | 1409 | uint16_t len = strlen(str); 1410 | 1411 | while (len--) { 1412 | 1413 | //--------------------------------------------------------------------- 1414 | // проверка на кириллицу UTF-8, если латиница то пропускаем if 1415 | // Расширенные символы ASCII Win-1251 кириллица (код символа 128-255) 1416 | // проверяем первый байт из двух ( так как UTF-8 ето два байта ) 1417 | // если он больше либо равен 0xC0 ( первый байт в кириллеце будет равен 0xD0 либо 0xD1 именно в алфавите ) 1418 | if ( (uint8_t)*str >= 0xC0 ){ // код 0xC0 соответствует символу кириллица 'A' по ASCII Win-1251 1419 | 1420 | // проверяем какой именно байт первый 0xD0 либо 0xD1--------------------------------------------- 1421 | switch ((uint8_t)*str) { 1422 | case 0xD0: { 1423 | // увеличиваем массив так как нам нужен второй байт 1424 | str++; 1425 | // проверяем второй байт там сам символ 1426 | if ((uint8_t)*str >= 0x90 && (uint8_t)*str <= 0xBF){ buff_char = (*str) + 0x30; } // байт символов А...Я а...п делаем здвиг на +48 1427 | else if ((uint8_t)*str == 0x81) { buff_char = 0xA8; break; } // байт символа Ё ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1428 | else if ((uint8_t)*str == 0x84) { buff_char = 0xAA; break; } // байт символа Є ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1429 | else if ((uint8_t)*str == 0x86) { buff_char = 0xB2; break; } // байт символа І ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1430 | else if ((uint8_t)*str == 0x87) { buff_char = 0xAF; break; } // байт символа Ї ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1431 | break; 1432 | } 1433 | case 0xD1: { 1434 | // увеличиваем массив так как нам нужен второй байт 1435 | str++; 1436 | // проверяем второй байт там сам символ 1437 | if ((uint8_t)*str >= 0x80 && (uint8_t)*str <= 0x8F){ buff_char = (*str) + 0x70; } // байт символов п...я елаем здвиг на +112 1438 | else if ((uint8_t)*str == 0x91) { buff_char = 0xB8; break; } // байт символа ё ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1439 | else if ((uint8_t)*str == 0x94) { buff_char = 0xBA; break; } // байт символа є ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1440 | else if ((uint8_t)*str == 0x96) { buff_char = 0xB3; break; } // байт символа і ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1441 | else if ((uint8_t)*str == 0x97) { buff_char = 0xBF; break; } // байт символа ї ( если нужнф еще символы добавляем тут и в функции DrawChar() ) 1442 | break; 1443 | } 1444 | } 1445 | //------------------------------------------------------------------------------------------------ 1446 | // уменьшаем еще переменную так как израсходывали 2 байта для кириллицы 1447 | len--; 1448 | 1449 | ST7789_DrawCharWithAngle(x, y, TextColor, BgColor, TransparentBg, Font, multiplier, angle_degrees, buff_char); 1450 | } 1451 | //--------------------------------------------------------------------- 1452 | else{ 1453 | ST7789_DrawCharWithAngle(x, y, TextColor, BgColor, TransparentBg, Font, multiplier, angle_degrees, *str); 1454 | } 1455 | // Смещаем начальные координаты с каждым символом с учетом угла 1456 | x += (Font->FontWidth * multiplier * cos((360.0 - angle_degrees) * PI / 180.0) + 0.5); 1457 | y += (Font->FontWidth * multiplier * sin((360.0 - angle_degrees) * PI / 180.0) + 0.5); 1458 | 1459 | /* Increase string pointer */ 1460 | str++; 1461 | } 1462 | } 1463 | //============================================================================== 1464 | 1465 | 1466 | //============================================================================== 1467 | // Процедура ротации ( положение ) дисплея 1468 | //============================================================================== 1469 | // па умолчанию 1 режим ( всего 1, 2, 3, 4 ) 1470 | void ST7789_rotation( uint8_t rotation ){ 1471 | 1472 | ST7789_Select(); 1473 | 1474 | ST7789_SendCmd(ST7789_MADCTL); 1475 | 1476 | // длайвер расчитан на экран 320 х 240 ( максимальный размер ) 1477 | // для подгона под любой другой нужно отнимать разницу пикселей 1478 | 1479 | switch (rotation) { 1480 | 1481 | case 1: 1482 | //== 2.25" 76 x 284 ST7789 ================================================= 1483 | #ifdef ST7789_IS_76X284 1484 | ST7789_SendData(ST7789_MADCTL_RGB); 1485 | ST7789_Width = 76; 1486 | ST7789_Height = 284; 1487 | ST7789_X_Start = 82; 1488 | ST7789_Y_Start = 18; 1489 | ST7789_FillScreen(0); 1490 | #endif 1491 | //========================================================================== 1492 | 1493 | //== 1.13" 135 x 240 ST7789 ================================================= 1494 | #ifdef ST7789_IS_135X240 1495 | ST7789_SendData(ST7789_MADCTL_RGB); 1496 | ST7789_Width = 135; 1497 | ST7789_Height = 240; 1498 | ST7789_X_Start = 52; 1499 | ST7789_Y_Start = 40; 1500 | ST7789_FillScreen(0); 1501 | #endif 1502 | //========================================================================== 1503 | 1504 | //== 1.3" 240 x 240 ST7789 ================================================= 1505 | #ifdef ST7789_IS_240X240 1506 | ST7789_SendData(ST7789_MADCTL_RGB); 1507 | ST7789_Width = 240; 1508 | ST7789_Height = 240; 1509 | ST7789_X_Start = 0; 1510 | ST7789_Y_Start = 0; 1511 | ST7789_FillScreen(0); 1512 | #endif 1513 | //========================================================================== 1514 | 1515 | //== 1.47" 172 x 320 ST7789 ================================================= 1516 | #ifdef ST7789_IS_172X320 1517 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1518 | ST7789_Width = 320; 1519 | ST7789_Height = 172; 1520 | ST7789_X_Start = 0; 1521 | ST7789_Y_Start = 34; 1522 | ST7789_FillScreen(0); 1523 | #endif 1524 | //========================================================================== 1525 | 1526 | //== 1.69" 240 x 280 ST7789 ================================================= 1527 | #ifdef ST7789_IS_240X280 1528 | ST7789_SendData(ST7789_MADCTL_RGB); 1529 | ST7789_Width = 240; 1530 | ST7789_Height = 280; 1531 | ST7789_X_Start = 0; 1532 | ST7789_Y_Start = 20; 1533 | ST7789_FillScreen(0); 1534 | #endif 1535 | //========================================================================== 1536 | 1537 | //== 2" 240 x 320 ST7789 ================================================= 1538 | #ifdef ST7789_IS_240X320 1539 | ST7789_SendData(ST7789_MADCTL_RGB); 1540 | ST7789_Width = 240; 1541 | ST7789_Height = 320; 1542 | ST7789_X_Start = 0; 1543 | ST7789_Y_Start = 0; 1544 | ST7789_FillScreen(0); 1545 | #endif 1546 | //========================================================================== 1547 | break; 1548 | 1549 | case 2: 1550 | //== 2.25" 76 x 284 ST7789 ================================================= 1551 | #ifdef ST7789_IS_76X284 1552 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1553 | ST7789_Width = 284; 1554 | ST7789_Height = 76; 1555 | ST7789_X_Start = 18; 1556 | ST7789_Y_Start = 82; 1557 | ST7789_FillScreen(0); 1558 | #endif 1559 | //========================================================================== 1560 | 1561 | //== 1.13" 135 x 240 ST7789 ================================================= 1562 | #ifdef ST7789_IS_135X240 1563 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1564 | ST7789_Width = 240; 1565 | ST7789_Height = 135; 1566 | ST7789_X_Start = 40; 1567 | ST7789_Y_Start = 53; 1568 | ST7789_FillScreen(0); 1569 | #endif 1570 | //========================================================================== 1571 | 1572 | //== 1.3" 240 x 240 ST7789 ================================================= 1573 | #ifdef ST7789_IS_240X240 1574 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1575 | ST7789_Width = 240; 1576 | ST7789_Height = 240; 1577 | ST7789_X_Start = 0; 1578 | ST7789_Y_Start = 0; 1579 | ST7789_FillScreen(0); 1580 | #endif 1581 | //========================================================================== 1582 | 1583 | //== 1.47" 172 x 320 ST7789 ================================================= 1584 | #ifdef ST7789_IS_172X320 1585 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); 1586 | ST7789_Width = 172; 1587 | ST7789_Height = 320; 1588 | ST7789_X_Start = 34; 1589 | ST7789_Y_Start = 0; 1590 | ST7789_FillScreen(0); 1591 | #endif 1592 | //========================================================================== 1593 | 1594 | //== 1.69" 240 x 280 ST7789 ================================================= 1595 | #ifdef ST7789_IS_240X280 1596 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1597 | ST7789_Width = 280; 1598 | ST7789_Height = 240; 1599 | ST7789_X_Start = 20; 1600 | ST7789_Y_Start = 0; 1601 | ST7789_FillScreen(0); 1602 | #endif 1603 | //========================================================================== 1604 | 1605 | //== 2" 240 x 320 ST7789 ================================================= 1606 | #ifdef ST7789_IS_240X320 1607 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1608 | ST7789_Width = 320; 1609 | ST7789_Height = 240; 1610 | ST7789_X_Start = 0; 1611 | ST7789_Y_Start = 0; 1612 | ST7789_FillScreen(0); 1613 | #endif 1614 | //========================================================================== 1615 | break; 1616 | 1617 | case 3: 1618 | //== 2.25" 76 x 284 ST7789 ================================================= 1619 | #ifdef ST7789_IS_76X284 1620 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); 1621 | ST7789_Width = 76; 1622 | ST7789_Height = 284; 1623 | ST7789_X_Start = 82; 1624 | ST7789_Y_Start = 18; 1625 | ST7789_FillScreen(0); 1626 | #endif 1627 | //========================================================================== 1628 | 1629 | //== 1.13" 135 x 240 ST7789 ================================================= 1630 | #ifdef ST7789_IS_135X240 1631 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); 1632 | ST7789_Width = 135; 1633 | ST7789_Height = 240; 1634 | ST7789_X_Start = 53; 1635 | ST7789_Y_Start = 40; 1636 | ST7789_FillScreen(0); 1637 | #endif 1638 | //========================================================================== 1639 | 1640 | //== 1.3" 240 x 240 ST7789 ================================================= 1641 | #ifdef ST7789_IS_240X240 1642 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); 1643 | ST7789_Width = 240; 1644 | ST7789_Height = 240; 1645 | ST7789_X_Start = 0; 1646 | ST7789_Y_Start = 80; 1647 | ST7789_FillScreen(0); 1648 | #endif 1649 | //========================================================================== 1650 | 1651 | //== 1.47" 172 x 320 ST7789 ================================================= 1652 | #ifdef ST7789_IS_172X320 1653 | ST7789_SendData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1654 | ST7789_Width = 320; 1655 | ST7789_Height = 172; 1656 | ST7789_X_Start = 0; 1657 | ST7789_Y_Start = 34; 1658 | ST7789_FillScreen(0); 1659 | #endif 1660 | //========================================================================== 1661 | 1662 | //== 1.69" 240 x 280 ST7789 ================================================= 1663 | #ifdef ST7789_IS_240X280 1664 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); 1665 | ST7789_Width = 240; 1666 | ST7789_Height = 280; 1667 | ST7789_X_Start = 0; 1668 | ST7789_Y_Start = 20; 1669 | ST7789_FillScreen(0); 1670 | #endif 1671 | //========================================================================== 1672 | 1673 | //== 2" 240 x 320 ST7789 ================================================= 1674 | #ifdef ST7789_IS_240X320 1675 | ST7789_SendData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); 1676 | ST7789_Width = 240; 1677 | ST7789_Height = 320; 1678 | ST7789_X_Start = 0; 1679 | ST7789_Y_Start = 0; 1680 | ST7789_FillScreen(0); 1681 | #endif 1682 | //========================================================================== 1683 | 1684 | break; 1685 | 1686 | case 4: 1687 | //== 2.25" 76 x 284 ST7789 ================================================= 1688 | #ifdef ST7789_IS_76X284 1689 | ST7789_SendData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1690 | ST7789_Width = 284; 1691 | ST7789_Height = 76; 1692 | ST7789_X_Start = 18; 1693 | ST7789_Y_Start = 82; 1694 | ST7789_FillScreen(0); 1695 | #endif 1696 | //========================================================================== 1697 | 1698 | //== 1.13" 135 x 240 ST7789 ================================================= 1699 | #ifdef ST7789_IS_135X240 1700 | ST7789_SendData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1701 | ST7789_Width = 240; 1702 | ST7789_Height = 135; 1703 | ST7789_X_Start = 40; 1704 | ST7789_Y_Start = 52; 1705 | ST7789_FillScreen(0); 1706 | #endif 1707 | //========================================================================== 1708 | 1709 | //== 1.3" 240 x 240 ST7789 ================================================= 1710 | #ifdef ST7789_IS_240X240 1711 | ST7789_SendData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1712 | ST7789_Width = 240; 1713 | ST7789_Height = 240; 1714 | ST7789_X_Start = 80; 1715 | ST7789_Y_Start = 0; 1716 | ST7789_FillScreen(0); 1717 | #endif 1718 | //========================================================================== 1719 | 1720 | //== 1.47" 172 x 320 ST7789 ================================================= 1721 | #ifdef ST7789_IS_172X320 1722 | ST7789_SendData(ST7789_MADCTL_RGB); 1723 | ST7789_Width = 172; 1724 | ST7789_Height = 320; 1725 | ST7789_X_Start = 34; 1726 | ST7789_Y_Start = 0; 1727 | ST7789_FillScreen(0); 1728 | #endif 1729 | //========================================================================== 1730 | 1731 | //== 1.69" 240 x 280 ST7789 ================================================= 1732 | #ifdef ST7789_IS_240X280 1733 | ST7789_SendData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1734 | ST7789_Width = 280; 1735 | ST7789_Height = 240; 1736 | ST7789_X_Start = 20; 1737 | ST7789_Y_Start = 0; 1738 | ST7789_FillScreen(0); 1739 | #endif 1740 | //========================================================================== 1741 | 1742 | //== 2" 240 x 320 ST7789 ================================================= 1743 | #ifdef ST7789_IS_240X320 1744 | ST7789_SendData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); 1745 | ST7789_Width = 320; 1746 | ST7789_Height = 240; 1747 | ST7789_X_Start = 0; 1748 | ST7789_Y_Start = 0; 1749 | ST7789_FillScreen(0); 1750 | #endif 1751 | //========================================================================== 1752 | break; 1753 | 1754 | default: 1755 | break; 1756 | } 1757 | 1758 | ST7789_Unselect(); 1759 | } 1760 | //============================================================================== 1761 | 1762 | 1763 | //============================================================================== 1764 | // Процедура рисования иконки монохромной 1765 | //============================================================================== 1766 | void ST7789_DrawBitmap(int16_t x, int16_t y, const unsigned char* bitmap, int16_t w, int16_t h, uint16_t color){ 1767 | 1768 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte 1769 | uint8_t byte = 0; 1770 | 1771 | for(int16_t j=0; j= 0 && rotatedX < ST7789_Width && rotatedY >= 0 && rotatedY < ST7789_Height) { 1823 | // Получение цвета пикселя из исходного изображения 1824 | uint8_t byteWidth = (w + 7) / 8; 1825 | uint8_t byte = (*(const unsigned char*)(&bitmap[j * byteWidth + i / 8])); 1826 | if (byte & (0x80 >> (i & 7))) { 1827 | // Рисование пикселя на экране 1828 | ST7789_DrawPixel(rotatedX, rotatedY, color); 1829 | } 1830 | } 1831 | } 1832 | } 1833 | } 1834 | //============================================================================== 1835 | 1836 | 1837 | //============================================================================== 1838 | // Процедура рисования прямоугольник с закругленніми краями ( заполненый ) 1839 | //============================================================================== 1840 | void ST7789_DrawFillRoundRect(int16_t x, int16_t y, uint16_t width, uint16_t height, int16_t cornerRadius, uint16_t color) { 1841 | 1842 | int16_t max_radius = ((width < height) ? width : height) / 2; // 1/2 minor axis 1843 | if (cornerRadius > max_radius){ 1844 | cornerRadius = max_radius; 1845 | } 1846 | 1847 | ST7789_DrawRectangleFilled(x + cornerRadius, y, x + cornerRadius + width - 2 * cornerRadius, y + height, color); 1848 | // draw four corners 1849 | ST7789_DrawFillCircleHelper(x + width - cornerRadius - 1, y + cornerRadius, cornerRadius, 1, height - 2 * cornerRadius - 1, color); 1850 | ST7789_DrawFillCircleHelper(x + cornerRadius, y + cornerRadius, cornerRadius, 2, height - 2 * cornerRadius - 1, color); 1851 | } 1852 | //============================================================================== 1853 | 1854 | //============================================================================== 1855 | // Процедура рисования половины окружности ( правая или левая ) ( заполненый ) 1856 | //============================================================================== 1857 | void ST7789_DrawFillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta, uint16_t color) { 1858 | 1859 | int16_t f = 1 - r; 1860 | int16_t ddF_x = 1; 1861 | int16_t ddF_y = -2 * r; 1862 | int16_t x = 0; 1863 | int16_t y = r; 1864 | int16_t px = x; 1865 | int16_t py = y; 1866 | 1867 | delta++; // Avoid some +1's in the loop 1868 | 1869 | while (x < y) { 1870 | if (f >= 0) { 1871 | y--; 1872 | ddF_y += 2; 1873 | f += ddF_y; 1874 | } 1875 | x++; 1876 | ddF_x += 2; 1877 | f += ddF_x; 1878 | 1879 | if (x < (y + 1)) { 1880 | if (corners & 1){ 1881 | ST7789_DrawLine(x0 + x, y0 - y, x0 + x, y0 - y - 1 + 2 * y + delta, color); 1882 | } 1883 | if (corners & 2){ 1884 | ST7789_DrawLine(x0 - x, y0 - y, x0 - x, y0 - y - 1 + 2 * y + delta, color); 1885 | } 1886 | } 1887 | if (y != py) { 1888 | if (corners & 1){ 1889 | ST7789_DrawLine(x0 + py, y0 - px, x0 + py, y0 - px - 1 + 2 * px + delta, color); 1890 | } 1891 | if (corners & 2){ 1892 | ST7789_DrawLine(x0 - py, y0 - px, x0 - py, y0 - px - 1 + 2 * px + delta, color); 1893 | } 1894 | py = y; 1895 | } 1896 | px = x; 1897 | } 1898 | } 1899 | //============================================================================== 1900 | 1901 | //============================================================================== 1902 | // Процедура рисования четверти окружности (закругление, дуга) ( ширина 1 пиксель) 1903 | //============================================================================== 1904 | void ST7789_DrawCircleHelper(int16_t x0, int16_t y0, int16_t radius, int8_t quadrantMask, uint16_t color) 1905 | { 1906 | int16_t f = 1 - radius ; 1907 | int16_t ddF_x = 1; 1908 | int16_t ddF_y = -2 * radius; 1909 | int16_t x = 0; 1910 | int16_t y = radius; 1911 | 1912 | while (x <= y) { 1913 | if (f >= 0) { 1914 | y--; 1915 | ddF_y += 2; 1916 | f += ddF_y; 1917 | } 1918 | 1919 | x++; 1920 | ddF_x += 2; 1921 | f += ddF_x; 1922 | 1923 | if (quadrantMask & 0x4) { 1924 | ST7789_DrawPixel(x0 + x, y0 + y, color); 1925 | ST7789_DrawPixel(x0 + y, y0 + x, color);; 1926 | } 1927 | if (quadrantMask & 0x2) { 1928 | ST7789_DrawPixel(x0 + x, y0 - y, color); 1929 | ST7789_DrawPixel(x0 + y, y0 - x, color); 1930 | } 1931 | if (quadrantMask & 0x8) { 1932 | ST7789_DrawPixel(x0 - y, y0 + x, color); 1933 | ST7789_DrawPixel(x0 - x, y0 + y, color); 1934 | } 1935 | if (quadrantMask & 0x1) { 1936 | ST7789_DrawPixel(x0 - y, y0 - x, color); 1937 | ST7789_DrawPixel(x0 - x, y0 - y, color); 1938 | } 1939 | } 1940 | } 1941 | //============================================================================== 1942 | 1943 | //============================================================================== 1944 | // Процедура рисования прямоугольник с закругленніми краями ( пустотелый ) 1945 | //============================================================================== 1946 | void ST7789_DrawRoundRect(int16_t x, int16_t y, uint16_t width, uint16_t height, int16_t cornerRadius, uint16_t color) { 1947 | 1948 | int16_t max_radius = ((width < height) ? width : height) / 2; // 1/2 minor axis 1949 | if (cornerRadius > max_radius){ 1950 | cornerRadius = max_radius; 1951 | } 1952 | 1953 | ST7789_DrawLine(x + cornerRadius, y, x + cornerRadius + width -1 - 2 * cornerRadius, y, color); // Top 1954 | ST7789_DrawLine(x + cornerRadius, y + height - 1, x + cornerRadius + width - 1 - 2 * cornerRadius, y + height - 1, color); // Bottom 1955 | ST7789_DrawLine(x, y + cornerRadius, x, y + cornerRadius + height - 1 - 2 * cornerRadius, color); // Left 1956 | ST7789_DrawLine(x + width - 1, y + cornerRadius, x + width - 1, y + cornerRadius + height - 1 - 2 * cornerRadius, color); // Right 1957 | 1958 | // draw four corners 1959 | ST7789_DrawCircleHelper(x + cornerRadius, y + cornerRadius, cornerRadius, 1, color); 1960 | ST7789_DrawCircleHelper(x + width - cornerRadius - 1, y + cornerRadius, cornerRadius, 2, color); 1961 | ST7789_DrawCircleHelper(x + width - cornerRadius - 1, y + height - cornerRadius - 1, cornerRadius, 4, color); 1962 | ST7789_DrawCircleHelper(x + cornerRadius, y + height - cornerRadius - 1, cornerRadius, 8, color); 1963 | } 1964 | //============================================================================== 1965 | 1966 | //============================================================================== 1967 | // Процедура рисования линия толстая ( последний параметр толщина ) 1968 | //============================================================================== 1969 | void ST7789_DrawLineThick(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color, uint8_t thick) { 1970 | const int16_t deltaX = abs(x2 - x1); 1971 | const int16_t deltaY = abs(y2 - y1); 1972 | const int16_t signX = x1 < x2 ? 1 : -1; 1973 | const int16_t signY = y1 < y2 ? 1 : -1; 1974 | 1975 | int16_t error = deltaX - deltaY; 1976 | 1977 | if (thick > 1){ 1978 | ST7789_DrawCircleFilled(x2, y2, thick >> 1, color); 1979 | } 1980 | else{ 1981 | ST7789_DrawPixel(x2, y2, color); 1982 | } 1983 | 1984 | while (x1 != x2 || y1 != y2) { 1985 | if (thick > 1){ 1986 | ST7789_DrawCircleFilled(x1, y1, thick >> 1, color); 1987 | } 1988 | else{ 1989 | ST7789_DrawPixel(x1, y1, color); 1990 | } 1991 | 1992 | const int16_t error2 = error * 2; 1993 | if (error2 > -deltaY) { 1994 | error -= deltaY; 1995 | x1 += signX; 1996 | } 1997 | if (error2 < deltaX) { 1998 | error += deltaX; 1999 | y1 += signY; 2000 | } 2001 | } 2002 | } 2003 | //============================================================================== 2004 | 2005 | 2006 | //============================================================================== 2007 | // линия толстая нужной длины и указаным углом поворота (0-360) ( последний параметр толшина ) 2008 | //============================================================================== 2009 | void ST7789_DrawLineThickWithAngle(int16_t x, int16_t y, int16_t length, double angle_degrees, uint16_t color, uint8_t thick) { 2010 | double angleRad = (360.0 - angle_degrees) * PI / 180.0; 2011 | int16_t x2 = x + (int16_t)(cos(angleRad) * length) + 0.5; 2012 | int16_t y2 = y + (int16_t)(sin(angleRad) * length) + 0.5; 2013 | 2014 | ST7789_DrawLineThick(x, y, x2, y2, color, thick); 2015 | } 2016 | //============================================================================== 2017 | 2018 | 2019 | //============================================================================== 2020 | // Процедура рисования дуга толстая ( часть круга ) 2021 | //============================================================================== 2022 | void ST7789_DrawArc(int16_t x0, int16_t y0, int16_t radius, int16_t startAngle, int16_t endAngle, uint16_t color, uint8_t thick) { 2023 | 2024 | int16_t xLast = -1, yLast = -1; 2025 | 2026 | if (startAngle > endAngle) { 2027 | // Рисование первой части дуги от startAngle до 360 градусов 2028 | for (int16_t angle = startAngle; angle <= 360; angle += 2) { 2029 | float angleRad = (float)(360 - angle) * PI / 180; 2030 | int x = cos(angleRad) * radius + x0; 2031 | int y = sin(angleRad) * radius + y0; 2032 | 2033 | if (xLast != -1 && yLast != -1) { 2034 | if (thick > 1) { 2035 | ST7789_DrawLineThick(xLast, yLast, x, y, color, thick); 2036 | } else { 2037 | ST7789_DrawLine(xLast, yLast, x, y, color); 2038 | } 2039 | } 2040 | 2041 | xLast = x; 2042 | yLast = y; 2043 | } 2044 | 2045 | // Рисование второй части дуги от 0 до endAngle 2046 | for (int16_t angle = 0; angle <= endAngle; angle += 2) { 2047 | float angleRad = (float)(360 - angle) * PI / 180; 2048 | int x = cos(angleRad) * radius + x0; 2049 | int y = sin(angleRad) * radius + y0; 2050 | 2051 | if (xLast != -1 && yLast != -1) { 2052 | if (thick > 1) { 2053 | ST7789_DrawLineThick(xLast, yLast, x, y, color, thick); 2054 | } else { 2055 | ST7789_DrawLine(xLast, yLast, x, y, color); 2056 | } 2057 | } 2058 | 2059 | xLast = x; 2060 | yLast = y; 2061 | } 2062 | } else { 2063 | // Рисование дуги от startAngle до endAngle 2064 | for (int16_t angle = startAngle; angle <= endAngle; angle += 2) { 2065 | float angleRad = (float)(360 - angle) * PI / 180; 2066 | int x = cos(angleRad) * radius + x0; 2067 | int y = sin(angleRad) * radius + y0; 2068 | 2069 | if (xLast != -1 && yLast != -1) { 2070 | if (thick > 1) { 2071 | ST7789_DrawLineThick(xLast, yLast, x, y, color, thick); 2072 | } else { 2073 | ST7789_DrawLine(xLast, yLast, x, y, color); 2074 | } 2075 | } 2076 | 2077 | xLast = x; 2078 | yLast = y; 2079 | } 2080 | } 2081 | } 2082 | //============================================================================== 2083 | 2084 | 2085 | #if FRAME_BUFFER 2086 | //============================================================================== 2087 | // Процедура вывода буффера кадра на дисплей 2088 | //============================================================================== 2089 | void ST7789_Update(void){ 2090 | 2091 | ST7789_SetWindow(0, 0, ST7789_Width-1, ST7789_Height-1); 2092 | 2093 | ST7789_Select(); 2094 | 2095 | ST7789_SendDataMASS((uint8_t*)buff_frame, sizeof(uint16_t)*ST7789_Width*ST7789_Height); 2096 | 2097 | ST7789_Unselect(); 2098 | } 2099 | //============================================================================== 2100 | 2101 | //============================================================================== 2102 | // Процедура очистка только буфера кадра ( при етом сам экран не очищаеться ) 2103 | //============================================================================== 2104 | void ST7789_ClearFrameBuffer(void){ 2105 | memset((uint8_t*)buff_frame, 0x00, ST7789_Width*ST7789_Height*sizeof(uint16_t) ); 2106 | } 2107 | //============================================================================== 2108 | #endif 2109 | 2110 | 2111 | 2112 | 2113 | //######################################################################################################################### 2114 | //######################################################################################################################### 2115 | 2116 | 2117 | 2118 | 2119 | /************************ (C) COPYRIGHT GKP *****END OF FILE****/ 2120 | --------------------------------------------------------------------------------