oled displey

Committer:
docent
Date:
Tue Jul 23 12:32:26 2019 +0000
Revision:
0:cd4a2add97a0
for my students

Who changed what in which revision?

UserRevisionLine numberNew contents of line
docent 0:cd4a2add97a0 1 /****************************************************************************/
docent 0:cd4a2add97a0 2 // Function: Cpp file for TroykaOLED
docent 0:cd4a2add97a0 3 // Hardware: SSD1306
docent 0:cd4a2add97a0 4 // Arduino IDE: Arduino-1.8.5
docent 0:cd4a2add97a0 5 // Author: Igor Dementiev
docent 0:cd4a2add97a0 6 // Date: NOV 10,2018
docent 0:cd4a2add97a0 7 // Version: v1.0.0
docent 0:cd4a2add97a0 8 // by www.amperka.ru
docent 0:cd4a2add97a0 9 /****************************************************************************/
docent 0:cd4a2add97a0 10
docent 0:cd4a2add97a0 11 #include "TroykaOLED.h"
docent 0:cd4a2add97a0 12 #define pgm_read_byte * //my
docent 0:cd4a2add97a0 13 TroykaOLED::TroykaOLED (I2C *i2c,uint8_t i2cAddress, uint8_t width, uint8_t height):
docent 0:cd4a2add97a0 14 _wire(i2c)
docent 0:cd4a2add97a0 15 {
docent 0:cd4a2add97a0 16 _i2cAddress = i2cAddress;
docent 0:cd4a2add97a0 17 _width = width;
docent 0:cd4a2add97a0 18 _height = height;
docent 0:cd4a2add97a0 19 _bufferDisplay = new uint8_t[_width * _height / 8];
docent 0:cd4a2add97a0 20 _stateInvert = false;
docent 0:cd4a2add97a0 21 _stateAutoUpdate = true;
docent 0:cd4a2add97a0 22 _stateImageBG = true;
docent 0:cd4a2add97a0 23 _codingName = TXT_UTF8;
docent 0:cd4a2add97a0 24 }
docent 0:cd4a2add97a0 25
docent 0:cd4a2add97a0 26 void TroykaOLED::begin() {
docent 0:cd4a2add97a0 27 _font.width=0;
docent 0:cd4a2add97a0 28 _font.height=0;
docent 0:cd4a2add97a0 29 _font.firstSymbol=0;
docent 0:cd4a2add97a0 30 _font.sumSymbol=0;
docent 0:cd4a2add97a0 31 _font.invert=false;
docent 0:cd4a2add97a0 32 _font.background= true;
docent 0:cd4a2add97a0 33 _font.setFont= false;
docent 0:cd4a2add97a0 34 // _wire = wire;
docent 0:cd4a2add97a0 35 // инициируем I²C
docent 0:cd4a2add97a0 36 // _wire->begin();
docent 0:cd4a2add97a0 37
docent 0:cd4a2add97a0 38 // выключаем дисплей
docent 0:cd4a2add97a0 39 _sendCommand(SSD1306_DISPLAY_OFF);
docent 0:cd4a2add97a0 40 // устанавливаем частоту обновления дисплея в значение 0x80 (по умолчанию)
docent 0:cd4a2add97a0 41 _sendCommand(SSD1306_SET_DISPLAY_CLOCK);
docent 0:cd4a2add97a0 42 _sendCommand(0x80);
docent 0:cd4a2add97a0 43 // устанавливаем multiplex ratio (коэффициент мультиплексирования COM выводов) в значение 0x3F (по умолчанию)
docent 0:cd4a2add97a0 44 _sendCommand(SSD1306_SET_MULTIPLEX_RATIO);
docent 0:cd4a2add97a0 45 _sendCommand(0x3F);
docent 0:cd4a2add97a0 46 // устанавливаем смещение дисплея в 0 (без смещения)
docent 0:cd4a2add97a0 47 _sendCommand(SSD1306_SET_DISPLAY_OFFSET);
docent 0:cd4a2add97a0 48 _sendCommand(0x00);
docent 0:cd4a2add97a0 49 // устанавливаем смещение ОЗУ в значение 0 (без смещения)
docent 0:cd4a2add97a0 50 _sendCommand(SSD1306_SET_START_LINE | 0);
docent 0:cd4a2add97a0 51 // настраиваем схему питания (0x14 - включить внутренний DC-DC преобразователь, 0x10 - отключить внутренний DC/DC)
docent 0:cd4a2add97a0 52 _sendCommand(SSD1306_CHARGE_DCDC_PUMP);
docent 0:cd4a2add97a0 53 _sendCommand(0x14);
docent 0:cd4a2add97a0 54 // устанавливаем режим автоматической адресации (0x00-горизонтальная, 0x01-вертикальная, 0x10-страничная)
docent 0:cd4a2add97a0 55 _sendCommand(SSD1306_ADDR_MODE);
docent 0:cd4a2add97a0 56 _sendCommand(0x00);
docent 0:cd4a2add97a0 57 // устанавливаем режим строчной развертки (слева/направо)
docent 0:cd4a2add97a0 58 _sendCommand(SSD1306_SET_REMAP_L_TO_R);
docent 0:cd4a2add97a0 59 // устанавливаем режим кадровой развертки (сверху/вниз)
docent 0:cd4a2add97a0 60 _sendCommand(SSD1306_SET_REMAP_T_TO_D);
docent 0:cd4a2add97a0 61 // устанавливаем аппаратную конфигурация COM выводов в значение 0x12 (по умолчанию)
docent 0:cd4a2add97a0 62 _sendCommand(SSD1306_SET_COM_PINS);
docent 0:cd4a2add97a0 63 _sendCommand(0x12);
docent 0:cd4a2add97a0 64 // устанавливаем контрастность в значение 0xCF (допустимы значения от 0x00 до 0xFF)
docent 0:cd4a2add97a0 65 _sendCommand(SSD1306_SET_CONTRAST);
docent 0:cd4a2add97a0 66 _sendCommand(0xFF);
docent 0:cd4a2add97a0 67 // настраиваем схему DC/DC преобразователя (0xF1 - Vcc снимается с DC/DC преобразователя, 0x22 - Vcc подается извне)
docent 0:cd4a2add97a0 68 _sendCommand(SSD1306_SET_PRECHARGE_PERIOD);
docent 0:cd4a2add97a0 69 _sendCommand(0xF1);
docent 0:cd4a2add97a0 70 // устанавливаем питание светодиодов VcomH в значение выше чем по умолчанию: 0x30
docent 0:cd4a2add97a0 71 // это увеличит яркость дисплея
docent 0:cd4a2add97a0 72 // допустимые значения: 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70
docent 0:cd4a2add97a0 73 _sendCommand(SSD1306_SET_VCOM_DESELECT);
docent 0:cd4a2add97a0 74 _sendCommand(0x40);
docent 0:cd4a2add97a0 75 // разрешаем отображать содержимое RAM памяти
docent 0:cd4a2add97a0 76 _sendCommand(SSD1306_RAM_ON);
docent 0:cd4a2add97a0 77 // отключаем инверсию
docent 0:cd4a2add97a0 78 _sendCommand(SSD1306_INVERT_OFF);
docent 0:cd4a2add97a0 79 // включаем дисплей
docent 0:cd4a2add97a0 80 _sendCommand(SSD1306_DISPLAY_ON);
docent 0:cd4a2add97a0 81 // чистим экран
docent 0:cd4a2add97a0 82 clearDisplay();
docent 0:cd4a2add97a0 83 }
docent 0:cd4a2add97a0 84
docent 0:cd4a2add97a0 85 void TroykaOLED::update() {
docent 0:cd4a2add97a0 86 _sendBuffer();
docent 0:cd4a2add97a0 87 }
docent 0:cd4a2add97a0 88
docent 0:cd4a2add97a0 89 void TroykaOLED::autoUpdate(bool stateAutoUpdate) {
docent 0:cd4a2add97a0 90 _stateAutoUpdate = stateAutoUpdate;
docent 0:cd4a2add97a0 91 }
docent 0:cd4a2add97a0 92
docent 0:cd4a2add97a0 93 void TroykaOLED::setBrigtness(uint8_t brigtness) {
docent 0:cd4a2add97a0 94 _sendCommand(SSD1306_SET_CONTRAST);
docent 0:cd4a2add97a0 95 _sendCommand(brigtness);
docent 0:cd4a2add97a0 96 }
docent 0:cd4a2add97a0 97
docent 0:cd4a2add97a0 98 void TroykaOLED::clearDisplay() {
docent 0:cd4a2add97a0 99 memset(_bufferDisplay, 0, _width * _height / 8);
docent 0:cd4a2add97a0 100
docent 0:cd4a2add97a0 101 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 102 _sendBuffer();
docent 0:cd4a2add97a0 103 }
docent 0:cd4a2add97a0 104 }
docent 0:cd4a2add97a0 105
docent 0:cd4a2add97a0 106 void TroykaOLED::invertDisplay(bool stateInvert) {
docent 0:cd4a2add97a0 107 if(stateInvert) {
docent 0:cd4a2add97a0 108 _stateInvert = true;
docent 0:cd4a2add97a0 109 _sendCommand(SSD1306_INVERT_ON);
docent 0:cd4a2add97a0 110 } else {
docent 0:cd4a2add97a0 111 _stateInvert = false;
docent 0:cd4a2add97a0 112 _sendCommand(SSD1306_INVERT_OFF);
docent 0:cd4a2add97a0 113 }
docent 0:cd4a2add97a0 114 }
docent 0:cd4a2add97a0 115
docent 0:cd4a2add97a0 116 void TroykaOLED::invertText (bool stateInvertText) {
docent 0:cd4a2add97a0 117 _font.invert = stateInvertText;
docent 0:cd4a2add97a0 118 }
docent 0:cd4a2add97a0 119
docent 0:cd4a2add97a0 120 void TroykaOLED::bgText (bool stateTextBG) {
docent 0:cd4a2add97a0 121 _font.background = stateTextBG;
docent 0:cd4a2add97a0 122 }
docent 0:cd4a2add97a0 123
docent 0:cd4a2add97a0 124 void TroykaOLED::bgImage (bool stateImageBG) {
docent 0:cd4a2add97a0 125 _stateImageBG = stateImageBG;
docent 0:cd4a2add97a0 126 }
docent 0:cd4a2add97a0 127
docent 0:cd4a2add97a0 128 void TroykaOLED::setFont(const uint8_t* fontData) {
docent 0:cd4a2add97a0 129 // сохраняем указатель на первый байт массива в области памяти программ
docent 0:cd4a2add97a0 130 _font.fontData = fontData;
docent 0:cd4a2add97a0 131 // сохраняем ширину символов выбранного шрифта читая её из 0 байта массива по указателю fontData
docent 0:cd4a2add97a0 132 _font.width = pgm_read_byte(&fontData[0]);
docent 0:cd4a2add97a0 133 // сохраняем высоту символов выбранного шрифта читая её из 1 байта массива по указателю fontData
docent 0:cd4a2add97a0 134 _font.height = pgm_read_byte(&fontData[1]);
docent 0:cd4a2add97a0 135 // сохраняем код первого симола выбран. шрифта читая его из 2 байта массива по указателю fontData
docent 0:cd4a2add97a0 136 _font.firstSymbol = pgm_read_byte(&fontData[2]);
docent 0:cd4a2add97a0 137 // сохраняем количество символов в выбр шрифте читая их из 3 байта массива по указателю fontData
docent 0:cd4a2add97a0 138 _font.sumSymbol = pgm_read_byte(&fontData[3]);
docent 0:cd4a2add97a0 139 // устанавливаем флаг выбора шрифта
docent 0:cd4a2add97a0 140 _font.setFont = true;
docent 0:cd4a2add97a0 141 // определяем позицию бита указывающего количество пустых интервалов в массиве шрифта.
docent 0:cd4a2add97a0 142 uint16_t i = (uint16_t) _font.sumSymbol * _font.width * _font.height / 8 + 0x04;
docent 0:cd4a2add97a0 143 // определяем количество пустых интервалов в массиве шрифта.
docent 0:cd4a2add97a0 144 uint16_t j = pgm_read_byte(&fontData[i]);
docent 0:cd4a2add97a0 145 // указываем что первый пустой интервал в массиве шрифта находится после символа с кодом (0xFF) и состоит из 0 символов
docent 0:cd4a2add97a0 146 _font.startSpace[0] = 0xFF;
docent 0:cd4a2add97a0 147 _font.sumSpace[0] = 0;
docent 0:cd4a2add97a0 148 // указываем что второй пустой интервал в массиве шрифта находится после символа с кодом (0xFF) и состоит из 0 символов
docent 0:cd4a2add97a0 149 _font.startSpace[1] = 0xFF;
docent 0:cd4a2add97a0 150 _font.sumSpace[1] = 0;
docent 0:cd4a2add97a0 151 // указываем что третий пустой интервал в массиве шрифта находится после символа с кодом (0xFF) и состоит из 0 символов
docent 0:cd4a2add97a0 152 _font.startSpace[2] = 0xFF;
docent 0:cd4a2add97a0 153 _font.sumSpace[2] = 0;
docent 0:cd4a2add97a0 154 // если количество пустых интервалов больше 0
docent 0:cd4a2add97a0 155 // сохраняем начало первого пустого интервала символов и размер первого пустого интервала символов
docent 0:cd4a2add97a0 156 if (j > 0) {
docent 0:cd4a2add97a0 157 _font.startSpace[0] = pgm_read_byte(&fontData[i + 1]);
docent 0:cd4a2add97a0 158 _font.sumSpace[0] = pgm_read_byte(&fontData[i + 2]);
docent 0:cd4a2add97a0 159 }
docent 0:cd4a2add97a0 160 // если количество пустых интервалов больше 1
docent 0:cd4a2add97a0 161 // сохраняем начало второго пустого интервала символов и размер второго пустого интервала символов
docent 0:cd4a2add97a0 162 if (j > 1) {
docent 0:cd4a2add97a0 163 _font.startSpace[1] = pgm_read_byte(&fontData[i + 3]);
docent 0:cd4a2add97a0 164 _font.sumSpace[1] = pgm_read_byte(&fontData[i + 4]);
docent 0:cd4a2add97a0 165 }
docent 0:cd4a2add97a0 166 // если количество пустых интервалов больше 2
docent 0:cd4a2add97a0 167 // сохраняем начало третьего пустого интервала символов и размер третьего пустого интервала символов
docent 0:cd4a2add97a0 168 if (j > 2) {
docent 0:cd4a2add97a0 169 _font.startSpace[2] = pgm_read_byte(&fontData[i + 5]);
docent 0:cd4a2add97a0 170 _font.sumSpace[2] = pgm_read_byte(&fontData[i + 6]);
docent 0:cd4a2add97a0 171 }
docent 0:cd4a2add97a0 172 }
docent 0:cd4a2add97a0 173
docent 0:cd4a2add97a0 174 void TroykaOLED::setCoding(uint8_t codingName) {
docent 0:cd4a2add97a0 175 _codingName = codingName;
docent 0:cd4a2add97a0 176 }
docent 0:cd4a2add97a0 177
docent 0:cd4a2add97a0 178 void TroykaOLED::setCursor(int numX, int numY) {
docent 0:cd4a2add97a0 179 if(numX < _width) {
docent 0:cd4a2add97a0 180 _numX = numX;
docent 0:cd4a2add97a0 181 }
docent 0:cd4a2add97a0 182 if(numY < _height) {
docent 0:cd4a2add97a0 183 _numY = numY;
docent 0:cd4a2add97a0 184 }
docent 0:cd4a2add97a0 185 }
docent 0:cd4a2add97a0 186
docent 0:cd4a2add97a0 187 void TroykaOLED::print(char* data, int x, int y) {
docent 0:cd4a2add97a0 188 _print(_codingCP866(data), x, y);
docent 0:cd4a2add97a0 189 }
docent 0:cd4a2add97a0 190 /*
docent 0:cd4a2add97a0 191 void TroykaOLED::print(String str, int x, int y) {
docent 0:cd4a2add97a0 192 char data[str.length() + 1];
docent 0:cd4a2add97a0 193 str.toCharArray(data, str.length() + 1);
docent 0:cd4a2add97a0 194 _print(_codingCP866(data), x, y);
docent 0:cd4a2add97a0 195 }
docent 0:cd4a2add97a0 196 */
docent 0:cd4a2add97a0 197 void TroykaOLED::print(const char* str, int x, int y) {
docent 0:cd4a2add97a0 198 char data[strlen(str) + 1];
docent 0:cd4a2add97a0 199 for (uint8_t i = 0; i <= strlen(str); i++) {
docent 0:cd4a2add97a0 200 data[i] = str[i];
docent 0:cd4a2add97a0 201 }
docent 0:cd4a2add97a0 202 _print(_codingCP866(data), x, y);
docent 0:cd4a2add97a0 203 }
docent 0:cd4a2add97a0 204
docent 0:cd4a2add97a0 205 void TroykaOLED::print(int8_t num, int x, int y, uint8_t base) {
docent 0:cd4a2add97a0 206 print(int32_t(num), x, y, base);
docent 0:cd4a2add97a0 207 }
docent 0:cd4a2add97a0 208
docent 0:cd4a2add97a0 209 void TroykaOLED::print(uint8_t num, int x, int y, uint8_t base) {
docent 0:cd4a2add97a0 210 print(uint32_t(num), x, y, base);
docent 0:cd4a2add97a0 211 }
docent 0:cd4a2add97a0 212
docent 0:cd4a2add97a0 213 void TroykaOLED::print(int16_t num, int x, int y, uint8_t base) {
docent 0:cd4a2add97a0 214 print(int32_t(num), x, y, base);
docent 0:cd4a2add97a0 215 }
docent 0:cd4a2add97a0 216
docent 0:cd4a2add97a0 217 void TroykaOLED::print(uint16_t num, int x, int y, uint8_t base) {
docent 0:cd4a2add97a0 218 print(uint32_t(num), x, y, base);
docent 0:cd4a2add97a0 219 }
docent 0:cd4a2add97a0 220
docent 0:cd4a2add97a0 221 void TroykaOLED::print(int32_t num, int x, int y, uint8_t base) {
docent 0:cd4a2add97a0 222 // определяем количество разрядов числа
docent 0:cd4a2add97a0 223 // i = количество разрядов + 2, j = множитель кратный основанию системы счисления
docent 0:cd4a2add97a0 224 int8_t i = 2;
docent 0:cd4a2add97a0 225 int32_t j = 1;
docent 0:cd4a2add97a0 226 while (num / j) {
docent 0:cd4a2add97a0 227 j *= base;
docent 0:cd4a2add97a0 228 i++;
docent 0:cd4a2add97a0 229 }
docent 0:cd4a2add97a0 230 // создаём строку k из i символов и добавляем символ(ы) конца строки
docent 0:cd4a2add97a0 231 char k[i];
docent 0:cd4a2add97a0 232 i--;
docent 0:cd4a2add97a0 233 k[i] = 0;
docent 0:cd4a2add97a0 234 i--;
docent 0:cd4a2add97a0 235 if(num > 0) {
docent 0:cd4a2add97a0 236 k[i] = 0;
docent 0:cd4a2add97a0 237 i--;
docent 0:cd4a2add97a0 238 }
docent 0:cd4a2add97a0 239 // создаём строку k из i символов и добавляем символ(ы) конца строки
docent 0:cd4a2add97a0 240 uint32_t n = num < 0 ? num*-1 : num;
docent 0:cd4a2add97a0 241 while (i) {
docent 0:cd4a2add97a0 242 k[i]=_itoa(n % base);
docent 0:cd4a2add97a0 243 n /= base; i--;
docent 0:cd4a2add97a0 244 }
docent 0:cd4a2add97a0 245 // заполняем строку k
docent 0:cd4a2add97a0 246 if (num >= 0) {
docent 0:cd4a2add97a0 247 k[i]=_itoa(n % base);
docent 0:cd4a2add97a0 248 } else {
docent 0:cd4a2add97a0 249 k[i]='-';
docent 0:cd4a2add97a0 250 }
docent 0:cd4a2add97a0 251 // добавляем первый символ (либо первая цифра, либо знак минус)
docent 0:cd4a2add97a0 252 // выводим строку k
docent 0:cd4a2add97a0 253 print(k, x, y);
docent 0:cd4a2add97a0 254 }
docent 0:cd4a2add97a0 255
docent 0:cd4a2add97a0 256 void TroykaOLED::print(uint32_t num, int x, int y, uint8_t base) {
docent 0:cd4a2add97a0 257 // определяем количество разрядов числа
docent 0:cd4a2add97a0 258 // i = количество разрядов + 1, j = множитель кратный основанию системы счисления
docent 0:cd4a2add97a0 259 int8_t i = 1;
docent 0:cd4a2add97a0 260 uint32_t j = 1;
docent 0:cd4a2add97a0 261 while (num / j) {
docent 0:cd4a2add97a0 262 j *= base;
docent 0:cd4a2add97a0 263 i++;
docent 0:cd4a2add97a0 264 }
docent 0:cd4a2add97a0 265 if (num == 0) {
docent 0:cd4a2add97a0 266 i++;
docent 0:cd4a2add97a0 267 }
docent 0:cd4a2add97a0 268 // определяем строку k из i символов и заполняем её
docent 0:cd4a2add97a0 269 char k[i];
docent 0:cd4a2add97a0 270 i--;
docent 0:cd4a2add97a0 271 k[i] = 0;
docent 0:cd4a2add97a0 272
docent 0:cd4a2add97a0 273 while(i) {
docent 0:cd4a2add97a0 274 k[i - 1] = _itoa(num % base);
docent 0:cd4a2add97a0 275 num /= base;
docent 0:cd4a2add97a0 276 i--;
docent 0:cd4a2add97a0 277 }
docent 0:cd4a2add97a0 278 // выводим строку k
docent 0:cd4a2add97a0 279 print(k, x, y);
docent 0:cd4a2add97a0 280 }
docent 0:cd4a2add97a0 281
docent 0:cd4a2add97a0 282 void TroykaOLED::print(double num, int x, int y, uint8_t sum) {
docent 0:cd4a2add97a0 283 uint32_t i = 1, j = 0, k = 0;
docent 0:cd4a2add97a0 284 j = sum;
docent 0:cd4a2add97a0 285 while (j) {
docent 0:cd4a2add97a0 286 i *= 10;
docent 0:cd4a2add97a0 287 j--;
docent 0:cd4a2add97a0 288 }
docent 0:cd4a2add97a0 289 // выводим целую часть числа
docent 0:cd4a2add97a0 290 print(int32_t(num), x, y);
docent 0:cd4a2add97a0 291 // если требуется вывести хоть один знак после запятой, то ...
docent 0:cd4a2add97a0 292 if (sum) {
docent 0:cd4a2add97a0 293 // выводим символ разделителя
docent 0:cd4a2add97a0 294 print(".");
docent 0:cd4a2add97a0 295 // получаем целое число, которое требуется вывести после запятой
docent 0:cd4a2add97a0 296 j = num * i * (num < 0 ? -1 : 1);
docent 0:cd4a2add97a0 297 j %= i;
docent 0:cd4a2add97a0 298 k = j;
docent 0:cd4a2add97a0 299 // если полученное целое число равно нулю, то выводим sum раз символ «0»
docent 0:cd4a2add97a0 300 if (j == 0) {
docent 0:cd4a2add97a0 301 while(sum) {
docent 0:cd4a2add97a0 302 print("0");
docent 0:cd4a2add97a0 303 sum--;
docent 0:cd4a2add97a0 304 }
docent 0:cd4a2add97a0 305 } else {
docent 0:cd4a2add97a0 306 // иначе, если в полученном целом числе меньше разрядов чем требуется
docent 0:cd4a2add97a0 307 // заполняем эти разряды выводя символ «0», после чего выводим само число
docent 0:cd4a2add97a0 308 while (j * 10 < i) {
docent 0:cd4a2add97a0 309 print("0");
docent 0:cd4a2add97a0 310 j *= 10;
docent 0:cd4a2add97a0 311 }
docent 0:cd4a2add97a0 312 print(k);
docent 0:cd4a2add97a0 313 }
docent 0:cd4a2add97a0 314 }
docent 0:cd4a2add97a0 315 }
docent 0:cd4a2add97a0 316
docent 0:cd4a2add97a0 317 void TroykaOLED::drawPixel(int x, int y, uint8_t color) {
docent 0:cd4a2add97a0 318 _drawPixel(x, y, color);
docent 0:cd4a2add97a0 319 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 320 _sendBuffer();
docent 0:cd4a2add97a0 321 }
docent 0:cd4a2add97a0 322 _numX = x;
docent 0:cd4a2add97a0 323 _numY = y;
docent 0:cd4a2add97a0 324 }
docent 0:cd4a2add97a0 325
docent 0:cd4a2add97a0 326 void TroykaOLED::drawLine(int x1, int y1, int x2, int y2, uint8_t color) {
docent 0:cd4a2add97a0 327 _drawLine(x1, y1, x2, y2, color);
docent 0:cd4a2add97a0 328 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 329 _sendBuffer();
docent 0:cd4a2add97a0 330 }
docent 0:cd4a2add97a0 331 _numX = x2;
docent 0:cd4a2add97a0 332 _numY = y2;
docent 0:cd4a2add97a0 333 }
docent 0:cd4a2add97a0 334
docent 0:cd4a2add97a0 335 void TroykaOLED::drawLine(int x2, int y2, uint8_t color) {
docent 0:cd4a2add97a0 336 drawLine(_numX, _numY, x2, y2, color);
docent 0:cd4a2add97a0 337 }
docent 0:cd4a2add97a0 338
docent 0:cd4a2add97a0 339 void TroykaOLED::drawRect(int x1, int y1, int x2, int y2, bool fill, uint8_t color) {
docent 0:cd4a2add97a0 340 if (fill) {
docent 0:cd4a2add97a0 341 if (x1 < x2) {
docent 0:cd4a2add97a0 342 for (int x = x1; x <= x2; x++) {
docent 0:cd4a2add97a0 343 _drawLine(x,y1,x,y2,color);
docent 0:cd4a2add97a0 344 }
docent 0:cd4a2add97a0 345 } else {
docent 0:cd4a2add97a0 346 for (int x = x1; x >= x2; x--) {
docent 0:cd4a2add97a0 347 _drawLine(x,y1,x,y2,color);
docent 0:cd4a2add97a0 348 }
docent 0:cd4a2add97a0 349 }
docent 0:cd4a2add97a0 350 } else {
docent 0:cd4a2add97a0 351 _drawLine(x1, y1, x2, y1, color);
docent 0:cd4a2add97a0 352 _drawLine(x2, y2, x2, y1, color);
docent 0:cd4a2add97a0 353 _drawLine(x2, y2, x1, y2, color);
docent 0:cd4a2add97a0 354 _drawLine(x1, y1, x1, y2, color);
docent 0:cd4a2add97a0 355 }
docent 0:cd4a2add97a0 356 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 357 _sendBuffer();
docent 0:cd4a2add97a0 358 }
docent 0:cd4a2add97a0 359 _numX = x2;
docent 0:cd4a2add97a0 360 _numY = y2;
docent 0:cd4a2add97a0 361 }
docent 0:cd4a2add97a0 362
docent 0:cd4a2add97a0 363 void TroykaOLED::drawCircle(int x, int y, uint8_t r, bool fill, uint8_t color) {
docent 0:cd4a2add97a0 364 // x1,y1 - положительные координаты точек круга с центром 00
docent 0:cd4a2add97a0 365 // p - отрицательная парабола
docent 0:cd4a2add97a0 366 int x1 = 0, y1 = r, p = 1 - r;
docent 0:cd4a2add97a0 367 // цикл будет выполняться пока координата x не станет чуть меньше y
docent 0:cd4a2add97a0 368 // прочертит дугу от 0 до 45° - это 1/8 часть круга
docent 0:cd4a2add97a0 369 while (x1 < y1 + 1) {
docent 0:cd4a2add97a0 370 if (fill) {
docent 0:cd4a2add97a0 371 // прорисовываем горизонтальные линии вверху круга (между точками 3 и 1 дуг)
docent 0:cd4a2add97a0 372 _drawLine(x - x1, y - y1, x + x1, y - y1, color);
docent 0:cd4a2add97a0 373 // прорисовываем горизонтальные линии внизу круга (между точками 4 и 2 дуг)
docent 0:cd4a2add97a0 374 _drawLine(x - x1, y + y1, x + x1, y + y1, color);
docent 0:cd4a2add97a0 375 // прорисовываем горизонтальные линии выше середины круга (между точками 7 и 5 дуг)
docent 0:cd4a2add97a0 376 _drawLine(x - y1, y - x1, x + y1, y - x1, color);
docent 0:cd4a2add97a0 377 // прорисовываем горизонтальные линии выше середины круга (между точками 8 и 6 дуг)
docent 0:cd4a2add97a0 378 _drawLine(x - y1, y + x1, x + y1, y + x1, color);
docent 0:cd4a2add97a0 379 } else {
docent 0:cd4a2add97a0 380 // 1 дуга 0° - 45° (построенная в соответствии с уравнением)
docent 0:cd4a2add97a0 381 _drawPixel(x + x1, y - y1, color);
docent 0:cd4a2add97a0 382 // 2 дуга 180° - 135° (1 дуга отражённая по вертикали)
docent 0:cd4a2add97a0 383 _drawPixel(x + x1, y + y1, color);
docent 0:cd4a2add97a0 384 // 3 дуга 360° - 315° (1 дуга отражённая по горизонтали)
docent 0:cd4a2add97a0 385 _drawPixel(x - x1, y - y1, color);
docent 0:cd4a2add97a0 386 // 4 дуга 180° - 225° (2 дуга отражённая по горизонтали)
docent 0:cd4a2add97a0 387 _drawPixel(x - x1, y + y1, color);
docent 0:cd4a2add97a0 388 // 5 дуга 90° - 45° (2 дуга повёрнутая на -90°)
docent 0:cd4a2add97a0 389 _drawPixel(x + y1, y - x1, color);
docent 0:cd4a2add97a0 390 // 6 дуга 90° - 135° (1 дуга повёрнутая на +90°)
docent 0:cd4a2add97a0 391 _drawPixel(x + y1, y + x1, color);
docent 0:cd4a2add97a0 392 // 7 дуга 270° - 315° (1 дуга повёрнутая на -90°)
docent 0:cd4a2add97a0 393 _drawPixel(x - y1, y - x1, color);
docent 0:cd4a2add97a0 394 // 8 дуга 270° - 225° (2 дуга повёрнутая на +90°)
docent 0:cd4a2add97a0 395 _drawPixel(x - y1, y + x1, color);
docent 0:cd4a2add97a0 396 }
docent 0:cd4a2add97a0 397 // если парабола p вышла в положительный диапазон
docent 0:cd4a2add97a0 398 if(p >= 0) {
docent 0:cd4a2add97a0 399 // сдвигаем её вниз на y1 * 2 (каждый такой сдвиг провоцирет смещение точки y1 первой дуги вниз)
docent 0:cd4a2add97a0 400 y1--;
docent 0:cd4a2add97a0 401 p -= y1 * 2;
docent 0:cd4a2add97a0 402 }
docent 0:cd4a2add97a0 403 // с каждым проходом цикла, смещаем точку x1 первой дуги влево и находим новую координату параболы p
docent 0:cd4a2add97a0 404 p++;
docent 0:cd4a2add97a0 405 x1++;
docent 0:cd4a2add97a0 406 p += x1 * 2;
docent 0:cd4a2add97a0 407 }
docent 0:cd4a2add97a0 408 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 409 _sendBuffer();
docent 0:cd4a2add97a0 410 }
docent 0:cd4a2add97a0 411 _numX = x;
docent 0:cd4a2add97a0 412 _numY = y;
docent 0:cd4a2add97a0 413 }
docent 0:cd4a2add97a0 414
docent 0:cd4a2add97a0 415 bool TroykaOLED::bitRead(uint8_t data, uint8_t bit)
docent 0:cd4a2add97a0 416 {
docent 0:cd4a2add97a0 417 uint8_t b;
docent 0:cd4a2add97a0 418 b=(data>>bit)&1;
docent 0:cd4a2add97a0 419 if(b)
docent 0:cd4a2add97a0 420 return true;
docent 0:cd4a2add97a0 421 else
docent 0:cd4a2add97a0 422 return false;
docent 0:cd4a2add97a0 423 }
docent 0:cd4a2add97a0 424
docent 0:cd4a2add97a0 425 void TroykaOLED::drawImage(const uint8_t* image, int x, int y, uint8_t mem) {
docent 0:cd4a2add97a0 426 uint8_t w = getImageWidth(image, mem);
docent 0:cd4a2add97a0 427 uint8_t h = getImageHeight(image, mem);
docent 0:cd4a2add97a0 428 bool color;
docent 0:cd4a2add97a0 429 // колонка с которой требуется начать вывод изображения ...
docent 0:cd4a2add97a0 430 switch(x) {
docent 0:cd4a2add97a0 431 // определяем начальную колонку для выравнивания по левому краю
docent 0:cd4a2add97a0 432 case OLED_LEFT:
docent 0:cd4a2add97a0 433 _numX = 0;
docent 0:cd4a2add97a0 434 break;
docent 0:cd4a2add97a0 435 // определяем начальную колонку для выравнивания по центру
docent 0:cd4a2add97a0 436 case OLED_CENTER:
docent 0:cd4a2add97a0 437 _numX = (_width - w) / 2;
docent 0:cd4a2add97a0 438 break;
docent 0:cd4a2add97a0 439 // определяем начальную колонку для выравнивания по правому краю
docent 0:cd4a2add97a0 440 case OLED_RIGHT:
docent 0:cd4a2add97a0 441 _numX = _width - w;
docent 0:cd4a2add97a0 442 break;
docent 0:cd4a2add97a0 443 // начальной колонкой останется та, на которой был закончен вывод предыдущего текста или изображения
docent 0:cd4a2add97a0 444 case OLED_THIS:
docent 0:cd4a2add97a0 445 _numX = _numX;
docent 0:cd4a2add97a0 446 break;
docent 0:cd4a2add97a0 447 // начальная колонка определена пользователем
docent 0:cd4a2add97a0 448 default:
docent 0:cd4a2add97a0 449 _numX = x;
docent 0:cd4a2add97a0 450 break;
docent 0:cd4a2add97a0 451 }
docent 0:cd4a2add97a0 452 // строка с которой требуется начать вывод изображения ...
docent 0:cd4a2add97a0 453 switch(y) {
docent 0:cd4a2add97a0 454 // определяем начальную строку для выравнивания по верхнему краю
docent 0:cd4a2add97a0 455 case OLED_TOP:
docent 0:cd4a2add97a0 456 _numY = h - 1;
docent 0:cd4a2add97a0 457 break;
docent 0:cd4a2add97a0 458 // определяем начальную строку для выравнивания по центру
docent 0:cd4a2add97a0 459 case OLED_CENTER:
docent 0:cd4a2add97a0 460 _numY = (_height - h) / 2;
docent 0:cd4a2add97a0 461 break;
docent 0:cd4a2add97a0 462 // определяем начальную строку для выравнивания по нижнему краю
docent 0:cd4a2add97a0 463 case OLED_BOTTOM:
docent 0:cd4a2add97a0 464 _numY = _height - 1;
docent 0:cd4a2add97a0 465 break;
docent 0:cd4a2add97a0 466 // начальной строкой останется та, на которой выведен предыдущий текст или изображение
docent 0:cd4a2add97a0 467 case OLED_THIS:
docent 0:cd4a2add97a0 468 _numY = _numY;
docent 0:cd4a2add97a0 469 break;
docent 0:cd4a2add97a0 470 // начальная строка определена пользователем
docent 0:cd4a2add97a0 471 default:
docent 0:cd4a2add97a0 472 _numY = y;
docent 0:cd4a2add97a0 473 break;
docent 0:cd4a2add97a0 474 }
docent 0:cd4a2add97a0 475 // проходим по страницам изображения...
docent 0:cd4a2add97a0 476 for (uint8_t p = 0; p < h; p++) {
docent 0:cd4a2add97a0 477 // проходим по колонкам изображения...
docent 0:cd4a2add97a0 478 for (uint8_t k = 0; k < w; k++) {
docent 0:cd4a2add97a0 479 // если массив изображения находится в памяти ОЗУ
docent 0:cd4a2add97a0 480 if (mem == IMG_RAM) {
docent 0:cd4a2add97a0 481 // получаем цвет очередного пикселя из p % 8 бита
docent 0:cd4a2add97a0 482 // 2 + (p / 8 * w) + k байта, массива image
docent 0:cd4a2add97a0 483 color = bitRead(image[2 + (p / 8 * w) + k], p % 8);
docent 0:cd4a2add97a0 484 } else if (mem == IMG_ROM) {
docent 0:cd4a2add97a0 485 // если массив изображения находится в памяти ПЗУ
docent 0:cd4a2add97a0 486 // получаем цвет очередного пикселя из p % 8 бита
docent 0:cd4a2add97a0 487 // 2 + (p / 8 * w) + k байта, массива image
docent 0:cd4a2add97a0 488 color = bitRead(pgm_read_byte(&image[2 + (p / 8 * w) + k]), p % 8);
docent 0:cd4a2add97a0 489 }
docent 0:cd4a2add97a0 490 // если у изображения есть фон или цвет пикселя белый
docent 0:cd4a2add97a0 491 if (_stateImageBG || color) {
docent 0:cd4a2add97a0 492 // прорисовываем пиксель в координате (_numX + k, _numY + p)
docent 0:cd4a2add97a0 493 _drawPixel( _numX + k, _numY + p, color);
docent 0:cd4a2add97a0 494 }
docent 0:cd4a2add97a0 495 }
docent 0:cd4a2add97a0 496 }
docent 0:cd4a2add97a0 497 // добавляем ширину изображения к координате _numX
docent 0:cd4a2add97a0 498 _numX += w;
docent 0:cd4a2add97a0 499 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 500 _sendBuffer();
docent 0:cd4a2add97a0 501 }
docent 0:cd4a2add97a0 502 }
docent 0:cd4a2add97a0 503
docent 0:cd4a2add97a0 504 bool TroykaOLED::getPixel(int x, int y) {
docent 0:cd4a2add97a0 505 if(x < 0 || x > _height - 1 || y < 0 || y > _width - 1) {
docent 0:cd4a2add97a0 506 return 0;
docent 0:cd4a2add97a0 507 }
docent 0:cd4a2add97a0 508 // определяем номер байта массива _bufferDisplay в котором находится пиксель
docent 0:cd4a2add97a0 509 uint16_t numByte = (y / 8 * 128) + x;
docent 0:cd4a2add97a0 510 // определяем номер бита в найденном байте, который соответсвует искомому пикселю
docent 0:cd4a2add97a0 511 uint8_t numBit = y % 8;
docent 0:cd4a2add97a0 512 // возвращаем цвет пикселя из бита numBit элемента numByte массива _bufferDisplay
docent 0:cd4a2add97a0 513 return bitRead(_bufferDisplay[numByte], numBit);
docent 0:cd4a2add97a0 514 }
docent 0:cd4a2add97a0 515
docent 0:cd4a2add97a0 516 uint8_t TroykaOLED::getImageWidth(const uint8_t* image, uint8_t mem) {
docent 0:cd4a2add97a0 517 // возвращаем ширину изображения
docent 0:cd4a2add97a0 518 return (mem == IMG_RAM) ? image[0] : pgm_read_byte(&image[0]);
docent 0:cd4a2add97a0 519 }
docent 0:cd4a2add97a0 520
docent 0:cd4a2add97a0 521 uint8_t TroykaOLED::getImageHeight(const uint8_t* image, uint8_t mem) {
docent 0:cd4a2add97a0 522 // возвращаем высоту изображения
docent 0:cd4a2add97a0 523 return (mem == IMG_RAM) ? image[1] : pgm_read_byte(&image[1]);
docent 0:cd4a2add97a0 524 }
docent 0:cd4a2add97a0 525
docent 0:cd4a2add97a0 526 void TroykaOLED::_print(char* data, int x, int y) {
docent 0:cd4a2add97a0 527 // если шрифт не выбран или его высота не кратна 8 пикселям, то выходим из функции
docent 0:cd4a2add97a0 528 if (_font.setFont == false || _font.height % 8 > 0) {
docent 0:cd4a2add97a0 529 return;
docent 0:cd4a2add97a0 530 }
docent 0:cd4a2add97a0 531 // определяем количество колонок которое занимают выводимые символы
docent 0:cd4a2add97a0 532 uint16_t len = strlen(data) * _font.width;
docent 0:cd4a2add97a0 533 if (len > _width) {
docent 0:cd4a2add97a0 534 len = _width / _font.width * _font.width;
docent 0:cd4a2add97a0 535 }
docent 0:cd4a2add97a0 536 // объявляем переменную для хранения номера байта в массиве шрифта
docent 0:cd4a2add97a0 537 uint16_t num;
docent 0:cd4a2add97a0 538 // объявляем переменные для хранения координат точек
docent 0:cd4a2add97a0 539 int x1, y1;
docent 0:cd4a2add97a0 540 // объявляем переменную для хранения цвета точек
docent 0:cd4a2add97a0 541 bool c;
docent 0:cd4a2add97a0 542 // колонка с которой требуется начать вывод текста ...
docent 0:cd4a2add97a0 543 switch (x) {
docent 0:cd4a2add97a0 544 // определяем начальную колонку для выравнивания по левому краю.
docent 0:cd4a2add97a0 545 case OLED_LEFT:
docent 0:cd4a2add97a0 546 _numX = 0;
docent 0:cd4a2add97a0 547 break;
docent 0:cd4a2add97a0 548 // определяем начальную колонку для выравнивания по центру
docent 0:cd4a2add97a0 549 case OLED_CENTER:
docent 0:cd4a2add97a0 550 _numX = (_width - len) / 2;
docent 0:cd4a2add97a0 551 break;
docent 0:cd4a2add97a0 552 // определяем начальную колонку для выравнивания по правому краю
docent 0:cd4a2add97a0 553 case OLED_RIGHT:
docent 0:cd4a2add97a0 554 _numX = _width - len;
docent 0:cd4a2add97a0 555 break;
docent 0:cd4a2add97a0 556 // начальной колонкой останется та, на которой был закончен вывод предыдущего текста или изображения
docent 0:cd4a2add97a0 557 case OLED_THIS:
docent 0:cd4a2add97a0 558 _numX = _numX;
docent 0:cd4a2add97a0 559 break;
docent 0:cd4a2add97a0 560 // начальная колонка определена пользователем
docent 0:cd4a2add97a0 561 default:
docent 0:cd4a2add97a0 562 _numX = x;
docent 0:cd4a2add97a0 563 break;
docent 0:cd4a2add97a0 564 }
docent 0:cd4a2add97a0 565 // строка с которой требуется начать вывод текста ...
docent 0:cd4a2add97a0 566 switch (y) {
docent 0:cd4a2add97a0 567 // определяем начальную строку для выравнивания по верхнему краю
docent 0:cd4a2add97a0 568 case OLED_TOP:
docent 0:cd4a2add97a0 569 _numY = _font.height - 1;
docent 0:cd4a2add97a0 570 break;
docent 0:cd4a2add97a0 571 // определяем начальную строку для выравнивания по центру
docent 0:cd4a2add97a0 572 case OLED_CENTER:
docent 0:cd4a2add97a0 573 _numY = (_height - _font.height) / 2 + _font.height;
docent 0:cd4a2add97a0 574 break;
docent 0:cd4a2add97a0 575 // определяем начальную строку для выравнивания по нижнему краю
docent 0:cd4a2add97a0 576 case OLED_BOTTOM:
docent 0:cd4a2add97a0 577 _numY = _height;
docent 0:cd4a2add97a0 578 break;
docent 0:cd4a2add97a0 579 // начальной строкой останется та, на которой выведен предыдущий текст или изображение
docent 0:cd4a2add97a0 580 case OLED_THIS:
docent 0:cd4a2add97a0 581 _numY = _numY;
docent 0:cd4a2add97a0 582 break;
docent 0:cd4a2add97a0 583 // начальная строка определена пользователем
docent 0:cd4a2add97a0 584 default:
docent 0:cd4a2add97a0 585 _numY = y;
docent 0:cd4a2add97a0 586 break;
docent 0:cd4a2add97a0 587 }
docent 0:cd4a2add97a0 588 // пересчитываем количество колонок которое занимают выводимые символы, с учётом начальной позиции
docent 0:cd4a2add97a0 589 if (_numX + len > _width) {
docent 0:cd4a2add97a0 590 len = (_width - _numX) / _font.width * _font.width;
docent 0:cd4a2add97a0 591 }
docent 0:cd4a2add97a0 592 // проходим по страницам символов...
docent 0:cd4a2add97a0 593 for (int8_t p = 0; p < _font.height / 8; p++) {
docent 0:cd4a2add97a0 594 // проходим по выводимым символам...
docent 0:cd4a2add97a0 595 for (uint8_t n = 0; n < (len / _font.width); n++) {
docent 0:cd4a2add97a0 596 // присваиваем переменной num код выводимого символа
docent 0:cd4a2add97a0 597 num = uint8_t(data[n]);
docent 0:cd4a2add97a0 598 // если в массиве символов, до кода текущего символа, имеется пустой интервал
docent 0:cd4a2add97a0 599 // уменьшаем код текущего символа на количество символов в пустом интервале
docent 0:cd4a2add97a0 600 if(_font.startSpace[0] < num) {
docent 0:cd4a2add97a0 601 num -= _font.sumSpace[0];
docent 0:cd4a2add97a0 602 }
docent 0:cd4a2add97a0 603 // если в массиве символов, до кода текущего символа, имеется пустой интервал
docent 0:cd4a2add97a0 604 // уменьшаем код текущего символа на количество символов в пустом интервале
docent 0:cd4a2add97a0 605 if (_font.startSpace[1] < num) {
docent 0:cd4a2add97a0 606 num -= _font.sumSpace[1];
docent 0:cd4a2add97a0 607 }
docent 0:cd4a2add97a0 608 // если в массиве символов, до кода текущего символа, имеется пустой интервал
docent 0:cd4a2add97a0 609 // то уменьшаем код текущего символа на количество символов в пустом интервале
docent 0:cd4a2add97a0 610 if (_font.startSpace[2] < num) {
docent 0:cd4a2add97a0 611 num -= _font.sumSpace[2];
docent 0:cd4a2add97a0 612 }
docent 0:cd4a2add97a0 613 // вычитаем код первого символа (с которого начинается массив шрифта)
docent 0:cd4a2add97a0 614 num -= _font.firstSymbol;
docent 0:cd4a2add97a0 615 // умножаем полученное значение на ширину символа (количество колонок)
docent 0:cd4a2add97a0 616 num *= _font.width;
docent 0:cd4a2add97a0 617 // умножаем полученное значение на высоту символа (количество страниц)
docent 0:cd4a2add97a0 618 num *= _font.height / 8;
docent 0:cd4a2add97a0 619 // добавляем количество колонок данного символа, которые уже были выведены на предыдущих страницах
docent 0:cd4a2add97a0 620 num += p * _font.width;
docent 0:cd4a2add97a0 621 // добавляем количество байт в начале массива шрифта, которые не являются байтами символов
docent 0:cd4a2add97a0 622 num += 0x04;
docent 0:cd4a2add97a0 623 // проходим по байтам очередного символа
docent 0:cd4a2add97a0 624 for (uint8_t k = 0; k < _font.width; k++) {
docent 0:cd4a2add97a0 625 // проходим по байтам очередного символа
docent 0:cd4a2add97a0 626 for (uint8_t b = 0; b < 8; b++) {
docent 0:cd4a2add97a0 627 // начальная колонка всего текста + (количество выведенных символов * ширина символов) + номер байта текущего символа
docent 0:cd4a2add97a0 628 x1 = _numX + n * _font.width + k;
docent 0:cd4a2add97a0 629 // нижняя строка текста - высота симолов + количество уже выведенных страниц + номер бита байта текущего символа + 1
docent 0:cd4a2add97a0 630 y1 = _numY + p * 8 + b;
docent 0:cd4a2add97a0 631 // цвет точки символа: 1-белый, 0-чёрный
docent 0:cd4a2add97a0 632 c = bitRead( pgm_read_byte(&_font.fontData[num + k]), b);
docent 0:cd4a2add97a0 633 // если цвет текста требуется инвертировать
docent 0:cd4a2add97a0 634 if (_font.invert) {
docent 0:cd4a2add97a0 635 // если установлен фон текста или точка стоит на букве (а не на фоне)
docent 0:cd4a2add97a0 636 if (_font.background || c) {
docent 0:cd4a2add97a0 637 // выводим инвертированную точку
docent 0:cd4a2add97a0 638 _drawPixel(x1, y1, !c);
docent 0:cd4a2add97a0 639 }
docent 0:cd4a2add97a0 640 } else {
docent 0:cd4a2add97a0 641 // если цвет текста не требуется инвертировать
docent 0:cd4a2add97a0 642 // если установлен фон текста или точка стоит на букве (а не на фоне)
docent 0:cd4a2add97a0 643 if (_font.background || c) {
docent 0:cd4a2add97a0 644 // выводим не инвертированную точку
docent 0:cd4a2add97a0 645 _drawPixel(x1, y1, c);
docent 0:cd4a2add97a0 646 }
docent 0:cd4a2add97a0 647 }
docent 0:cd4a2add97a0 648 }
docent 0:cd4a2add97a0 649 }
docent 0:cd4a2add97a0 650 }
docent 0:cd4a2add97a0 651 }
docent 0:cd4a2add97a0 652 if(_stateAutoUpdate) {
docent 0:cd4a2add97a0 653 _sendBuffer();
docent 0:cd4a2add97a0 654 }
docent 0:cd4a2add97a0 655 // сохраняем координату окончания текста.
docent 0:cd4a2add97a0 656 _numX += len;
docent 0:cd4a2add97a0 657 }
docent 0:cd4a2add97a0 658
docent 0:cd4a2add97a0 659 // параметр: одна цифра от 0 до 15
docent 0:cd4a2add97a0 660 // преобразуем цифры 0-9 в символ с кодом 48-57, а цифры 10-15 в символ с кодом 65-71
docent 0:cd4a2add97a0 661 char TroykaOLED::_itoa(uint8_t num) {
docent 0:cd4a2add97a0 662 return char(num + (num < 10 ? 48 : 55));
docent 0:cd4a2add97a0 663 }
docent 0:cd4a2add97a0 664
docent 0:cd4a2add97a0 665 char* TroykaOLED::_codingCP866(char* StrIn) {
docent 0:cd4a2add97a0 666 // определяем строку для вывода результата
docent 0:cd4a2add97a0 667 char* StrOut = StrIn;
docent 0:cd4a2add97a0 668 // переменненые для хранения номера сивола в строках StrIn и StrOut
docent 0:cd4a2add97a0 669 uint8_t numIn = 0, numOut = 0;
docent 0:cd4a2add97a0 670 // переменненые для хранения текущего кода символа в строках StrIn и StrOut
docent 0:cd4a2add97a0 671 uint8_t charThis = StrIn[0], charNext = StrIn[1];
docent 0:cd4a2add97a0 672 switch (_codingName) {
docent 0:cd4a2add97a0 673 // преобразуем текст из кодировки UTF-8:
docent 0:cd4a2add97a0 674 case TXT_UTF8:
docent 0:cd4a2add97a0 675 while (charThis > 0 && numIn < 0xFF ) {
docent 0:cd4a2add97a0 676 // если код текущего символа равен 208, а за ним следует символ с кодом 144...191
docent 0:cd4a2add97a0 677 // значит это буква «А»...«п» требующая преобразования к коду 128...175
docent 0:cd4a2add97a0 678 if (charThis == 0xD0 && charNext >= 0x90 && charNext <= 0xBF) {
docent 0:cd4a2add97a0 679 StrOut[numOut] = charNext - 0x10;
docent 0:cd4a2add97a0 680 numIn++;
docent 0:cd4a2add97a0 681 } else if (charThis == 0xD0 && charNext == 0x81) {
docent 0:cd4a2add97a0 682 // если код текущего символа равен 208, а за ним следует символ с кодом 129
docent 0:cd4a2add97a0 683 // значит это буква «Ё» требующая преобразования к коду 240
docent 0:cd4a2add97a0 684 StrOut[numOut] = 0xF0; numIn++;
docent 0:cd4a2add97a0 685 } else if (charThis == 0xD1 && charNext >= 0x80 && charNext <= 0x8F) {
docent 0:cd4a2add97a0 686 // если код текущего символа равен 209, а за ним следует символ с кодом 128...143
docent 0:cd4a2add97a0 687 // значит это буква «р»...«я» требующая преобразования к коду 224...239
docent 0:cd4a2add97a0 688 StrOut[numOut] = charNext + 0x60; numIn++;
docent 0:cd4a2add97a0 689 } else if (charThis == 0xD1 && charNext == 0x91) {
docent 0:cd4a2add97a0 690 // если код текущего символа равен 209, а за ним следует символ с кодом 145
docent 0:cd4a2add97a0 691 // значит это буква «ё» требующая преобразования к коду 241
docent 0:cd4a2add97a0 692 StrOut[numOut] = 0xF1;
docent 0:cd4a2add97a0 693 numIn++;
docent 0:cd4a2add97a0 694 } else {
docent 0:cd4a2add97a0 695 // иначе не меняем символ
docent 0:cd4a2add97a0 696 StrOut[numOut] = charThis;
docent 0:cd4a2add97a0 697 }
docent 0:cd4a2add97a0 698 // переходим к следующему символу
docent 0:cd4a2add97a0 699 numIn++;
docent 0:cd4a2add97a0 700 numOut++;
docent 0:cd4a2add97a0 701 charThis = StrIn[numIn];
docent 0:cd4a2add97a0 702 charNext = StrIn[numIn + 1];
docent 0:cd4a2add97a0 703 // добавляем символ конца строки и возвращаем строку StrOut
docent 0:cd4a2add97a0 704 }
docent 0:cd4a2add97a0 705 StrOut[numOut] = '\0';
docent 0:cd4a2add97a0 706 break;
docent 0:cd4a2add97a0 707 //преобразуем текст из кодировки WINDOWS-1251:
docent 0:cd4a2add97a0 708 case TXT_WIN1251:
docent 0:cd4a2add97a0 709 // если код текущего символа строки StrIn больше 0 и номер текушего символа строки StrIn меньше 255
docent 0:cd4a2add97a0 710 while (charThis > 0 && numIn < 0xFF) {
docent 0:cd4a2add97a0 711 // если код текущего символа равен 192...239
docent 0:cd4a2add97a0 712 // значит это буква «А»...«п» требующая преобразования к коду 128...175
docent 0:cd4a2add97a0 713 if (charThis >= 0xC0 && charThis <= 0xEF) {
docent 0:cd4a2add97a0 714 StrOut[numOut] = charThis - 0x40;
docent 0:cd4a2add97a0 715 } else if (charThis >= 0xF0 && charThis <= 0xFF) {
docent 0:cd4a2add97a0 716 // если код текущего символа равен 240...255
docent 0:cd4a2add97a0 717 // значит это буква «р»...«я» требующая преобразования к коду 224...239
docent 0:cd4a2add97a0 718 StrOut[numOut] = charThis - 0x10;
docent 0:cd4a2add97a0 719 } else if (charThis == 0xA8) {
docent 0:cd4a2add97a0 720 // если код текущего символа равен 168, значит это буква «Ё» требующая преобразования к коду 240
docent 0:cd4a2add97a0 721 StrOut[numOut] = 0xF0;
docent 0:cd4a2add97a0 722 }else if (charThis == 0xB8) {
docent 0:cd4a2add97a0 723 // если код текущего символа равен 184, значит это буква «ё» требующая преобразования к коду 241
docent 0:cd4a2add97a0 724 StrOut[numOut] = 0xF1;
docent 0:cd4a2add97a0 725 } else {
docent 0:cd4a2add97a0 726 // иначе не меняем символ
docent 0:cd4a2add97a0 727 StrOut[numOut] = charThis;
docent 0:cd4a2add97a0 728 }
docent 0:cd4a2add97a0 729 // переходим к следующему символу
docent 0:cd4a2add97a0 730 numIn++;
docent 0:cd4a2add97a0 731 numOut++;
docent 0:cd4a2add97a0 732 charThis = StrIn[numIn];
docent 0:cd4a2add97a0 733 // добавляем символ конца строки
docent 0:cd4a2add97a0 734 }
docent 0:cd4a2add97a0 735 StrOut[numOut] = '\0';
docent 0:cd4a2add97a0 736 break;
docent 0:cd4a2add97a0 737 }
docent 0:cd4a2add97a0 738 // возвращаем строку StrOut
docent 0:cd4a2add97a0 739 return StrOut;
docent 0:cd4a2add97a0 740 }
docent 0:cd4a2add97a0 741
docent 0:cd4a2add97a0 742 void TroykaOLED::_drawPixel(int x, int y, uint8_t color) {
docent 0:cd4a2add97a0 743 if(x < 0 || x > _width - 1 || y < 0 || y > _height - 1) {
docent 0:cd4a2add97a0 744 return;
docent 0:cd4a2add97a0 745 }
docent 0:cd4a2add97a0 746 // определяем номер страницы в которой должен находиться пиксель
docent 0:cd4a2add97a0 747 uint8_t p = y / 8;
docent 0:cd4a2add97a0 748 // определяем номер байта массива _bufferDisplay в котором требуется прорисовать пиксель
docent 0:cd4a2add97a0 749 uint16_t numByte = (p * 128 ) + x;
docent 0:cd4a2add97a0 750 // определяем номер бита в найденном байте, который соответсвует рисуемому пикселю
docent 0:cd4a2add97a0 751 uint8_t numBit = y % 8;
docent 0:cd4a2add97a0 752 switch (color) {
docent 0:cd4a2add97a0 753 case WHITE:
docent 0:cd4a2add97a0 754 _bufferDisplay[numByte] |= 1 << numBit;
docent 0:cd4a2add97a0 755 break;
docent 0:cd4a2add97a0 756 case BLACK:
docent 0:cd4a2add97a0 757 _bufferDisplay[numByte] &= ~(1 << numBit);
docent 0:cd4a2add97a0 758 break;
docent 0:cd4a2add97a0 759 case INVERSE:
docent 0:cd4a2add97a0 760 _bufferDisplay[numByte] ^= 1 << numBit;
docent 0:cd4a2add97a0 761 break;
docent 0:cd4a2add97a0 762 }
docent 0:cd4a2add97a0 763 }
docent 0:cd4a2add97a0 764
docent 0:cd4a2add97a0 765 void TroykaOLED::_drawLine(int x1, int y1, int x2, int y2, uint8_t color) {
docent 0:cd4a2add97a0 766 int x3 = x2 - x1;
docent 0:cd4a2add97a0 767 int y3 = y2 - y1;
docent 0:cd4a2add97a0 768 // рисуем линию по линейному уровнению (y-y1)/(y2-y1) = (x-x1)/(x2-x1)
docent 0:cd4a2add97a0 769 // определяем где больше расстояние (по оси x или y)
docent 0:cd4a2add97a0 770 // по той оси проходим в цикле, для поиска точек на другой оси
docent 0:cd4a2add97a0 771 if (abs(x3) > abs(y3)) {
docent 0:cd4a2add97a0 772 if (x1 < x2) {
docent 0:cd4a2add97a0 773 for (int x = x1; x <= x2; x++) {
docent 0:cd4a2add97a0 774 _drawPixel(x,((x - x1) * y3 / x3 + y1), color);
docent 0:cd4a2add97a0 775 }
docent 0:cd4a2add97a0 776 } else {
docent 0:cd4a2add97a0 777 for (int x = x1; x >= x2; x--) {
docent 0:cd4a2add97a0 778 _drawPixel(x,((x - x1) * y3 / x3 + y1), color);
docent 0:cd4a2add97a0 779 }
docent 0:cd4a2add97a0 780 }
docent 0:cd4a2add97a0 781 } else {
docent 0:cd4a2add97a0 782 if (y1 < y2) {
docent 0:cd4a2add97a0 783 for (int y = y1; y <= y2; y++) {
docent 0:cd4a2add97a0 784 _drawPixel(((y - y1) * x3 / y3 + x1), y, color);
docent 0:cd4a2add97a0 785 }
docent 0:cd4a2add97a0 786 } else {
docent 0:cd4a2add97a0 787 for (int y = y1; y >= y2; y--) {
docent 0:cd4a2add97a0 788 _drawPixel(((y - y1) * x3 / y3 + x1), y, color);
docent 0:cd4a2add97a0 789 }
docent 0:cd4a2add97a0 790 }
docent 0:cd4a2add97a0 791 }
docent 0:cd4a2add97a0 792 }
docent 0:cd4a2add97a0 793
docent 0:cd4a2add97a0 794 // отправка байта команды
docent 0:cd4a2add97a0 795 /*
docent 0:cd4a2add97a0 796 void TroykaOLED::_sendCommand(uint8_t command){
docent 0:cd4a2add97a0 797 _wire->beginTransmission(_i2cAddress);
docent 0:cd4a2add97a0 798 _wire->write(0x80);
docent 0:cd4a2add97a0 799 _wire->write(command);
docent 0:cd4a2add97a0 800 _wire->endTransmission();
docent 0:cd4a2add97a0 801 }
docent 0:cd4a2add97a0 802 */
docent 0:cd4a2add97a0 803 void TroykaOLED::_sendCommand(uint8_t command)
docent 0:cd4a2add97a0 804 {
docent 0:cd4a2add97a0 805 char data_write[2];
docent 0:cd4a2add97a0 806 data_write[0]=0x80;
docent 0:cd4a2add97a0 807 data_write[1]=command;
docent 0:cd4a2add97a0 808 _wire->write(_i2cAddress,data_write, 2,0);
docent 0:cd4a2add97a0 809 }
docent 0:cd4a2add97a0 810 // отправка буфера (массива _bufferDisplay) в дисплей
docent 0:cd4a2add97a0 811 void TroykaOLED::_sendBuffer() {
docent 0:cd4a2add97a0 812 _sendCommand(SSD1306_ADDR_PAGE);
docent 0:cd4a2add97a0 813 _sendCommand(0);
docent 0:cd4a2add97a0 814 _sendCommand(_height / 8 - 1);
docent 0:cd4a2add97a0 815 _sendCommand(SSD1306_ADDR_COLUMN);
docent 0:cd4a2add97a0 816 _sendCommand(0);
docent 0:cd4a2add97a0 817 _sendCommand(_width - 1);
docent 0:cd4a2add97a0 818 char data_write[17]; //my
docent 0:cd4a2add97a0 819 data_write[0]=0x40;
docent 0:cd4a2add97a0 820 for (int i = 0; i < _width * _height / 8; i++){
docent 0:cd4a2add97a0 821 for (uint8_t x = 0; x < 16; x++) {
docent 0:cd4a2add97a0 822 data_write[x+1]=_bufferDisplay[i++];
docent 0:cd4a2add97a0 823 }
docent 0:cd4a2add97a0 824 /*
docent 0:cd4a2add97a0 825 _wire->beginTransmission(_i2cAddress);
docent 0:cd4a2add97a0 826 _wire->write(0x40);
docent 0:cd4a2add97a0 827 for (uint8_t x = 0; x < 16; x++) {
docent 0:cd4a2add97a0 828 _wire->write(_bufferDisplay[i++]);
docent 0:cd4a2add97a0 829 }
docent 0:cd4a2add97a0 830 i--;
docent 0:cd4a2add97a0 831 _wire->endTransmission();
docent 0:cd4a2add97a0 832 */
docent 0:cd4a2add97a0 833 i--;
docent 0:cd4a2add97a0 834 _wire->write(_i2cAddress,data_write, 17,0);
docent 0:cd4a2add97a0 835 }
docent 0:cd4a2add97a0 836 }