Кириллица на дисплее или что я делаю не так?
- Войдите на сайт для отправки комментариев
Кириллица на дисплее или что я делаю не так?
Честно говоря, мне самому кириллица как-то без особой надобности.
Но, почему-то, на форуме вокруг нее творятся страшные вещи.
Например, по ссылкам:
http://lesson.iarduino.ru/page/urok-8-russkiy-yazyk-na-oled-displee-128x64/
http://arduino-project.net/russkie-ukrainskie-shrifty-oled-i2c/
предлагают использовать ее следующим образом.
Допустим, все библиотеки, шрифты и т.п. скачаны и установлены, переходим к программированию.
Скажем, нужно вывести на экран фразу "Моя Arduino сгорела.". Оказывается, что просто так это сделать нельзя. Следует:
- установить русский фонт,
- вывести "Моя " с нужного места экрана,
- теперь переключить фонт на английский,
- посчитать, сколько символов занимает первая надпись,
- вывести строку с учетом указанного смещения,
- вывести строку "Arduino ",
- снова переключить фонт - обратно на русский,
- снова посчитать смещение,
- вывести "сгорела."
Мало того, при наборе строк "Моя " и "сгорела." нужно переключить клавиатуру в латинскую раскладку, но набирать, глядя на русские надписи на клавиатуре.
Что при этом будет на экране - сложно представить.
А чтобы потом самому не запутаться в коде, рекомендуется дублировать надписи в комментариях - теперь уже в нормальной кодировке.
То есть это должно выглядеть примерно так:
myOLED.setFont(RusFont);
myOLED.print("Vjz ", 0, 3); // Выводим надпись "Моя "
myOLED.setFont(LatFont);
myOLED.print("Arduino ", 4, 3); // Выводим надпись "Arduino "
myOLED.setFont(RusFont);
myOLED.print("cujhtkf/", 12, 3); // Выводим надпись "сгорела."
Я лично делаю так:
LD.printString6("0123456789!\"#$%&'()*+", 0, 0, 21);
LD.printString6(",-./:;<=>?@[\\]^_`{|}~", 0, 1, 21);
LD.printString6("ABCDEFGHIJKLMNOPQRSTU", 0, 2, 21);
LD.printString6("VWXYZabcdefghijklmnop",0, 3, 21);
LD.printString6("qrstuvwxyzАБВГДЕЁЖЗИЙ", 0, 4, 21);
LD.printString6("КЛМНОПРСТУФХЦЧШЩЪЫЬЭЮ", 0, 5, 21);
LD.printString6("Яабвгдеёжзийклмнопрст", 0, 6, 21);
LD.printString6("уфхцчшщъыьэюяЇїЎў§°±µ", 0, 7, 21);
и получаю на экране:

При этом моя IDE, как и положено, работает в utf-8.
Что я делаю неправильно?
разве неясно что ты делаешь неправильно? Ты используешь волшебную библиотеку, в которой есть то, что не смогли сделать другие программисты.
Выход только один - срочно её удалить. А также все ее копии из архивов. Тогда ты будешь как все - корячиться с написанием кода и комментированием для потомков. Ведь только умственный процесс - это эволюция, выживают сильнейшие, а не ленивые.
Ну, библиотекой это пока называть рано. Это - пока мои первые попытки что-то написать для arduino.
Удалить, конечно, можно.
Только ведь я снова смогу это написать - вот проблема!
Придётся тебя ликвидировать. Человечество важнее.
А по делу - мне строки LD.printString6 незнакомы, это что-то новое, и что значат три цифры в конце?
"6" в конце названия функции означает фонт шириной 6 пикселей.
Послежние 3 цифры - наследие библиотеки by Oscar Liang (OzOLED), которая послужила одним из прототипов: первые два числа означают координаты символа на экране, а последняя - количество выводимых символов.
В общем, все это нуждается в упорядочивании, чем я постепенно и занимаюсь.
Так как никакой конструктивной критики моей идеи по использованию кириллицы в Ардуино не последовало (за исключением предложения убицца ап стену), выкладываю предварительный вариант библиотеки.
Библиотека разрабатывалась, исходя из минимизации занимаемого ею места как в постоянной, так и в оперативной памяти.
Библиотека работает с кодировкой utf-8, которая принята в IDE Arduino.
Библиотека позволяет отображать все символы ASCII кроме управляющих, все символы русского алфавита, включая Ёё, некоторые символы кириллицы украинского и беларусского алфавита [ЃѓЄєІіЇїЎўҐґ], и четыре прочих символа, которые мне понравились [§°±µ].
Никакие другие символы библиотека отображать не может. Зато при попытке отображения произвольной последовательности utf-8 символов последствия могут быть непредсказуемы.
Библиотека позволяет отображать символы двух размеров 6х8 и 12х16 пикселей, но в целях экономии большой фонт получается путем "растягивания" малого, а потому довольно угловат.
Для меня пока непонятен принци переключения между фонтами. Я вижу здесь 2 варианта:
LD.setFont(Font_12x16); LD.printString("10"); LD.setFont(Font_6x8); LD.printString("3"); LD.setFont(Font_12x16); LD.printString(" = 1000");и
LD.printStringBig("10"); LD.printStringSmall("3"); LD.printStringBig(" = 1000");Хотелось бы услышать мнение, какой вариант удобнее.
Библиотека проверялась исключительно с 0.96" OLED дисплеем SSD1306 128x64, может ли она работать с чем-либо другим, не знаю.
Работа над библиотекой пока не закончена, поэтому просьба не распространять эту библиотеку.
Пример работы (файл Test_ASOLED_1.ino):
#include <Wire.h> #include "ASOLED.h" #include "mice.c" int State = 0; long NewTime, OldTime; void setup() { OldTime = millis(); LD.init(); //initialze OLED display LD.clearDisplay(); } void loop() { int n0 = 123; int n1 = -321; float d0 = 456.789; float d1 = -0.00789; NewTime = millis(); if ((NewTime - OldTime) > 5000) { OldTime = NewTime; State = ++State % 5; LD.clearDisplay(); } switch (State) { case 0: LD.printString6("0123456789!\"#$%&'()*+", 0, 0); LD.printString6(",-./:;<=>?@[\\]^_`{|}~", 0, 1); LD.printString6("ABCDEFGHIJKLMNOPQRSTU", 0, 2); LD.printString6("VWXYZabcdefghijklmnop",0, 3); LD.printString6("qrstuvwxyzАБВГДЕЁЖЗИЙ", 0, 4); LD.printString6("КЛМНОПРСТУФХЦЧШЩЪЫЬЭЮ", 0, 5); LD.printString6("Яабвгдеёжзийклмнопрст", 0, 6); LD.printString6("уфхцчшщъыьэюяЇїЎў§°±µ", 0, 7); break; case 1: LD.printString12("012345%&'+", 0, 0); LD.printString12("ABCDEFGHIJ", 0, 2); LD.printString12("vwxyzАБВЕЁ", 0, 4); LD.printString12("юяЇїЎў§°±µ", 0, 6); break; case 2: for (int i = 0; i < 128; i++){ int j = (int)(sin(i*0.09 + 0.2)*35) + 45; LD.VertBar(i, j, 0, 90); } break; case 3: LD.printNumber((long)n0, 0, 0); // 123 LD.printNumber((long)n1, 0, 2); // -321 LD.printNumber(d0, 6, 60, 2); // 456.789 LD.printNumber(-d0, 6, 48, 0); // -456.789 LD.printNumber(d1, 8, 0, 6); // 0.00789 LD.printNumber((long)10, 28, 4); // 10 LD.printString6("3"); //, 0, 4); // ^3 LD.printString12("="); //, 0, 4); // = LD.printNumber((long)1000); //, 0, 4); // 1000 break; case 4 : LD.drawBitmap(mice, 0, 0, 128, 8); break; } }Заголовочный файл библиотеки (ASOLED.h):
/* ASOLED.h - 0.96' I2C 128x64 OLED Driver Library ver. 0.1a 2015 Copyright (c) Sergey Andrianov Please, do not distribute this library. It is not ready yet. Work is not complete. It is a preliminary variant exceptionally for testing. */ #ifndef ASOLED_data_H #define ASOLED_data_H #include <Arduino.h> #define ASOLED_Max_X 128 //128 Pixels #define ASOLED_Max_Y 64 //64 Pixels #define OLED_ADDRESS 0x3C // 0x78 #define I2C_400KHZ 1 // 0 to use default 100Khz, 1 for 400Khz #define Font_6x8 1 #define Font_12x16 2 class ASOLED { public: void init(); void setSize(const char font); // void printString(const char *String, byte X=255, byte Y=255, byte numChar=255); void printString6(const char *String, byte X=255, byte Y=255); void printString12(const char *String, byte X=255, byte Y=255); // font 12x16 byte printNumber(long n, byte X=255, byte Y=255); byte printNumber(float float_num, byte prec=6, byte Y=255, byte numChar=255); void drawBitmap(const byte *bitmaparray, byte X, byte Y, byte width, byte height); // X - in 1 pixel, Y - in 8 pixels void VertBar(int Num, int Val, int MinVal, int MaxVal); void clearDisplay(); void setNormalDisplay(); void setInverseDisplay(); void setBrightness(byte Brightness); private: void sendCommand(byte command); void sendData(byte Data); void printChar(char c); void setCursorXY(byte Column, byte Row); // X * 1 pixels, Y * 8 pixels void setPowerOff(); void setPowerOn(); void setPageMode(); void setHorizontalMode(); byte addressingMode; char CurrFont; // font size char NumberString[16]; // 4 print numbers byte LenString = 0; // current length of NumberString byte CurrX = 0; // current position byte CurrY = 0; }; extern ASOLED LD; // ASOLED object #endifКод библиотеки (ASOLED.cpp):
#include "ASOLED.h" #include <Wire.h> #include <avr/pgmspace.h> #include "a_Small_Rus.c" // registers #define ASA_OLED_COMMAND_MODE 0x80 #define ASA_OLED_DATA_MODE 0x40 //========================================================== unsigned char ASA_utf8_preliminary_byte = 0; unsigned char RecodeUTF_ASA(unsigned char c) { switch (c) { case (unsigned char)0xD0: ASA_utf8_preliminary_byte = c; // wait second byte return 255; case (unsigned char)0xD1: ASA_utf8_preliminary_byte = c; // wait second byte return 255; case (unsigned char)0xD2: ASA_utf8_preliminary_byte = c; // wait second byte return 255; case (unsigned char)0xC2: ASA_utf8_preliminary_byte = c; // wait second byte return 255; default: if(ASA_utf8_preliminary_byte == 0) // first half of ASCII table or nonsupported symbol { if((c >= ' ') && (c <= '~')) { return c; }else{ return '*'; } } else if(ASA_utf8_preliminary_byte == 0xD0) // { ASA_utf8_preliminary_byte = 0; if((c >= 144) && (c <= 191)) { return c - 17; } else if (c == 129) { // РЃ return 191; } else if (c == 131) { // Рѓ return 193; } else if (c == 132) { // Р„ return 195; } else if (c == 134) { // Р† return 197; } else if (c == 135) { // Р‡ return 199; } else if (c == 142) { // РЋ return 201; } else { return '*'; } } else if(ASA_utf8_preliminary_byte == 0xD1) // { ASA_utf8_preliminary_byte = 0; if((c >= 128) && (c <= 143)){ return c + 47; } else if (c == 145) { // С‘ return 192; } else if (c == 147) { // С“ return 194; } else if (c == 148) { // С” return 196; } else if (c == 150) { // С– return 198; } else if (c == 151) { // С— return 200; } else if (c == 158) { // Сћ return 202; } else { return '*'; } } else if(ASA_utf8_preliminary_byte == 0xD2) // { ASA_utf8_preliminary_byte = 0; if (c == 144) { // Тђ return 203; } else if (c == 145) { // Т‘ return 204; } else { return '*'; } } else if(ASA_utf8_preliminary_byte == 0xC2) // { ASA_utf8_preliminary_byte = 0; if (c == 167) { // В§ return 205; } else if (c == 176) { // В° return 206; } else if (c == 177) { // В± return 207; } else if (c == 181) { // Вµ return 208; } else { return '*'; } } else { return '*'; } } } // ====================== LOW LEVEL ========================= void ASOLED::sendCommand(byte command){ Wire.beginTransmission(OLED_ADDRESS); // begin transmitting Wire.write(ASA_OLED_COMMAND_MODE);//data mode Wire.write(command); Wire.endTransmission(); // stop transmitting } void ASOLED::sendData(byte data){ Wire.beginTransmission(OLED_ADDRESS); // begin transmitting Wire.write(ASA_OLED_DATA_MODE);//data mode Wire.write(data); Wire.endTransmission(); // stop transmitting } void ASOLED::printChar(char C){ // write to temp string for numbers NumberString[LenString++] = C; NumberString[LenString] = 0; } void ASOLED::printString6(const char *String, byte X, byte Y){ setCursorXY(X, Y); while(*String){ unsigned char c = RecodeUTF_ASA(*String++); if (c != 255) { // printChar6(c); sendData(0); for(byte i=0; i<5; i++) sendData(pgm_read_byte(&SmallFont[(c-32)*(int)5 + i + 4])); CurrX += 6; } } } unsigned int EnlardeByte2Word(char b) { unsigned int d = 0; for (byte i = 0; i < 8; i++) { unsigned int e = (((unsigned int)b) & (1 << i)) << i; d = d | e | (e << 1); } return d; } void ASOLED::printString12(const char *String, byte X, byte Y){ setCursorXY(X, Y); const char *String0 = String; unsigned int m = 0; byte tmpX = CurrX; while(*String){ // print upper half of the string unsigned char c = RecodeUTF_ASA(*String++); if (c != 255) { if(tmpX < (ASOLED_Max_X - 2)) { sendData(0); sendData(0); tmpX += 2; } for(byte i=0; i<5; i++) { if(tmpX < (ASOLED_Max_X - 2)) { m = EnlardeByte2Word(pgm_read_byte(&SmallFont[(c-32)*(int)5 + i + 4])); sendData(lowByte(m)); sendData(lowByte(m)); tmpX += 2; } } } } setCursorXY(CurrX, CurrY+1); while(*String0){ // print lower half of the string unsigned char c = RecodeUTF_ASA(*String0++); if (c != 255) { if(CurrX < (ASOLED_Max_X - 2)) { sendData(0); sendData(0); CurrX += 2; } for(byte i=0; i<5; i++) { if(CurrX < (ASOLED_Max_X - 2)) { m = EnlardeByte2Word(pgm_read_byte(&SmallFont[(c-32)*(int)5 + i + 4])); sendData(highByte(m)); sendData(highByte(m)); CurrX += 2; } } } } setCursorXY(CurrX, CurrY-1); } byte ASOLED::printNumber(long long_num, byte X, byte Y){ LenString = 0; setCursorXY(X, Y); byte char_buffer[10] = ""; byte i = 0; byte f = 0; // number of characters if (long_num < 0) { f++; printChar('-'); long_num = -long_num; } else if (long_num == 0) { f++; printChar('0'); printString12(&NumberString[0]); //, X, Y); return f; } while (long_num > 0) { char_buffer[i++] = long_num % 10; long_num /= 10; } f += i; for(; i > 0; i--) printChar('0'+ char_buffer[i - 1]); printString12(&NumberString[0]); //, X, Y); return f; } byte ASOLED::printNumber(float float_num, byte prec, byte X, byte Y){ LenString = 0; setCursorXY(X, Y); // prec - 6 maximum byte num_int = 0; byte num_frac = 0; byte num_extra = 0; long d = float_num; // get the integer part float f = float_num - d; // get the fractional part if (d == 0 && f < 0.0){ printChar('-'); num_extra++; printChar('0'); num_extra++; f *= -1; printString12(&NumberString[0]); //, CurrX, CurrY); LenString = 0; } else if (d < 0 && f < 0.0){ num_int = printNumber(d); //, CurrX, CurrY); // count how many digits in integer part LenString = 0; f *= -1; } else{ num_int = printNumber(d); //, CurrX, CurrY); // count how many digits in integer part LenString = 0; } // only when fractional part > 0, we show decimal point if (f > 0.0){ printChar('.'); num_extra++; printString12(&NumberString[0]); //, X, Y); LenString = 0; if (num_int + prec > 8) prec = 8 - num_int; for (byte j=0; j<prec; j++){ f *= 10.0; byte dd = f; printChar('0' + dd); f -= dd; } printString12(&NumberString[0]); //, X, Y); num_frac = prec; } return num_int + num_frac + num_extra; } void ASOLED::drawBitmap(const byte *bitmaparray, byte X, byte Y, byte width, byte height){ // max width = 128 // max height = 8 for (int j = 0; j < height; j++) { setCursorXY(X, Y + lowByte(j)); for (byte i = 0; i < width; i++) sendData(pgm_read_byte(&bitmaparray[i + 4 + j*width])); } } void ASOLED::VertBar(int Num, int Val, int MinVal, int MaxVal) { if (Val < MinVal) Val = MinVal; // consider that Val already scaled if (Val > MaxVal) Val = MaxVal; Val -= MinVal; for (int i = 0; i < 8; i++) // go from high levels to low ones { setCursorXY(Num, i); int b; // will calc this value for each columns (bars) int UpB = (MaxVal - MinVal)*(8-i)/8; if (Val <= UpB) // top boundary { int DownB = (MaxVal - MinVal)*(7-i)/8; if (Val >= DownB) // bottom boundary { // Val are in this interval int j = (Val - DownB)*8/(UpB - DownB); int k = 0xFF00; b = (k >> j) & 0xFF; } else { b = 0; } } else { b = 0xFF; } sendData(b); } setCursorXY(0, 0); } // =================== High Level =========================== ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // commands #define ASA_OLED_CMD_DISPLAY_OFF 0xAE #define ASA_OLED_CMD_DISPLAY_ON 0xAF #define ASA_OLED_CMD_NORMAL_DISPLAY 0xA6 #define ASA_OLED_CMD_INVERSE_DISPLAY 0xA7 #define ASA_OLED_CMD_SET_BRIGHTNESS 0x81 #define ASA_OLED_RIGHT_SCROLL 0x26 #define ASA_OLED_LEFT_SCROLL 0x27 #define ASA_OLED_SET_VERTICAL_SCROLL_AREA 0xA3 #define ASA_OLED_VERTICAL_RIGHT_SCROLL 0x29 #define ASA_OLED_VERTICAL_LEFT_SCROLL 0x2A #define ASA_OLED_CMD_ACTIVATE_SCROLL 0x2F #define ASA_OLED_CMD_DEACTIVATE_SCROLL 0x2E #define HORIZONTAL_ADDRESSING 0x00 #define PAGE_ADDRESSING 0x02 #define Scroll_Left 0x00 #define Scroll_Right 0x01 #define Scroll_Up 0x02 #define Scroll_Down 0x03 #define Scroll_2Frames 0x07 #define Scroll_3Frames 0x04 #define Scroll_4Frames 0x05 #define Scroll_5Frames 0x00 #define Scroll_25Frames 0x06 #define Scroll_64Frames 0x01 #define Scroll_128Frames 0x02 #define Scroll_256Frames 0x03 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SSD1306 Commandset // ------------------ // Fundamental Commands #define ASA_DISPLAY_ALL_ON_RESUME 0xA4 // Addressing Setting Commands #define ASA_MEMORY_ADDR_MODE 0x20 // Hardware Configuration Commands #define ASA_SET_START_LINE 0x40 #define ASA_SET_SEGMENT_REMAP 0xA0 #define ASA_SET_MULTIPLEX_RATIO 0xA8 #define ASA_COM_SCAN_DIR_DEC 0xC8 #define ASA_SET_DISPLAY_OFFSET 0xD3 #define ASA_SET_COM_PINS 0xDA #define ASA_CHARGE_PUMP 0x8D // Timing & Driving Scheme Setting Commands #define ASA_SET_DISPLAY_CLOCK_DIV_RATIO 0xD5 #define ASA_SET_PRECHARGE_PERIOD 0xD9 #define ASA_SET_VCOM_DESELECT 0xDB void ASOLED::init(){ Wire.begin(); // upgrade to 400KHz! (only use when your other i2c device support this speed) if (I2C_400KHZ){ // save I2C bitrate (default 100Khz) byte twbrbackup = TWBR; TWBR = 12; } setPageMode(); // default addressing mode clearDisplay(); setCursorXY(0,0); // Additional command LD.setPowerOff(); LD.sendCommand(ASA_SET_DISPLAY_CLOCK_DIV_RATIO); LD.sendCommand(0x80); LD.sendCommand(ASA_SET_MULTIPLEX_RATIO); LD.sendCommand(0x3F); LD.sendCommand(ASA_SET_DISPLAY_OFFSET); LD.sendCommand(0x0); LD.sendCommand(ASA_SET_START_LINE | 0x0); LD.sendCommand(ASA_CHARGE_PUMP); LD.sendCommand(0x14); LD.sendCommand(ASA_MEMORY_ADDR_MODE); LD.sendCommand(0x00); LD.sendCommand(ASA_SET_SEGMENT_REMAP | 0x1); LD.sendCommand(ASA_COM_SCAN_DIR_DEC); LD.sendCommand(ASA_SET_COM_PINS); LD.sendCommand(0x12); LD.setBrightness(0xCF); LD.sendCommand(ASA_SET_PRECHARGE_PERIOD); LD.sendCommand(0xF1); LD.sendCommand(ASA_SET_VCOM_DESELECT); LD.sendCommand(0x40); LD.sendCommand(ASA_DISPLAY_ALL_ON_RESUME); LD.setNormalDisplay(); LD.setPowerOn(); } void ASOLED::setCursorXY(byte X, byte Y){ // Y - 1 unit = 1 page (8 pixel rows) // X - 1 unit = 1 pixel columns if (X < 128) if ((X != CurrX) || (Y != CurrY)){ sendCommand(0x00 + (X & 0x0F)); //set column lower address sendCommand(0x10 + ((X>>4)&0x0F)); //set column higher address sendCommand(0xB0 + Y); //set page address CurrX = X; CurrY = Y; } } void ASOLED::setSize(const char font) { CurrFont = font; } void ASOLED::clearDisplay() { for(byte page=0; page<8; page++) { setCursorXY(0, page); for(byte column=0; column<128; column++) //clear all columns sendData(0); } setCursorXY(0,0); } void ASOLED::setInverseDisplay(){ sendCommand(ASA_OLED_CMD_INVERSE_DISPLAY); } void ASOLED::setNormalDisplay(){ sendCommand(ASA_OLED_CMD_NORMAL_DISPLAY); } void ASOLED::setPowerOff(){ sendCommand(ASA_OLED_CMD_DISPLAY_OFF); } void ASOLED::setPowerOn(){ sendCommand(ASA_OLED_CMD_DISPLAY_ON); } void ASOLED::setBrightness(byte Brightness){ sendCommand(ASA_OLED_CMD_SET_BRIGHTNESS); sendCommand(Brightness); } void ASOLED::setPageMode(){ addressingMode = PAGE_ADDRESSING; sendCommand(0x20); //set addressing mode sendCommand(PAGE_ADDRESSING); //set page addressing mode } void ASOLED::setHorizontalMode(){ addressingMode = HORIZONTAL_ADDRESSING; sendCommand(0x20); //set addressing mode sendCommand(HORIZONTAL_ADDRESSING); //set page addressing mode } ASOLED LD; // Preinstantiate ObjectsШрифт (a_Small_Rus.c):
#if defined(__AVR__) #include <avr/pgmspace.h> #define fontdatatype const uint8_t #elif defined(__PIC32MX__) #define PROGMEM #define fontdatatype const unsigned char #elif defined(__arm__) #define PROGMEM #define fontdatatype const unsigned char #endif // New font 177 symbols 5x8 = 885+4 bytes fontdatatype SmallFont[] PROGMEM = { 0x05, 0x08, 0x20, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, // sp 0x00, 0x00, 0x2f, 0x00, 0x00, // ! 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x14, 0x7f, 0x14, 0x7f, 0x14, // # 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ 0x23, 0x13, 0x08, 0x64, 0x62, // % 0x36, 0x49, 0x55, 0x22, 0x50, // & 0x00, 0x05, 0x03, 0x00, 0x00, // ' 0x00, 0x1c, 0x22, 0x41, 0x00, // ( 0x00, 0x41, 0x22, 0x1c, 0x00, // ) 0x14, 0x08, 0x3E, 0x08, 0x14, // * 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x00, 0xA0, 0x60, 0x00, // , 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x60, 0x60, 0x00, 0x00, // . 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x21, 0x41, 0x45, 0x4B, 0x31, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x01, 0x71, 0x09, 0x05, 0x03, // 7 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x36, 0x36, 0x00, 0x00, // : 0x00, 0x56, 0x36, 0x00, 0x00, // ; 0x08, 0x14, 0x22, 0x41, 0x00, // < 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x32, 0x49, 0x59, 0x51, 0x3E, // @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x7F, 0x41, 0x41, 0x22, 0x1C, // D 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x46, 0x49, 0x49, 0x49, 0x31, // S 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x07, 0x08, 0x70, 0x08, 0x07, // Y 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x7F, 0x41, 0x41, 0x00, // [ 0x01, 0x06, 0x08, 0x30, 0x40, // Backslash 0x00, 0x41, 0x41, 0x7F, 0x00, // ] 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x40, 0x40, 0x40, 0x40, 0x40, // _ 0x00, 0x03, 0x05, 0x00, 0x00, // ` 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x7F, 0x48, 0x44, 0x44, 0x38, // b 0x38, 0x44, 0x44, 0x44, 0x20, // c 0x38, 0x44, 0x44, 0x48, 0x7F, // d 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x08, 0x7E, 0x09, 0x01, 0x02, // f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x40, 0x80, 0x84, 0x7D, 0x00, // j 0x7F, 0x10, 0x28, 0x44, 0x00, // k 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x7C, 0x04, 0x18, 0x04, 0x78, // m 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x38, 0x44, 0x44, 0x44, 0x38, // o 0xFC, 0x24, 0x24, 0x24, 0x18, // p 0x18, 0x24, 0x24, 0x18, 0xFC, // q 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x48, 0x54, 0x54, 0x54, 0x20, // s 0x04, 0x3F, 0x44, 0x40, 0x20, // t 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y 0x44, 0x64, 0x54, 0x4C, 0x44, // z 0x00, 0x10, 0x7C, 0x82, 0x00, // { 0x00, 0x00, 0xFF, 0x00, 0x00, // | 0x00, 0x82, 0x7C, 0x10, 0x00, // } 0x08, 0x04, 0x08, 0x10, 0x08, // 7E 126 ~ 0x7C, 0x12, 0x11, 0x12, 0x7C, // А 0x7F, 0x49, 0x49, 0x49, 0x31, // Б 0x7F, 0x45, 0x45, 0x45, 0x3A, // В 0x7F, 0x01, 0x01, 0x01, 0x03, // Г 0x60, 0x3F, 0x21, 0x3F, 0x60, // Д 0x7F, 0x49, 0x49, 0x49, 0x41, // Е 0x73, 0x0C, 0x7F, 0x0C, 0x73, // Ж 0x21, 0x41, 0x49, 0x4D, 0x33, // З 0x7F, 0x10, 0x08, 0x04, 0x7F, // И 0x7E, 0x20, 0x11, 0x08, 0x7E, // Й 0x7F, 0x08, 0x14, 0x22, 0x41, // К 0x40, 0x3F, 0x01, 0x01, 0x7F, // Л 0x7F, 0x06, 0x08, 0x06, 0x7F, // М 0x7F, 0x08, 0x08, 0x08, 0x7F, // Н 0x3E, 0x41, 0x41, 0x41, 0x3E, // О 0x7F, 0x01, 0x01, 0x01, 0x7F, // П 0x7F, 0x09, 0x09, 0x09, 0x06, // Р 0x3E, 0x41, 0x41, 0x41, 0x22, // С 0x03, 0x01, 0x7F, 0x01, 0x03, // Т 0x61, 0x26, 0x18, 0x06, 0x01, // У 0x1C, 0x22, 0x7F, 0x22, 0x1C, // Ф 0x63, 0x14, 0x08, 0x14, 0x63, // Х 0x3F, 0x20, 0x20, 0x3F, 0x60, // Ц 0x07, 0x08, 0x08, 0x08, 0x7F, // Ч 0x7F, 0x40, 0x7F, 0x40, 0x7F, // Ш 0x3F, 0x20, 0x3F, 0x20, 0x7F, // Щ 0x01, 0x7F, 0x48, 0x48, 0x30, // Ъ 0x7F, 0x48, 0x78, 0x00, 0x7F, // Ы 0x7F, 0x48, 0x48, 0x30, 0x00, // Ь 0x41, 0x49, 0x49, 0x2A, 0x1C, // Э 0x7F, 0x10, 0x3E, 0x41, 0x3E, // Ю 0x66, 0x19, 0x09, 0x09, 0x7F, // Я 0x20, 0x54, 0x54, 0x78, 0x40, // а 0x3E, 0x49, 0x45, 0x45, 0x38, // б 0x7E, 0x4A, 0x4A, 0x34, 0x00, // в 0x7C, 0x04, 0x04, 0x0C, 0x00, // г 0x38, 0x45, 0x45, 0x49, 0x3E, // д 0x38, 0x54, 0x54, 0x54, 0x18, // е 0x4C, 0x30, 0x7C, 0x30, 0x4C, // ж 0x24, 0x42, 0x4A, 0x34, 0x00, // з 0x7C, 0x20, 0x10, 0x7C, 0x00, // и 0x7C, 0x21, 0x11, 0x7C, 0x00, // й 0x7C, 0x10, 0x28, 0x44, 0x00, // к 0x40, 0x3C, 0x04, 0x04, 0x7C, // л 0x7C, 0x08, 0x10, 0x08, 0x7C, // м 0x7C, 0x10, 0x10, 0x7C, 0x00, // н 0x38, 0x44, 0x44, 0x44, 0x38, // о 0x7C, 0x04, 0x04, 0x7C, 0x00, // п 0xFC, 0x18, 0x24, 0x24, 0x18, // р 0x38, 0x44, 0x44, 0x44, 0x28, // с 0x04, 0x04, 0x7C, 0x04, 0x04, // т 0x4C, 0x90, 0x90, 0x90, 0x7C, // у 0x18, 0x24, 0x7E, 0x24, 0x18, // ф 0x44, 0x28, 0x10, 0x28, 0x44, // х 0x3C, 0x20, 0x20, 0x3C, 0x60, // ц 0x1C, 0x10, 0x10, 0x7C, 0x00, // ч 0x7C, 0x40, 0x7C, 0x40, 0x7C, // ш 0x3C, 0x20, 0x3C, 0x20, 0x7C, // щ 0x04, 0x7C, 0x50, 0x70, 0x00, // ъ 0x7C, 0x50, 0x70, 0x00, 0x7C, // ы 0x7C, 0x50, 0x70, 0x00, 0x00, // ь 0x42, 0x42, 0x52, 0x52, 0x3C, // э 0x7C, 0x10, 0x38, 0x44, 0x38, // ю 0x40, 0x2C, 0x12, 0x7E, 0x00, // я 0x7E, 0x4B, 0x4A, 0x4B, 0x42, // Ё D0 81 0x38, 0x55, 0x54, 0x55, 0x18, // ё D1 91 0x7C, 0x04, 0x05, 0x04, 0x00, //81 129 Ѓ D0 83 0x00, 0x78, 0x0A, 0x09, 0x00, //83 131 ѓ D1 93 0x3E, 0x49, 0x49, 0x41, 0x22, //AA 170 Є D0 84 0x38, 0x54, 0x54, 0x44, 0x28, //BA 186 є D1 94 0x00, 0x41, 0x7F, 0x41, 0x00, //B2 178 І D0 86 0x00, 0x44, 0x7D, 0x40, 0x00, //B3 179 і D1 96 0x00, 0x45, 0x7C, 0x45, 0x00, //AF 175 Ї D0 87 0x00, 0x45, 0x7C, 0x41, 0x00, //BF 191 ї D1 97 0x23, 0x44, 0x39, 0x04, 0x03, //A1 161 Ў D0 8E 0x24, 0x49, 0x32, 0x09, 0x04, //A2 162 ў D1 9E 0x7E, 0x02, 0x02, 0x02, 0x01, //A5 165 Ґ D2 90 0x7C, 0x04, 0x04, 0x02, 0x00, //B4 180 ґ D2 91 0x00, 0x4A, 0x55, 0x29, 0x00, //A7 167 § C2 A7 0x00, 0x06, 0x09, 0x09, 0x06, // ° C2 B0 0x44, 0x44, 0x5F, 0x44, 0x44, //B1 177 ± C2 B1 0x7C, 0x10, 0x10, 0x3C, 0x40, //B5 181 µ C2 B5 };И демонстрационная картинка (mice.c) - к библиотеке отношения не имеет, просто для иллюстрации:
#if defined(__AVR__) #include <avr/pgmspace.h> #define fontdatatype const uint8_t #elif defined(__PIC32MX__) #define PROGMEM #define fontdatatype const unsigned char #elif defined(__arm__) #define PROGMEM #define fontdatatype const unsigned char #endif // mice bitmap 128x64 fontdatatype mice[] PROGMEM={ 0x80, 0x40, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0010 (16) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, // 0x0020 (32) pixels 0x3F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0030 (48) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0040 (64) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0050 (80) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xCF, 0xCF, 0xEF, 0xCF, 0x9F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, // 0x0060 (96) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x9F, 0x9F, 0xDF, 0xCF, 0xCF, 0xCF, // 0x0070 (112) pixels 0x1F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0080 (128) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0090 (144) pixels 0xFF, 0xFF, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00A0 (160) pixels 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x00B0 (176) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x00C0 (192) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x00D0 (208) pixels 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xE1, 0x07, 0x3F, // 0x00E0 (224) pixels 0xFF, 0xFF, 0x7F, 0x1F, 0x47, 0x33, 0x98, 0xCC, 0xE6, 0xF3, 0xF9, 0xFE, 0xFF, 0xFF, 0x3F, 0x07, // 0x00F0 (240) pixels 0xC0, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0100 (256) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0110 (272) pixels 0xFF, 0xFF, 0xFC, 0xF0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0120 (288) pixels 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0130 (304) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0140 (320) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x07, 0x03, 0x01, 0x01, 0x00, // 0x0150 (336) pixels 0x00, 0x00, 0xC0, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xF7, 0xE6, 0x00, // 0x0160 (352) pixels 0x33, 0xF9, 0xF0, 0x04, 0x0E, 0xCF, 0xEF, 0xE7, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0x00, 0x03, // 0x0170 (368) pixels 0x03, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0180 (384) pixels 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x1F, // 0x0190 (400) pixels 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1E, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01A0 (416) pixels 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xF9, 0xF1, 0xC3, // 0x01B0 (432) pixels 0x87, 0xCF, 0x9F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x01C0 (448) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01D0 (464) pixels 0x00, 0x00, 0x3F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0xDF, 0xCF, 0xEF, 0xE7, 0xB7, 0x33, 0x11, 0x30, // 0x01E0 (480) pixels 0xC6, 0xC7, 0xE3, 0x10, 0x32, 0x17, 0x67, 0xAF, 0xCF, 0x1F, 0x3F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, // 0x01F0 (496) pixels 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0200 (512) pixels 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0210 (528) pixels 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0220 (544) pixels 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x01, 0xC1, 0xF1, // 0x0230 (560) pixels 0x07, 0x3F, 0x0F, 0x87, 0x0C, 0x01, 0x0F, 0x7F, 0x1F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x0F, 0xFF, // 0x0240 (576) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF8, 0xF8, 0xF0, // 0x0250 (592) pixels 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00, 0x3E, 0x3C, // 0x0260 (608) pixels 0x03, 0x8F, 0x01, 0x3C, 0x3E, 0x00, 0x83, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x70, // 0x0270 (624) pixels 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0280 (640) pixels 0xFF, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0290 (656) pixels 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xE0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0x7E, 0x7C, // 0x02A0 (672) pixels 0x3C, 0x3C, 0x3C, 0x78, 0x78, 0xF1, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF3, 0xE7, // 0x02B0 (688) pixels 0xF0, 0xF8, 0xF0, 0xF3, 0xF8, 0xF8, 0xFC, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xFF, // 0x02C0 (704) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x02D0 (720) pixels 0x80, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0x63, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x08, 0x00, // 0x02E0 (736) pixels 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0xFF, 0x3F, 0x39, 0x78, 0xF8, 0xF8, 0x60, 0x00, // 0x02F0 (752) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0300 (768) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, // 0x0310 (784) pixels 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xE7, 0xCF, 0x9F, 0x3F, 0x3F, 0x7F, 0x7F, 0xFF, // 0x0320 (800) pixels 0xF8, 0xE3, 0xCF, 0xBF, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0330 (816) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x9F, 0xCF, 0xE3, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, // 0x0340 (832) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0350 (848) pixels 0xFF, 0xFC, 0xF9, 0xF3, 0xE7, 0xCE, 0xDE, 0x9C, 0xB9, 0x33, 0x67, 0x87, 0x0F, 0x4F, 0x8F, 0x8F, // 0x0360 (864) pixels 0x8E, 0x8E, 0x8E, 0x8E, 0x07, 0x87, 0xF3, 0x79, 0x7D, 0x3E, 0x9F, 0xCF, 0xE7, 0xF3, 0xF8, 0xFE, // 0x0370 (880) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0380 (896) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0390 (912) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, // 0x03A0 (928) pixels 0xFE, 0xFC, 0xFC, 0xFC, 0xFD, 0xF8, 0xFA, 0xF8, 0xF8, 0xF9, 0xF9, 0xFD, 0xF9, 0xF9, 0xF9, 0xF9, // 0x03B0 (944) pixels 0xF9, 0xFD, 0xFD, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x03C0 (960) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x03D0 (976) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF9, 0xF8, 0xF0, 0xF1, // 0x03E0 (992) pixels 0xF1, 0xF1, 0xF1, 0xF8, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x03F0 (1008) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0400 (1024) pixels };Потому что критиковать было нечего, была только декларация о намерениях. Вот теперь есть реальный результат, значит можно тестировать на хомячках и давать реальные замечания.
Пока с меня только вопросы:
фильтровать входящее, все недопустимое отбрасывать.
Второй удобнее, т.к. нагляднее. Кстати, как насчет объединенных строк, типа
LD.printStringSmall("Темп. =", temp, "°");?Библиотека толко текст отображает? Без линий и прямоугольников красивое меню сложно будет нарисовать. Может просто взять этот кусок из тех библиотек? (моему минимализму достаточно только прорисовки горизонтальных линий "от ... и до ...").
Спасибо за конструктивную критику.
А нужно ли это?
Компьютер с 32 Кбайтами ROM и 2 Кбайтами RAM в принципе неспособен отобразить всю таблицу utf-8. Приходится ограничиваться чем-то существенно меньшим.
Кроме того, это две совершенно разные задачи:
- обрабатывать произвольные ВНЕШНИЕ данные,
- обрабатывать заранее заданный набор ВНУТРЕННИХ данных.
В первом случае контроль и отсечение недопустимого обязателен, а во втором - он вряд ли целесообразен. Устройство будет отображать только те тексты, которые для него заранее подготовил программист и никакие другие. Значит, это его забота - чтобы все данные входили в допустимый диапазон, и незачем тратить на обработку таких ситуаций лишние байты памяти.
Волюнтаризм в чистом виде. Можно добавить любое количество (пока их общее число не превысит 255), но каждый будет стоить довольно много памяти, т.к. помимо 5 байт в знакогенераторе на каждый дополнительный символ требуется отдельная ветка в коде.
LD.printStringSmall("Темп. =", temp, "°");?Меня тоже сильно напрягает отсутствие в Arduino стандартной С-шной функции printf, но т.к. мое знакомство с данным устройством составляет пока менее 2-х недель, я не успел достоверно выяснить, с чем это связано. Сильно подозреваю, что с существенным ограничением по памяти.
Кому нравится поп, а кому - попадья.
Если Вы измеряете температуру, то, вероятно, Вам гораздо важнее "градус" чем "мю". А если емкость конденсаторов, - скорее всего, будет наоборот.
Но добавить еще пару-тройку символов по заказам трудящихся - без проблем.
Только текст и вертикальные линии.
Фактически в условиях Arduino может быть только два типа библиотек для подобного дисплея:
1. Допускают попиксельную графику, в частности позволяет рисовать произвольные линии, окружности и т.п. В частности, позволяют вывести букву в любом месте экрана. Отжирают более 2/3 всей доступной оперативной памяти.
2. Позволяют рисовать только символы (и только по сетке в 8 пикселей по вертикали) и вертикальные линии. Имеют довольно скромные запросы по оперативной памати.
Первые, на мой взгляд, имеют право на существование в проектах, где дисплей - центральное устройство, а весь код предназначен именно для того, чтобы вывести нечто полезное на дисплей.
Если же дисплей имеет вспомогательное значение (например, проекты с развитой электромеханикой: роботы, манипуляторы, управление производственными процессами и пр.), то в большинстве случаев единственно приемлемым будет второй вариант.
Моя библиотека рассчитана именно на 2-й вариант.
PS. В библиотеку входит процедура отображения битмапа. Можно создать любую картинку в битмапе и вывести ее на экран. Так что теоретически пиксельная графика здесь также возможна.
фиг с ней, это графикой. А будет возможность программно задавать несколько пользовательских символов (как это сделало в библиотеках для текстовых LCD), т.е. без правки библиотечных файлов?
А какой смысл в этих нескольких порльзовательских символах?
И каким образом Вы предлагаете их задавать?
Если Вы знаете, как их нарисовать, не будет ли проще добавить их в существующий знакогенератор (т.е. путем правки библиотеки)?
И еще: должны ли им соответствовать какие-либо utf-8 коды, или основная мысль как раз отображать символы, не имеющие utf-8 кодов?
Немного подрихтовал библиотечку.
Решил, что для переключение фонта нужно оставить оба варианта. Строку можно вывести одной из трех процедур: две из них устанавливают конкретный фонт и выводят им, третья выводит ранее установленным фонтом.
Демонстрационная программа:
#include <Wire.h> #include "ASOLED.h" #include "mice.c" static const unsigned char PROGMEM Logo_BMP[] = { 0x10, 0x10, 0xff, 0x01, B00000000, B00000001, B00000001, B00000011, B11110011, B11111110, B01111110, B00110011, B00011111, B00001101, B00011011, B00111111, B00111111, B01111100, B01110000, B00000000, B11000000, B11000000, B11000000, B11100000, B11100000, B11111000, B11111111, B10011111, B11111100, B01110000, B10100000, B11100000, B11110000, B11110000, B01110000, B00110000 }; const uint8_t pacman[] PROGMEM={ 0x14, 0x18, 0x00, 0x01, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3E, 0x1C, // 0x0010 (16) pixels 0x0C, 0x00, 0x00, 0x00, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, // 0x0020 (32) pixels 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, // 0x0030 (48) pixels 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0x7C, // 0x0010 (16) pixels 0x7C, 0x38, 0x20, 0x00, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, // 0x0020 (32) pixels 0xF9, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, // 0x0030 (48) pixels 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, // 0x0010 (16) pixels 0xF8, 0xF0, 0xE0, 0x80, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x0020 (32) pixels 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF9, 0x79, 0x19, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, // 0x0030 (48) pixels 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, }; const uint8_t pacman_clear[] PROGMEM={ 0x03, 0x18, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const uint8_t pill[] PROGMEM={ 0x05, 0x08, 0x00, 0x01, 0x0E, 0x1F, 0x1F, 0x1F, 0x0E, }; int State = 0; long NewTime, OldTime; void setup() { OldTime = millis(); LD.init(); //initialze OLED display LD.clearDisplay(); } void loop() { int n0 = 123; int n1 = -321; // byte i; float d0 = 456.789; float d1 = -0.00789; NewTime = millis(); if ((NewTime - OldTime) > 5000) { OldTime = NewTime; State = ++State % 6; LD.clearDisplay(); } byte phase = NewTime/150%4; if (phase == 3) phase = 1; byte Xpacman = (NewTime-OldTime)/50 + 8; // State = 5; switch (State) { case 0: LD.printString_6x8("0123456789!\"#$%&'()*+", 0, 0); LD.printString_6x8(",-./:;<=>?@[\\]^_`{|}~", 0, 1); LD.printString_6x8("ABCDEFGHIJKLMNOPQRSTU", 0, 2); LD.printString_6x8("VWXYZabcdefghijklmnop",0, 3); LD.printString_6x8("qrstuvwxyzАБВГДЕЁЖЗИЙ", 0, 4); LD.printString_6x8("КЛМНОПРСТУФХЦЧШЩЪЫЬЭЮ", 0, 5); LD.printString_6x8("Яабвгдеёжзийклмнопрст", 0, 6); LD.printString_6x8("уфхцчшщъыьэюяЇїЎў§°±µ", 0, 7); break; case 1: LD.printString_12x16("012345%&'+", 0, 0); LD.printString_12x16("ABCDEFGHIJ", 0, 2); LD.printString_12x16("vwxyzАБВЕЁ", 0, 4); LD.printString_12x16("юяЇїЎў§°±µ", 0, 6); break; case 2: for (int i = 0; i < 128; i++){ int j = (int)(sin(i*0.09 + 0.2)*35) + 45; LD.VertBar(i, j, 0, 90); } break; case 3: LD.printNumber((long)n0, 0, 0); // 123 LD.printNumber((long)n1, 0, 2); // -321 LD.printNumber(d0, 6, 60, 2); // 456.789 LD.printNumber(-d0, 6, 48, 0); // -456.789 LD.printNumber(d1, 8, 0, 6); // 0.00789 LD.printNumber((long)10, 28, 4); // 10 LD.printString_6x8("3"); //, 0, 4); // ^3 LD.printString_12x16("="); //, 0, 4); // = LD.printNumber((long)1000); //, 0, 4); // 1000 break; case 4 : LD.drawBitmap(mice, 0, 0, 128, 8); break; case 5 : for(byte i = 0; i < 5; i++) if (i*24 > Xpacman) LD.drawBitmap(pill, 26 + i*24, 1, 5, 1); LD.drawBitmap(pacman_clear, Xpacman-3, 0, 3, 2); LD.drawBitmap(&pacman[phase*60], Xpacman, 0, 20, 3); LD.drawBitmap(Logo_BMP, 100, 6); //, 16, 2); LD.printString_6x8("Small ", 0, 4); // ^3 LD.printNumber((long)n0); // 123 LD.printNumber(-d0); // -456.789 LD.printString_12x16("Big ", 0, 6); // = LD.printNumber((long)n0); // 123 break; } }Заголовочный файл (ASOLED.h):
/* ASOLED.h - 0.96' I2C 128x64 OLED Driver Library ver. 0.2a 2015 Copyright (c) Sergey Andrianov Please, do not distribute this library. It is not ready yet. Work is not complete. It is a preliminary variant exceptionally for testing. */ #ifndef ASOLED_data_H #define ASOLED_data_H #include <Arduino.h> #define ASOLED_Max_X 128 //128 Pixels #define ASOLED_Max_Y 64 //64 Pixels #define OLED_ADDRESS 0x3C // 0x78 #define I2C_400KHZ 1 // 0 to use default 100Khz, 1 for 400Khz #define Font_6x8 1 #define Font_12x16 2 class ASOLED { public: void init(); void setFont(const char font); // set current font size (CurrFont) [Font_6x8 | Font_12x16] void printString(const char *String, byte X=255, byte Y=255); // Current font void printString_6x8(const char *String, byte X=255, byte Y=255); // font 6x8, switch CurrFont to Font_6x8 void printString_12x16(const char *String, byte X=255, byte Y=255); // font 12x16, switch CurrFont to Font_12x16 byte printNumber(long n, byte X=255, byte Y=255); // current font byte printNumber(float float_num, byte prec=6, byte Y=255, byte numChar=255); // current font void drawBitmap(const byte *bitmaparray, byte X, byte Y, byte width, byte height); // X - in 1 pixel, Y - in 8 pixels void drawBitmap(const byte *bitmaparray, byte X, byte Y); // X - in 1 pixel, Y - in 8 pixels unit void VertBar(int Num, int Val, int MinVal, int MaxVal); // draw vertical line from bottom, h ~ (Val - MinVal)/(MaxVal - MinVal) void clearDisplay(); void setNormalDisplay(); void setInverseDisplay(); void setBrightness(byte Brightness); void setCursorXY(byte Column, byte Row); // X * 1 pixels, Y * 8 pixels byte GetCurrentX(); // get current X position in 1-pixel unit (from 9 to 127) byte GetCurrentY(); // get current Y position in 8-pixel unit (from 0 to 7) private: void sendCommand(byte command); void sendData(byte Data); void printChar(char c); void setPowerOff(); void setPowerOn(); void setPageMode(); void setHorizontalMode(); byte addressingMode; char CurrFont = 1; // font size [Font_6x8 | Font_12x16] char NumberString[16]; // 4 print numbers byte LenString = 0; // current length of NumberString byte CurrX = 0; // current position byte CurrY = 0; }; extern ASOLED LD; // ASOLED object #endifКод библиотеки (ASOLED.cpp):
#include "ASOLED.h" #include <Wire.h> #include <avr/pgmspace.h> #include "a_Small_Rus.c" // registers #define ASA_OLED_COMMAND_MODE 0x80 #define ASA_OLED_DATA_MODE 0x40 //========================================================== unsigned char ASA_utf8_preliminary_byte = 0; unsigned char RecodeUTF_ASA(unsigned char c) { switch (c) { case (unsigned char)0xD0: ASA_utf8_preliminary_byte = c; // wait second byte return 255; case (unsigned char)0xD1: ASA_utf8_preliminary_byte = c; // wait second byte return 255; case (unsigned char)0xD2: ASA_utf8_preliminary_byte = c; // wait second byte return 255; case (unsigned char)0xC2: ASA_utf8_preliminary_byte = c; // wait second byte return 255; default: if(ASA_utf8_preliminary_byte == 0) // first half of ASCII table or nonsupported symbol { if((c >= ' ') && (c <= '~')) { return c; }else{ return '*'; } } else if(ASA_utf8_preliminary_byte == 0xD0) // { ASA_utf8_preliminary_byte = 0; if((c >= 144) && (c <= 191)) { return c - 17; } else if (c == 129) { // РЃ return 191; } else if (c == 131) { // Рѓ return 193; } else if (c == 132) { // Р„ return 195; } else if (c == 134) { // Р† return 197; } else if (c == 135) { // Р‡ return 199; } else if (c == 142) { // РЋ return 201; } else { return '*'; } } else if(ASA_utf8_preliminary_byte == 0xD1) // { ASA_utf8_preliminary_byte = 0; if((c >= 128) && (c <= 143)){ return c + 47; } else if (c == 145) { // С‘ return 192; } else if (c == 147) { // С“ return 194; } else if (c == 148) { // С” return 196; } else if (c == 150) { // С– return 198; } else if (c == 151) { // С— return 200; } else if (c == 158) { // Сћ return 202; } else { return '*'; } } else if(ASA_utf8_preliminary_byte == 0xD2) // { ASA_utf8_preliminary_byte = 0; if (c == 144) { // Тђ return 203; } else if (c == 145) { // Т‘ return 204; } else { return '*'; } } else if(ASA_utf8_preliminary_byte == 0xC2) // { ASA_utf8_preliminary_byte = 0; if (c == 167) { // В§ return 205; } else if (c == 176) { // В° return 206; } else if (c == 177) { // В± return 207; } else if (c == 181) { // Вµ return 208; } else { return '*'; } } else { return '*'; } } } // ====================== LOW LEVEL ========================= void ASOLED::sendCommand(byte command){ Wire.beginTransmission(OLED_ADDRESS); // begin transmitting Wire.write(ASA_OLED_COMMAND_MODE);//data mode Wire.write(command); Wire.endTransmission(); // stop transmitting } void ASOLED::sendData(byte data){ Wire.beginTransmission(OLED_ADDRESS); // begin transmitting Wire.write(ASA_OLED_DATA_MODE);//data mode Wire.write(data); Wire.endTransmission(); // stop transmitting } void ASOLED::printChar(char C){ // write to temp string for numbers NumberString[LenString++] = C; NumberString[LenString] = 0; } void ASOLED::printString_6x8(const char *String, byte X, byte Y){ CurrFont = Font_6x8; setCursorXY(X, Y); while(*String){ unsigned char c = RecodeUTF_ASA(*String++); if (c != 255) { // printChar6(c); sendData(0); for(byte i=0; i<5; i++) sendData(pgm_read_byte(&SmallFont[(c-32)*(int)5 + i + 4])); CurrX += 6; } } } unsigned int EnlardeByte2Word(char b) { unsigned int d = 0; for (byte i = 0; i < 8; i++) { unsigned int e = (((unsigned int)b) & (1 << i)) << i; d = d | e | (e << 1); } return d; } void ASOLED::printString_12x16(const char *String, byte X, byte Y){ CurrFont = Font_12x16; setCursorXY(X, Y); const char *String0 = String; unsigned int m = 0; byte tmpX = CurrX; while(*String){ // print upper half of the string unsigned char c = RecodeUTF_ASA(*String++); if (c != 255) { if(tmpX < (ASOLED_Max_X - 2)) { sendData(0); sendData(0); tmpX += 2; } for(byte i=0; i<5; i++) { if(tmpX < (ASOLED_Max_X - 2)) { m = EnlardeByte2Word(pgm_read_byte(&SmallFont[(c-32)*(int)5 + i + 4])); sendData(lowByte(m)); sendData(lowByte(m)); tmpX += 2; } } } } setCursorXY(CurrX, CurrY+1); while(*String0){ // print lower half of the string unsigned char c = RecodeUTF_ASA(*String0++); if (c != 255) { if(CurrX < (ASOLED_Max_X - 2)) { sendData(0); sendData(0); CurrX += 2; } for(byte i=0; i<5; i++) { if(CurrX < (ASOLED_Max_X - 2)) { m = EnlardeByte2Word(pgm_read_byte(&SmallFont[(c-32)*(int)5 + i + 4])); sendData(highByte(m)); sendData(highByte(m)); CurrX += 2; } } } } setCursorXY(CurrX, CurrY-1); } void ASOLED::printString(const char *String, byte X, byte Y) // Current font { if(CurrFont == Font_6x8) printString_6x8(String, X, Y); else printString_12x16(String, X, Y); } byte ASOLED::printNumber(long long_num, byte X, byte Y){ LenString = 0; setCursorXY(X, Y); byte char_buffer[10] = ""; byte i = 0; byte f = 0; // number of characters if (long_num < 0) { f++; printChar('-'); long_num = -long_num; } else if (long_num == 0) { f++; printChar('0'); printString(&NumberString[0]); //, X, Y); return f; } while (long_num > 0) { char_buffer[i++] = long_num % 10; long_num /= 10; } f += i; for(; i > 0; i--) printChar('0'+ char_buffer[i - 1]); printString(&NumberString[0]); //, X, Y); return f; } byte ASOLED::printNumber(float float_num, byte prec, byte X, byte Y){ LenString = 0; setCursorXY(X, Y); // prec - 6 maximum byte num_int = 0; byte num_frac = 0; byte num_extra = 0; long d = float_num; // get the integer part float f = float_num - d; // get the fractional part if (d == 0 && f < 0.0){ printChar('-'); num_extra++; printChar('0'); num_extra++; f *= -1; printString(&NumberString[0]); LenString = 0; } else if (d < 0 && f < 0.0){ num_int = printNumber(d); // count how many digits in integer part LenString = 0; f *= -1; } else{ num_int = printNumber(d); // count how many digits in integer part LenString = 0; } // only when fractional part > 0, we show decimal point if (f > 0.0){ printChar('.'); num_extra++; printString(&NumberString[0]); //, X, Y); LenString = 0; if (num_int + prec > 8) prec = 8 - num_int; for (byte j=0; j<prec; j++){ f *= 10.0; byte dd = f; printChar('0' + dd); f -= dd; } printString(&NumberString[0]); num_frac = prec; } return num_int + num_frac + num_extra; } void ASOLED::drawBitmap(const byte *bitmaparray, byte X, byte Y, byte width, byte height){ // max width = 128 // max height = 8 for (int j = 0; j < height; j++) { setCursorXY(X, Y + lowByte(j)); for (byte i = 0; i < width; i++) sendData(pgm_read_byte(bitmaparray + i + 4 + j*width)); } } void ASOLED::drawBitmap(const byte *bitmaparray, byte X, byte Y){ byte width = pgm_read_byte(&bitmaparray[0]); byte height = pgm_read_byte(&bitmaparray[1])/8; for (int j = 0; j < height; j++) { setCursorXY(X, Y + lowByte(j)); for (byte i = 0; i < width; i++) sendData(pgm_read_byte(bitmaparray + i + 4 + j*width)); } } void ASOLED::VertBar(int Num, int Val, int MinVal, int MaxVal) { if (Val < MinVal) Val = MinVal; // consider that Val already scaled if (Val > MaxVal) Val = MaxVal; Val -= MinVal; for (int i = 0; i < 8; i++) // go from high levels to low ones { setCursorXY(Num, i); int b; // will calc this value for each columns (bars) int UpB = (MaxVal - MinVal)*(8-i)/8; if (Val <= UpB) // top boundary { int DownB = (MaxVal - MinVal)*(7-i)/8; if (Val >= DownB) // bottom boundary { // Val are in this interval int j = (Val - DownB)*8/(UpB - DownB); int k = 0xFF00; b = (k >> j) & 0xFF; } else { b = 0; } } else { b = 0xFF; } sendData(b); } setCursorXY(0, 0); } // =================== High Level =========================== ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // commands #define ASA_OLED_CMD_DISPLAY_OFF 0xAE #define ASA_OLED_CMD_DISPLAY_ON 0xAF #define ASA_OLED_CMD_NORMAL_DISPLAY 0xA6 #define ASA_OLED_CMD_INVERSE_DISPLAY 0xA7 #define ASA_OLED_CMD_SET_BRIGHTNESS 0x81 #define ASA_OLED_RIGHT_SCROLL 0x26 #define ASA_OLED_LEFT_SCROLL 0x27 #define ASA_OLED_SET_VERTICAL_SCROLL_AREA 0xA3 #define ASA_OLED_VERTICAL_RIGHT_SCROLL 0x29 #define ASA_OLED_VERTICAL_LEFT_SCROLL 0x2A #define ASA_OLED_CMD_ACTIVATE_SCROLL 0x2F #define ASA_OLED_CMD_DEACTIVATE_SCROLL 0x2E #define HORIZONTAL_ADDRESSING 0x00 #define PAGE_ADDRESSING 0x02 #define Scroll_Left 0x00 #define Scroll_Right 0x01 #define Scroll_Up 0x02 #define Scroll_Down 0x03 #define Scroll_2Frames 0x07 #define Scroll_3Frames 0x04 #define Scroll_4Frames 0x05 #define Scroll_5Frames 0x00 #define Scroll_25Frames 0x06 #define Scroll_64Frames 0x01 #define Scroll_128Frames 0x02 #define Scroll_256Frames 0x03 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SSD1306 Commandset // ------------------ // Fundamental Commands #define ASA_DISPLAY_ALL_ON_RESUME 0xA4 // Addressing Setting Commands #define ASA_MEMORY_ADDR_MODE 0x20 // Hardware Configuration Commands #define ASA_SET_START_LINE 0x40 #define ASA_SET_SEGMENT_REMAP 0xA0 #define ASA_SET_MULTIPLEX_RATIO 0xA8 #define ASA_COM_SCAN_DIR_DEC 0xC8 #define ASA_SET_DISPLAY_OFFSET 0xD3 #define ASA_SET_COM_PINS 0xDA #define ASA_CHARGE_PUMP 0x8D // Timing & Driving Scheme Setting Commands #define ASA_SET_DISPLAY_CLOCK_DIV_RATIO 0xD5 #define ASA_SET_PRECHARGE_PERIOD 0xD9 #define ASA_SET_VCOM_DESELECT 0xDB void ASOLED::init(){ Wire.begin(); // upgrade to 400KHz! (only use when your other i2c device support this speed) if (I2C_400KHZ){ // save I2C bitrate (default 100Khz) byte twbrbackup = TWBR; TWBR = 12; } setPageMode(); // default addressing mode clearDisplay(); setCursorXY(0,0); // Additional command LD.setPowerOff(); LD.sendCommand(ASA_SET_DISPLAY_CLOCK_DIV_RATIO); LD.sendCommand(0x80); LD.sendCommand(ASA_SET_MULTIPLEX_RATIO); LD.sendCommand(0x3F); LD.sendCommand(ASA_SET_DISPLAY_OFFSET); LD.sendCommand(0x0); LD.sendCommand(ASA_SET_START_LINE | 0x0); LD.sendCommand(ASA_CHARGE_PUMP); LD.sendCommand(0x14); LD.sendCommand(ASA_MEMORY_ADDR_MODE); LD.sendCommand(0x00); LD.sendCommand(ASA_SET_SEGMENT_REMAP | 0x1); LD.sendCommand(ASA_COM_SCAN_DIR_DEC); LD.sendCommand(ASA_SET_COM_PINS); LD.sendCommand(0x12); LD.setBrightness(0xCF); LD.sendCommand(ASA_SET_PRECHARGE_PERIOD); LD.sendCommand(0xF1); LD.sendCommand(ASA_SET_VCOM_DESELECT); LD.sendCommand(0x40); LD.sendCommand(ASA_DISPLAY_ALL_ON_RESUME); LD.setNormalDisplay(); LD.setPowerOn(); } void ASOLED::setCursorXY(byte X, byte Y){ // Y - 1 unit = 1 page (8 pixel rows) // X - 1 unit = 1 pixel columns if (X < 128) if ((X != CurrX) || (Y != CurrY)){ sendCommand(0x00 + (X & 0x0F)); //set column lower address sendCommand(0x10 + ((X>>4)&0x0F)); //set column higher address sendCommand(0xB0 + Y); //set page address CurrX = X; CurrY = Y; } } void ASOLED::setFont(const char font) { CurrFont = font; } void ASOLED::clearDisplay() { for(byte page=0; page<8; page++) { setCursorXY(0, page); for(byte column=0; column<128; column++) //clear all columns sendData(0); } setCursorXY(0,0); } void ASOLED::setInverseDisplay(){ sendCommand(ASA_OLED_CMD_INVERSE_DISPLAY); } void ASOLED::setNormalDisplay(){ sendCommand(ASA_OLED_CMD_NORMAL_DISPLAY); } void ASOLED::setPowerOff(){ sendCommand(ASA_OLED_CMD_DISPLAY_OFF); } void ASOLED::setPowerOn(){ sendCommand(ASA_OLED_CMD_DISPLAY_ON); } void ASOLED::setBrightness(byte Brightness){ sendCommand(ASA_OLED_CMD_SET_BRIGHTNESS); sendCommand(Brightness); } void ASOLED::setPageMode(){ addressingMode = PAGE_ADDRESSING; sendCommand(0x20); //set addressing mode sendCommand(PAGE_ADDRESSING); //set page addressing mode } void ASOLED::setHorizontalMode(){ addressingMode = HORIZONTAL_ADDRESSING; sendCommand(0x20); //set addressing mode sendCommand(HORIZONTAL_ADDRESSING); //set page addressing mode } ASOLED LD; // Preinstantiate ObjectsОстальные два файла (шрифт и демонстрационный битмап) остались без изменений, так что их можно взять из 5-го поста настоящей темы.
Советую досмотреть демонстрацию до крнца: хотя библиотека формально и не поддерживает графику, но...
Спасибо за ответ!
И спасибо за библиотеку! Библиотека понравилась, честно! Спасибо за Ваш труд!
Если позволите, скажу несколько слов про концепцию РУССКОГО ШРИФТА. Я по образованию инженер-электронщик, имею некоторый жизненный опыт и некоторые свои мысли по поводу развития РУССКОГО ПРОЕКТА АРДУИНО, с которыми хочу поделиться.
1) По моему мнению надо сделать революционное решение и перестать тащить за собой "БАБУШКИН САКВОЯЖ", который и выбросить жалко, и пользы от него с гулькин нос. Что я имею в виду? Предлагаю отказаться от полной поддержки кодировки ANSI в проекте РУССКОГО ARDUINO. ПОСЕМУ ПРЕДЛАГАЮ ПЕРЕПИСАТЬ ТАБЛИЦУ СИМВОЛОВ ПОД ПОТРЕБИТЕЛЬСКИЕ НУЖДЫ МАСТЕРОВ ПО ЭЛЕКТРОНИКИ И ВЫКИНУТЬ ИЗ ЭТОЙ ТАБЛИЦЫ ВСЕ ЗАГЛАВНЫЕ АНГЛИЙСКИЕ БУКВЫ, ЗАМЕНИВ ИХ НА ВОСТРЕБОВАННЫЕ СПЕЦИАЛИЗИРОВАННЫЕ СИМВОЛЫ ДЛЯ ИНДИКАЦИИ ДАТЧИКОВ И ИСПОЛНИТЕЛЬНЫХ УСТРОЙСТВ СТАНДАРТНЫМИ СРЕДСТВАМИ ШРИФТА. Предлагаю оставить только малые английские буквы исключительно только для совместимости и интернет шилдами.
2) Создать шрифтовые символы таких элементов как батарейка, термопара, солнечная панель, мотор, насос, реле, автомат, кнопка, лампа, кран, звонок и т.д. Эти символы должны быть в двух графических видах - активный т.е.(включенный) и неактивный (выключенный). Можно использовать инверсию графического изображения, или еще что.
3) Считаю, что в шрифт также необходимо добавить фукцию рисования таблиц, в ячейки которых можно раставлять буквенно - численные значения, а также в процессе наладки изделия, выводить матрицы и массивы.
Вот такое мое предложение. Жду ваших коментариев.
Если позволите, скажу несколько слов про концепцию РУССКОГО ШРИФТА. Я по образованию инженер-электронщик, имею некоторый жизненный опыт и некоторые свои мысли по поводу развития РУССКОГО ПРОЕКТА АРДУИНО, с которыми хочу поделиться.
а как же российский флаг? а давайте еще гимн пропишем и что бы обязательно при включении прокручивался.. и всем вставать при прокрутке гимна...
да и обязательно нужно прописать портрет ВВП. на каждом экране по центру что бы был.
А может не стоит тролить?!
А может не стоит тролить?!
тролить? это вы про свои идеи? давайте прикинем...
с одной стороны, латиница и весь глобус разработчиков...
с вашей стороны, кирилица и 2 с половиной инвалида которым это нужно
нарисовать вы можете все что вам хочеться. вообще без ограничений..
Троль тем и отличается, что глобус. Если вам это не нужно - валите из темы в глобус разработчиков.
Троль тем и отличается, что глобус. Если вам это не нужно - валите из темы в глобус разработчиков.
халявщики отличаются тем что когда им дают маленький кусочек. то они в ответ приносят кучу разных требований и условий. которые нафиг никому не нужны!
да ладно, идея в общем-то здравая.
сильно сомневаюсь, что кто-то у нас пишет проекты "на весь глобус". и действительно, для ардуины вместо дублиующих шрифтов было бы гораздо удобнее добавить спец. символы.
кстати, интересно. только на мове hello world получается в рифму. украинский- красивый язык )
сильно сомневаюсь, что кто-то у нас пишет проекты "на весь глобус".
вы не поверите :) но таки да пишут. и их много у нас есть.
1) По моему мнению надо сделать революционное решение и перестать тащить за собой "БАБУШКИН САКВОЯЖ", который и выбросить жалко, и пользы от него с гулькин нос. Что я имею в виду? Предлагаю отказаться от полной поддержки кодировки ANSI в проекте РУССКОГО ARDUINO. ПОСЕМУ ПРЕДЛАГАЮ ПЕРЕПИСАТЬ ТАБЛИЦУ СИМВОЛОВ ПОД ПОТРЕБИТЕЛЬСКИЕ НУЖДЫ МАСТЕРОВ ПО ЭЛЕКТРОНИКИ И ВЫКИНУТЬ ИЗ ЭТОЙ ТАБЛИЦЫ ВСЕ ЗАГЛАВНЫЕ АНГЛИЙСКИЕ БУКВЫ, ЗАМЕНИВ ИХ НА ВОСТРЕБОВАННЫЕ СПЕЦИАЛИЗИРОВАННЫЕ СИМВОЛЫ ДЛЯ ИНДИКАЦИИ ДАТЧИКОВ И ИСПОЛНИТЕЛЬНЫХ УСТРОЙСТВ СТАНДАРТНЫМИ СРЕДСТВАМИ ШРИФТА. Предлагаю оставить только малые английские буквы исключительно только для совместимости и интернет шилдами.
Скажите, Вы, как инженер, пытались применять в своих проектах ну, скажем, резьюу диаметром 3.6 мм?
Существует такое понятик как стандарт и отход от него (в отсутствие совершенно исключительных причин, а личные амбиции к таковым не относятся) практически однозначно ведет в тупик.
Что касается отказа от латинницы, то, насколько мне известно, именно таковыми и были предыдущие проекты по русификации дисплеев: количество символов сохрянялось постоянным (как наследие ASCII) - 95 штук, но начертание латинницы заменялось на начертание кириллицы. В принципе, подход, имеющий право на существование, но весьма осложняющий процесс программирования, что, на мой взгляд, существенно противоречит идеям проекта Arduino.
Данный проект отличается именно тем, что:
- совмещает в единой таблице символя кириллицы и латинницы и не требует переключений таблиц знакогенератора при переходе на латинницу и обратно,
- позволяет видеть буквы на экране в их привычном виде при стандартной настройке IDE Arduino.
Кроме того, с какой целью вообще отказываться от каких-то символов? Было 95, я добавил 80 с чем-то, даже до адресации одним байтом еще порядка 80 свободных номеров.
И потом, лично мне как-то особенно не нужна кириллица. А вот латинницей я активно пользуюсь. Ну просто карты так легли, что взялся за этот проект, который мне по сути не особо нужен.
И еще: в среде одна кодировка кириллицы, а в консоли - другая. А латинница совпадает. Так что при отладке в консоли все равно альтернаоивы использованию латинницы нет.
Еще, кстати, на днях обнаружил, что Processing не поддерживает киоиллицу даже в IDE.
Так что причин для отказа от латинницы IMHO нет. Никаких.
Вам нужны батарейкак, термопара, оеле, музыканту наверняка понадобятся ноты, водителю - дорожные знаки и т.д.
Все это хорошо, но почему для вывода пиктограмм нужно использовать именно оператор print, когда есть гораздо более подходящий drawBitmap? Вы же не собираетесь использовать длинные строки из символов батареек и реле? (кстати, в отличие от музыканта)
А если Вы запускали демонстрационный пример, то видели, что drawBitmap можно при желании применять даже для создании анимации.
Вот такое мое предложение. Жду ваших коментариев.
Не согласен.
Идея разработки хорошая. Концепция состоит в объединении двух шрифтов в согласии для простоты реализации двуязычного вывода на экран. Замечательная идея, преклоняюсь!
Но. Эта идея дает только некоторые преимущества, хоть и существенные, но они направлены для возможности, как говорил глобус, реализации проектов как англоязычным потребителям, так и русскоязычным потребителям. То есть и нашим и вашим. В этом подходе есть преимущества и недостатки. Да, существенно упрощается буквенный обмен, но скорость разработок существенно не меняется, так как надо каждый раз рисовать необходимые картинки, без возможности их масштабирования. Если же заменить ненужные в принципе для разработчика заглавные английские буквы наиболее распространенными символами, то процесс разработки существенно ускоряется, так как никто уже не тратит время на придумывание и реализацию картинного творчества.
Кроме того я несколько раз подчеркивал, что это революционное решение и направлено оно именно для развития РУССКОГО АНДРУИНО. Развитие же предполагает простоту и скорость програмной реализации идеи и несовместим с ппотерей времени на рисование необходимых символов и расчета координат их расположения на экране. Только вчера потерял два часа на реализацию на экране вида с символьно-графическим изображением в том представлении, в котором задумал. И сделал вывод - это крайне неудобно.
Вместо того, чтобы просто и быстро реализовать програмный код, тратишь время на оформление вида экрана. Потому считаю, что моя идея имеет право на жизнь как существенно увеличивающая скорость разработок библиотека. Тем более, что я изначально ориентирован на русский рынок сбыта и обслуживание англоязычного населения мне как-то без потребности.
Посему предложение. Чтобы глобус не считал меня халявщиком, я прошу вашего разрешения, как автора, воспользоваться вашей идеей и кодом, чтобы реализовать русскую буквенно символьную библиотеку кода ардуино, раз вы сами не хотите эти заниматься. Если позволите, то я переделаю ваш код под реализацию своей идеи, а время покажет правильность, или ошибочность моих предположений. Кстати, русский буквенно-символьный код может иметь не одну универсальную библиотеку, а набор библиотек, собранный в одно целое в зависимости от потребности специализации. Как то для автоматики, бытовой, для музыкантов, для производства, для рыбаков, для глобуса :)
а что в ардуино русского ты предлагаешь? если убрать латинские символы и в вместо них добавить русские? но от этого русским он не станет)))
а если в проекте нет дисплея? ну не нужен он там. проект автоматически становится забугорным?
ну тогда давайте и команды переписывать, и функции, да все ядро на русском, компилятор запилим, а то все же на английском
а что в ардуино русского ты предлагаешь? если убрать латинские символы и в вместо них добавить русские? но от этого русским он не станет)))
а если в проекте нет дисплея? ну не нужен он там. проект автоматически становится забугорным?
ну тогда давайте и команды переписывать, и функции, да все ядро на русском, компилятор запилим, а то все же на английском
Жень, дык это, цифры то АРАБСКИЕ остануться... че делать то?
а что делать тем у кого другие дисплеи? другие контролеры? они будут не русскими? как им жить дальше то?
Блин как будто нам было мало одного Клапауций...
точно. и от цифр придется отказаться)))
точно. и от цифр придется отказаться)))
во блин. что бы там сразу совсем русская была ардуина
а микропроцесоры из бересты вырезать... хотя блин береза и в северной америке растет некисло... что же делать? из чего производить процесоры?
Процессоры из святых мощей не проблема. Спасибо за таблицу перекодировки в церковн-словянские, но остается вопрос отображения шеснадцетиричных. Местные попы не знают, кадилом угрожают. Как 0xff по православному выводить?
Не согласен.
Идея разработки хорошая. Концепция состоит в объединении двух шрифтов в согласии для простоты реализации двуязычного вывода на экран. Замечательная идея, преклоняюсь!
Нет. Концепция состоит в создании библиотеки, которая строится на двух с половиной принципах:
"1". Ограниченная поддержка используемой в Arduino IDE кодировки utf-8 достаточная для русско-/украино-/белорусско-говорящего пользователя объеме.
"2". Компактность, т.е. минимум места занисаемого в оперативной и постоянной памати.
"Половинка". Учитывая весьма скромный размер дисплея, возможность писать шрифтом удвоенного размера с использованием существующего знакогенератора (с целью "2").
Сомнительное преимущество. "Картинное творчество" - один из способов придания законченному изделию индивидуальности.
И потом, я решительно не вижу никаких доводов в пользу упразднения латинницы. Лично мне, например, латинница нужна. Гораздо больше, чем кириллица. Тем более, ВСЕХ проблем предложенная библиотека не решает, например, добиться, чтобы в коде и консоли кириллические тексты выглядели одинаково, все равно не получится. Повторяю, я занялся кириллизацией шрифта по стечению обстоятельств: ждал посылки из Китая с заказанным набором деталей. И за это время обнаружил, что приемлемого решения для кириллизации имеющегося у меня дисплея нет. Причем, написать ее не сложно, проблема в том, что тому, кто способен ее написать, она не нужна, а кто испытывает в ней насущную необходимость (новички), написать ее не способны.
Но в любом случае - идее искоренения латинницы - мое твердое НЕТ.
Кстати, по-русски пишется "Ардуино". Не нужно пытаться скмбинировать эхотаг с моим ником. Мой ник никакого отношения к эхотагу не имеет - я под ним регистрируюсь на всех форумах.
Посему предложение. Чтобы глобус не считал меня халявщиком, я прошу вашего разрешения, как автора, воспользоваться вашей идеей и кодом, чтобы реализовать русскую буквенно символьную библиотеку кода ардуино, раз вы сами не хотите эти заниматься. Если позволите, то я переделаю ваш код под реализацию своей идеи, а время покажет правильность, или ошибочность моих предположений. Кстати, русский буквенно-символьный код может иметь не одну универсальную библиотеку, а набор библиотек, собранный в одно целое в зависимости от потребности специализации. Как то для автоматики, бытовой, для музыкантов, для производства, для рыбаков, для глобуса :)
Ну, мне, собственно, глубоко фиолетово кто и кем Вас будет считать. Нов Ваших словах я усматриваю рациональное зерно, правда, способ его воплощения мне видится несколько иным.
Привязывать пиктограммы к символам - решение, имеющее целый ряд отрицательных свойств:
1. Новичку трудно разобраться во взаимоотношении категорий "символ", "ко символа", "число". Если на это еще навесить отношение между символами и пиктограммами, он совершенно запутается. Поэтому лучше пусть выбирает пиктограммы не по коду символа, а по номеру - ему это будет понятнее.
2. На знакоместо у меня отводится 6 пикселов по ширине. А ширина символа в знакогенераторе - 5 пикселов (для экономии): один вертикальный ряд пикселов всегда оставтся пустым и разделяет символы между собой. Для пиктограммы, думаю, это неудобно.
3. Опять же, символ имеет фиксированный размер 5х8, а для пиктограммы может понадобиться большее, например, 8х8, 12х8 или 24х16. Нет смысла ограничивать ее размер форматом символа.
Поэтому я предлагаю следующее решение.
Я усовершенствую drawBitmap, чтобы она могла работать не только с отдельными картинками, но и с целыми библиотеками картинок одинакового размера, будь то набор пиктограмм или несколько кадров анимации для одного (или нескольких) объектов.
Мы с Вами согласовываем формат библиотеки. И Вы занимаетесь уже только библиотеками пиктограмм.
Каждый делает свою работу и все довольны.
Вопрос резонный.
Но вспомните собственную дату регистрации на форуме и посмотрите на мою - это я еще зарегистрировался за несколько дней до покупки первого контроллера.
Так что я пока не представляю всего разнообразия моделей Ардуино (и родственных проектов) и особенностей их взаимодействия с периферией. Да и в ближайшее время не стремлюсь разобраться - мне бы с Uno освоиться... Знаю только, что особенности есть (если судить по коду просмотренных мною библиотек).
Аналогично с многообразием используемых а Ардуино-проектах дисплеев. Мне OLED понравился тем, что безусловно контрастный и жрет мало электричества. Разбираться с другими начну не раньше, чем они мне понадобятся (хотя пара формата 16х2 символов в запасе имеется).
Но если кому надо - готов оказать содействие.
Вопрос резонный.
это был риторический вопрос... боюсь что все многообразие дисплеев и контролеров. а так же вариантов их сборки. устанете перелопачивать. тем более за просто так ( тоесть даром). дело не благодарное и сильно безсмысленное.
Я же написал: "Разбираться с другими начну не раньше, чем они мне понадобятся".
Вот в этом как раз и проблема. Большинство ( ака товарищ просящий прибить латиницу), не впиливают что все библиотеки, шрифты и железо, сделаны для решения вопросов разработчика. И в большинстве случаев представляет из себя набор костыликов который хоть как то но работает и решает узко поставленую задачу.. И что никто не собираеться перерабатывать эту кучу костыликов что бы кому то там еще стало приятно... :)
Согласен.
Давайте подумаем как это сделать. Только вот с масшабированием и форматом 5х8, или 6х9 иконок я бы подумал. Хоть они и масипусинькие, но если испоьлзовать их как колонтиум с последующим увеличением в два раза, то будет стильно. И еще вопрос, можно увеличить шрифт в четыре раза? Этакий SyperBig? Это даст еще больший прирост творчества. :)
Вот в этом как раз и проблема. Большинство ( ака товарищ просящий прибить латиницу)
Тамбовский волк тебе товарищъ. Даже не сомневаюсь, что у тебя, деревня все работает через кол да бревно. Лично у меня все шепчет как швейцарские часики. Видно, что у тебя опыта маловато и способностей никаких для творчества, потому ты и отираешься на форумах для подбирания чужих идей и кодов.
Вот в этом как раз и проблема. Большинство ( ака товарищ просящий прибить латиницу)
Тамбовский волк тебе товарищъ. Даже не сомневаюсь, что у тебя, деревня все работает через кол да бревно. Лично у меня все шепчет как швейцарские часики. Видно, что у тебя опыта маловато и способностей никаких для творчества, потому ты и отираешься на форумах для подбирания чужих идей и кодов.
и что же вы не поделились с сообществом своим шепотом швейцарских часиков? Где оно? где ваши библиотеки разработаные с нуля?
Вот в этом как раз и проблема. Большинство ( ака товарищ просящий прибить латиницу)
Тамбовский волк тебе товарищъ. Даже не сомневаюсь, что у тебя, деревня все работает через кол да бревно. Лично у меня все шепчет как швейцарские часики. Видно, что у тебя опыта маловато и способностей никаких для творчества, потому ты и отираешься на форумах для подбирания чужих идей и кодов.
и что же вы не поделились с сообществом своим шепотом швейцарских часиков? Где оно? где ваши библиотеки разработаные с нуля?
Я же говорил. Пасется деревня на халяву. А сам то всех халявщиками обзывает, халявщик.
Сходите в наш деревенский проект и попробуйте найти в нем что нибудь с форума.
http://arduino.ru/forum/proekty/vklyuchatel-vyklyuchatel-s-mozgom-i-orga...
Согласен.
Давайте подумаем как это сделать. Только вот с масшабированием и форматом 5х8, или 6х9 иконок я бы подумал. Хоть они и масипусинькие, но если испоьлзовать их как колонтиум с последующим увеличением в два раза, то будет стильно. И еще вопрос, можно увеличить шрифт в четыре раза? Этакий SyperBig? Это даст еще больший прирост творчества. :)
Иконок 6х9 в данном проекте не будет никогда. Т.к. для этого необходим экранный буфер, что явно противоречит идее минимизации расхода оперативной памяти.
Поэтому все вертикальные размеры кратны 8.
Идея масштабировать иконки мне как-то не нравится. Смволов - около 170, используешь ты их или нет, они занимают чуть меньше Кбайта, а если использовать "родной" шрифт 12х16, это потянет килобайта на 3.5. А иконок в проекте от 0 до ... ну, максимум, десятка. Ну пойдет на все про все 1/4 Кбайта - зато края будут не зазубренные.
Шрифт в принципе можно увеличить и в 4 и в 8 раз. В первом случае будет 2 строки по 5 символов, во втором - 2 символа на весь экран. Оно кому-то надо?
В принципе, можно было бы написать универсальную процедуру, масштабирующую фонт в заданное количество раз, но... сейчас в библиотеке строка удвоенного шрифта выводится не посимвольно, а сначала вся верхняя половина строки, а потом - вся нижняя. Сделано это с точки зрения оптимизации по времени. Даже при работе I2C на частоте 400 КГц заполнение экрана при условии оптимального программирования занимает примерно 120 мс. Если допускать неоптимальность - время возрастает в 3-4 раза. Каждая из половин строки выводится своей процедурой. Если строка будет делиться по вертикали на 4 части, это усложнит логику работы, увеличит объем кода... да и степень угловатости шрифта превысит разумные пределы.
В общем, ничего бесплатного не бывает. Особенно в системах со столь ограниченным объемом памяти. Поэтому я думаю, что попытка "повысить универсальность", вероятнее всего, пойдет во вред.
Во всем необходимо соблюдать баланс. Правда, сам баланс может быть разным, особенно для двух разных классов проектов:
- проекты, в которых основная задача - что-то показать пользователю, а экран является центральным прибором,
- проекты, в которых основная роль выполняется моторами, приводами, датчиками, а экран играет роль лишь вспомогательного индикатора.
Так вот, моя библиотека сбалансирована именно для второго типа задач.
Здравствуйте! andriano. Собрал вашу библу, и попробывал в своем проекте. Пользорватся действительно удобнее но возникла сложность...
Суть в этом кусочке кода.
byte s = ((time - previousMillis) / 1000ul) % 60; byte m = (((time - previousMillis) / 1000ul) / 60ul) % 60; if (s > 0 || m > 0)Не компилируется когда вывожу на дисплей потому как ругается на невозможность конвертации типов.
Хотя с библиотекой adafruit_gfx работает без проблем. Но в ней нет русского...
Так вот у меня вопрос, возможно ли добавить возможность работать к BYTE как со STRING?
Прошу сильно не пинать я новичек в этом деле...
как временный костыль:
byte s = ((time - previousMillis) / 1000UL) % 60; byte m = (((time - previousMillis) / 1000UL) / 60ul) % 60; if (s > 0 || m > 0) { LD.printString_6x8((String)m, 0, 4); LD.printString_6x8((String)s, 10, 4); }Недавно получил SSD1306(OLED 128x64) - подключил, залил - работает.
Аналогично. Только либа OLED_I2C - чёто с чемто! отжирает 1к RAM под буфер, запрещает прерывания, и содержит кучу лишнего кода, например поддерживая програмный и аппаратный i2c в одной сборке.
Пришлось переписать, попутно разделив на два класса.
Один дает вывод текста без графики и буферов. Разные шрифты и масштабирование. По вертикали выравнивание текста постраничное.
Второй графика с использованием буфера только во время работы с канвой, при этом канва не весь экран, а заданый прямоугольник. Позиции прямоугольника по вертикали тоже привязаны к страничкам. В общем сделал учитывая аппаратные особенности. Ну и битмапы напрямую из PGM.
Ещё скролинг прилепить интересно.
а причем тут либа OLED_I2C? У andriano вроде либа зовется ASOLED.
см. вторую сылку стартоврго поста.
Кириллица на дисплее или что я делаю не так?
Честно говоря, мне самому кириллица как-то без особой надобности.
Но, почему-то, на форуме вокруг нее творятся страшные вещи.
Например, по ссылкам:
http://lesson.iarduino.ru/page/urok-8-russkiy-yazyk-na-oled-displee-128x64/
http://arduino-project.net/russkie-ukrainskie-shrifty-oled-i2c/
предлагают использовать ее следующим образом.
Допустим, все библиотеки, шрифты и т.п. скачаны и установлены, переходим к программированию.
Скажем, нужно вывести на экран фразу "Моя Arduino сгорела.". Оказывается, что просто так это сделать нельзя. Следует:
- установить русский фонт,
- вывести "Моя " с нужного места экрана,
- теперь переключить фонт на английский,
- посчитать, сколько символов занимает первая надпись,
- вывести строку с учетом указанного смещения,
- вывести строку "Arduino ",
- снова переключить фонт - обратно на русский,
- снова посчитать смещение,
- вывести "сгорела."
Мало того, при наборе строк "Моя " и "сгорела." нужно переключить клавиатуру в латинскую раскладку, но набирать, глядя на русские надписи на клавиатуре.
Что при этом будет на экране - сложно представить.
А чтобы потом самому не запутаться в коде, рекомендуется дублировать надписи в комментариях - теперь уже в нормальной кодировке.
То есть это должно выглядеть примерно так:
myOLED.setFont(RusFont); myOLED.print("Vjz ", 0, 3); // Выводим надпись "Моя " myOLED.setFont(LatFont); myOLED.print("Arduino ", 4, 3); // Выводим надпись "Arduino " myOLED.setFont(RusFont); myOLED.print("cujhtkf/", 12, 3); // Выводим надпись "сгорела."Я лично делаю так:
LD.printString6("0123456789!\"#$%&'()*+", 0, 0, 21); LD.printString6(",-./:;<=>?@[\\]^_`{|}~", 0, 1, 21); LD.printString6("ABCDEFGHIJKLMNOPQRSTU", 0, 2, 21); LD.printString6("VWXYZabcdefghijklmnop",0, 3, 21); LD.printString6("qrstuvwxyzАБВГДЕЁЖЗИЙ", 0, 4, 21); LD.printString6("КЛМНОПРСТУФХЦЧШЩЪЫЬЭЮ", 0, 5, 21); LD.printString6("Яабвгдеёжзийклмнопрст", 0, 6, 21); LD.printString6("уфхцчшщъыьэюяЇїЎў§°±µ", 0, 7, 21);и получаю на экране:
При этом моя IDE, как и положено, работает в utf-8.
Что я делаю неправильно?
Все гараздо проще. Идем в настройки IDE arduino, меняем значение "preproc.substitute_unicode=false", сохраняем. Потом создаем файл фонт на 255 символов беря за основу таблицу windows cir. Пользуемся. Любят русские люди создавать себе проблеммы. А все гараздо проще. у меня так работает с библиотекой для tft от adafruit.
Все гараздо проще. Идем в настройки IDE arduino, меняем значение "preproc.substitute_unicode=false", сохраняем. Потом создаем файл фонт на 255 символов беря за основу таблицу windows cir. Пользуемся. Любят русские люди создавать себе проблеммы. А все гараздо проще. у меня так работает с библиотекой для tft от adafruit.
Похоже не все там так просто. И не от библиотеки зависит.
Вы имеете в виду файл ..\arduino-ххх\lib\preferences.txt и строки в нем должны выглядеть так
# auto-convert non-ascii chars to unicode escape sequences
preproc.substitute_unicode = false
Я и ранее пробовал так делать, и сейчас попробовал ещё раз. Не помогает.
Строка в скетче TestOLED выглядит
myOLED.drawString(1,1,"П",2);
в файле TestOLED.cpp после преобразования
myOLED.drawString(1,1,"\u041f",2);
Как видим опция не отключилась и символ конвертировался. IDE перезапускал конечно.
И на экране получаетсядва символа вида "Pf"
На какой версии у Вас работает? Я пробовал на версии 1.0.6.
Сам решил проблему так. Делаю файл, например resorce.inc, в него пишу в блокноте в кодировке Windows типа #define RUS_TEXT "краказябры! ". В скетче #include "resorce.inc" и может потребоватся путь указать. В нужном месте myOLED.drawString(5,7,RUS_TEXT,0); Все нормалек, до "resorce.inc" препроцессор не дотягивается.
Возможно вы вносите изменеия в файл preferences не выходя из IDE arduino. В таком случае изменения не сохраняются. Если у вас контролер tft из списка поддерживаемых библиотекой adafruit, скачайте у меня библиотеку и файл фонт http://178.130.34.198/adafruit
Все гараздо проще. Идем в настройки IDE arduino, меняем значение "preproc.substitute_unicode=false", сохраняем. Потом создаем файл фонт на 255 символов беря за основу таблицу windows cir. Пользуемся. Любят русские люди создавать себе проблеммы. А все гараздо проще. у меня так работает с библиотекой для tft от adafruit.
Да, скажу более: такой путь является более экономным по используемой памяти. Но мне кажется, это - не для новичка. Менять настройки IDE (причем не из самой IDE, а править конфигурационный файл), терять совместимость с уже имеющимися скетчами ... Ну а для "не новичка", сам вопрос необходимости кириллицы вызывает некоторый сомнения.
В общем, для меня вопрос стоял только так: "с неизменными настройками IDE".
Возможно вы вносите изменеия в файл preferences не выходя из IDE arduino. В таком случае изменения не сохраняются.
PS. Да, я тут пока отлаживал обмен по I2C между двумя Arduino, выяснил, что я все-таки реализовал не самый быстрый способ вывода на экран. Так что, когда дойдут руки, попытаюсь заметно ускорить вывод текста.
Все гараздо проще. Идем в настройки IDE arduino, меняем значение "preproc.substitute_unicode=false", сохраняем. Потом создаем файл фонт на 255 символов беря за основу таблицу windows cir. Пользуемся. Любят русские люди создавать себе проблеммы. А все гараздо проще. у меня так работает с библиотекой для tft от adafruit.
Да, скажу более: такой путь является более экономным по используемой памяти. Но мне кажется, это - не для новичка. Менять настройки IDE (причем не из самой IDE, а править конфигурационный файл), терять совместимость с уже имеющимися скетчами ... Ну а для "не новичка", сам вопрос необходимости кириллицы вызывает некоторый сомнения.
В общем, для меня вопрос стоял только так: "с неизменными настройками IDE".
Возможно вы вносите изменеия в файл preferences не выходя из IDE arduino. В таком случае изменения не сохраняются.
PS. Да, я тут пока отлаживал обмен по I2C между двумя Arduino, выяснил, что я все-таки реализовал не самый быстрый способ вывода на экран. Так что, когда дойдут руки, попытаюсь заметно ускорить вывод текста.
Менять настройки IDE можно и не выходя, а вот сохранять только выйдя из IDE. Предлогаемая настройка среды разработки подразумевает только допустимость использовать стандартный набор ACII кодировки, т.е. беззнаковое 255 символов таблица. На скетчи, их содержимое и компиляцию воздействия не производит.
PS. Кстати, "стандартный набор ACII кодировки" - это 128 символов (из которых 33 служебных), а не 255.
Посмотрти вот эту статью по руссификации
http://robocraft.ru/blog/892.html .
Посмотрти вот эту статью по руссификации
http://robocraft.ru/blog/892.html .
Ошибка: 404
К сожалению, такой страницы не существует. Вероятно, она была удалена с сервера, либо ее здесь никогда не было.
Вернуться назад, перейти на главную