Загрузил(а) файлы в 'OLED-I2C'
This commit is contained in:
parent
d86ced9a9d
commit
8d1374de00
189
OLED-I2C/I2C.h
Normal file
189
OLED-I2C/I2C.h
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#ifndef I2C_h
|
||||||
|
#define I2C_h
|
||||||
|
|
||||||
|
// этот символ необходим для совместимости с Wire.h. его значение является максимумом для параметра uint8_t используемого в оригинальной библиотеке.
|
||||||
|
#define BUFFER_LENGTH 255
|
||||||
|
|
||||||
|
class I2CLIB {
|
||||||
|
public:
|
||||||
|
void begin(void); // инициализация шины
|
||||||
|
void setClock(uint32_t clock); // ручная установка частоты шины 31-900 kHz (в герцах)
|
||||||
|
void beginTransmission(uint8_t address); // открыть соединение (для записи данных)
|
||||||
|
uint8_t endTransmission(bool stop); // закрыть соединение , произвести stop или restart (по умолчанию - stop)
|
||||||
|
uint8_t endTransmission(void); // закрыть соединение , произвести stop
|
||||||
|
size_t write(uint8_t data); // отправить в шину байт данных , отправка производится сразу , формат - byte "unsigned char"
|
||||||
|
uint8_t requestFrom(uint8_t address , uint8_t length , bool stop); //открыть соединение и запросить данные от устройства, отпустить или удержать шину
|
||||||
|
uint8_t requestFrom(uint8_t address , uint8_t length); //открыть соединение и запросить данные от устройства, отпустить шину
|
||||||
|
uint8_t read(void); // прочитать байт , БУФЕРА НЕТ!!! , читайте сразу все запрошенные байты , stop или restart после чтения последнего байта, настраивается в requestFrom
|
||||||
|
uint8_t available(void); // вернет количество оставшихся для чтения байт
|
||||||
|
// функции добавлены для совместимости с Wire API
|
||||||
|
inline void beginTransmission(int address){beginTransmission((uint8_t)address);}
|
||||||
|
uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop);
|
||||||
|
uint8_t requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop);
|
||||||
|
uint8_t requestFrom(int address, int quantity);
|
||||||
|
uint8_t requestFrom(int address, int quantity, int sendStop);
|
||||||
|
size_t write(const uint8_t *buffer, size_t size);
|
||||||
|
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(long n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||||
|
inline size_t write(int n) { return write((uint8_t)n); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t _requested_bytes = 0; // переменная хранит количество запрошенных и непрочитанных байт
|
||||||
|
bool _address_nack = false; // Флаг для отслеживания ошибки при передаче адреса
|
||||||
|
bool _data_nack = false; // Флаг для отслеживания ошибки при передаче данных
|
||||||
|
bool _stop_after_request = true; // stop или restart после чтения последнего байта
|
||||||
|
void start(void); // сервисная функция с нее начинается любая работа с шиной
|
||||||
|
void stop(void); // сервисная функция ей заканчивается работа с шиной
|
||||||
|
};
|
||||||
|
extern I2CLIB Wire;
|
||||||
|
|
||||||
|
void setPinMode(uint8_t pin, uint8_t mode) {
|
||||||
|
if (mode == INPUT) {
|
||||||
|
DDRD &= ~(1 << pin); // устанавливаем вход
|
||||||
|
} else {
|
||||||
|
DDRD |= (1 << pin); // устанавливаем выход
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CLIB::begin()
|
||||||
|
{ // Инициализация шины в роли master
|
||||||
|
setPinMode(SDA, INPUT_PULLUP); // Подтяжка шины
|
||||||
|
setPinMode(SCL, INPUT_PULLUP); // Подтяжка шины
|
||||||
|
TWBR = 72; // Стандартная скорость - 100kHz
|
||||||
|
TWSR = 0; // Делитель - /1 , статус - 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CLIB::setClock(uint32_t clock)
|
||||||
|
{ // Функция установки частоты шины 31-900 kHz (в герцах)
|
||||||
|
TWBR = (((long)F_CPU / clock) - 16) / 2; // Расчет baudrate - регистра
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CLIB::beginTransmission(uint8_t address)
|
||||||
|
{ // Начать передачу (для записи данных)
|
||||||
|
I2CLIB::start(); // Старт
|
||||||
|
I2CLIB::write(address << 1); // Отправка slave - устройству адреса с битом "write"
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::endTransmission(void)
|
||||||
|
{ // Завершить передачу и отпустить шину
|
||||||
|
return I2CLIB::endTransmission(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::endTransmission(bool stop)
|
||||||
|
{ // Завершить передачу (после записи данных)
|
||||||
|
if (stop) I2CLIB::stop(); // Если задано stop или аргумент пуст - отпустить шину
|
||||||
|
else I2CLIB::start(); // Иначе - restart (другой master на шине не сможет влезть между сообщениями)
|
||||||
|
if (_address_nack) { // Если нет ответа при передаче адреса
|
||||||
|
_address_nack = false; // Обнуляем оба флага
|
||||||
|
_data_nack = false; // Обнуляем оба флага
|
||||||
|
return 2; // Возвращаем '2'
|
||||||
|
} if (_data_nack) { // Если нет ответа при передаче данных
|
||||||
|
_address_nack = false; // Обнуляем оба флага
|
||||||
|
_data_nack = false; // Обнуляем оба флага
|
||||||
|
return 3; // Возвращаем '2'
|
||||||
|
} return 0; // Если все ОК - возвращаем '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t I2CLIB::write(uint8_t data)
|
||||||
|
{ // Прямая отправка байта на шину
|
||||||
|
TWDR = data; // Записать данные в data - регистр
|
||||||
|
TWCR = _BV(TWEN) | _BV(TWINT); // Запустить передачу
|
||||||
|
while (!(TWCR & _BV(TWINT))); // Дождаться окончания
|
||||||
|
uint8_t _bus_status = TWSR & 0xF8; // Чтение статуса шины
|
||||||
|
if(_bus_status == 0x20) _address_nack = true; // SLA + W + NACK ? - нет ответа при передаче адреса
|
||||||
|
if(_bus_status == 0x30) _data_nack = true; // BYTE + NACK ? - нет ответа при передаче данных
|
||||||
|
return 1; // для совместимости с Wire API
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::available()
|
||||||
|
{ // Вернуть оставшееся количество запрошенных для чтения байт
|
||||||
|
return _requested_bytes; // Это содержимое этой переменной
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::read()
|
||||||
|
{ // Прямое чтение байта из шины после запроса
|
||||||
|
if (--_requested_bytes) { // Если байт не последний
|
||||||
|
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Запустить чтение шины (с подтверждением "ACK")
|
||||||
|
while (!(TWCR & _BV(TWINT))); // Дождаться окончания приема данных
|
||||||
|
return TWDR; // Вернуть принятые данные , это содержимое data - регистра
|
||||||
|
}
|
||||||
|
_requested_bytes = 0; // Если читаем последний байт
|
||||||
|
TWCR = _BV(TWEN) | _BV(TWINT); // Запустить чтение шины (БЕЗ подтверждения "NACK")
|
||||||
|
while (!(TWCR & _BV(TWINT))); // Дождаться окончания приема данных
|
||||||
|
if (_stop_after_request) I2CLIB::stop(); // Если в requestFrom не задан аргумент stop , или stop задан как true - отпустить шину
|
||||||
|
else I2CLIB::start(); // Иначе - restart (другой master на шине не сможет влезть между сообщениями)
|
||||||
|
return TWDR; // Вернуть принятый ранее байт из data - регистра
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::requestFrom(uint8_t address , uint8_t length)
|
||||||
|
{ // Запрос n-го кол-ва байт от ведомого устройства и отпускание шины
|
||||||
|
return I2CLIB::requestFrom(address , length , true);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::requestFrom(uint8_t address , uint8_t length , bool stop)
|
||||||
|
{ // Запрос n-го кол-ва байт от ведомого устройства (Читайте все байты сразу!!!)
|
||||||
|
_stop_after_request = stop; // stop или restart после чтения последнего байта
|
||||||
|
_requested_bytes = length; // Записать в переменную количество запрошенных байт
|
||||||
|
I2CLIB::start(); // Начать работу на шине
|
||||||
|
I2CLIB::write((address << 1) | 0x1); // Отправить устройству адрес + бит "read"
|
||||||
|
return length; // вернуть длину сообщения для совместимости с оригинальной Wire API
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop){
|
||||||
|
return requestFrom(address , quantity , sendStop!=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop){
|
||||||
|
if (isize > 0) {
|
||||||
|
// send internal address; this mode allows sending a repeated start to access
|
||||||
|
// some devices' internal registers. This function is executed by the hardware
|
||||||
|
// TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers)
|
||||||
|
|
||||||
|
beginTransmission(address);
|
||||||
|
|
||||||
|
// the maximum size of internal address is 4 bytes
|
||||||
|
// не понятно почему ограничение размерности регистра в оригинальной Wire API в 3 байта
|
||||||
|
if (isize > 4){
|
||||||
|
isize = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write internal register address - most significant byte first
|
||||||
|
while (isize-- > 0)
|
||||||
|
write((uint8_t)(iaddress >> (isize*8)));
|
||||||
|
endTransmission(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestFrom(address, quantity, sendStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::requestFrom(int address, int quantity)
|
||||||
|
{
|
||||||
|
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t I2CLIB::requestFrom(int address, int quantity, int sendStop)
|
||||||
|
{
|
||||||
|
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t I2CLIB::write(const uint8_t *buffer, size_t size){
|
||||||
|
for (size_t i = 0 ; i < size; ++i)
|
||||||
|
write(buffer[i]);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CLIB::start()
|
||||||
|
{ // сервисная функция с нее начинается любая работа с шиной
|
||||||
|
TWCR = _BV(TWSTA) | _BV(TWEN) | _BV(TWINT); // start + I2CLIB enable + установка флага "выполнить задачу"
|
||||||
|
while (!(TWCR & _BV(TWINT))); // Ожидание завершения
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CLIB::stop()
|
||||||
|
{ // сервисная функция ей заканчивается работа с шиной
|
||||||
|
TWCR = _BV(TWSTO) | _BV(TWEN) | _BV(TWINT); // stop + I2CLIB enable + установка флага "выполнить задачу"
|
||||||
|
}
|
||||||
|
|
||||||
|
I2CLIB Wire = I2CLIB();
|
||||||
|
|
||||||
|
#endif
|
979
OLED-I2C/OLEDI2C.h
Normal file
979
OLED-I2C/OLEDI2C.h
Normal file
@ -0,0 +1,979 @@
|
|||||||
|
|
||||||
|
#ifndef OLEDI2C_h
|
||||||
|
#define OLEDI2C_h
|
||||||
|
|
||||||
|
// ===== константы =====
|
||||||
|
#define SSD1306_128x32 0
|
||||||
|
#define SSD1306_128x64 1
|
||||||
|
#define SSH1106_128x64 2
|
||||||
|
|
||||||
|
#define OLED_I2C 0
|
||||||
|
#define OLED_SPI 1
|
||||||
|
|
||||||
|
#define OLED_NO_BUFFER 0
|
||||||
|
#define OLED_BUFFER 1
|
||||||
|
|
||||||
|
#define OLED_CLEAR 0
|
||||||
|
#define OLED_FILL 1
|
||||||
|
#define OLED_STROKE 2
|
||||||
|
|
||||||
|
#define BUF_ADD 0
|
||||||
|
#define BUF_SUBTRACT 1
|
||||||
|
#define BUF_REPLACE 2
|
||||||
|
|
||||||
|
#define BITMAP_NORMAL 0
|
||||||
|
#define BITMAP_INVERT 1
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
#include "I2C.h" // лёгкая библиотека Wire (для atmega328)
|
||||||
|
#include "charMap.h"
|
||||||
|
|
||||||
|
#ifndef OLED_NO_PRINT
|
||||||
|
#include <Print.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ============================ БЭКЭНД КОНСТАНТЫ ==============================
|
||||||
|
// внутренние константы
|
||||||
|
#define OLED_WIDTH 128
|
||||||
|
#define OLED_HEIGHT_32 0x02
|
||||||
|
#define OLED_HEIGHT_64 0x12
|
||||||
|
#define OLED_64 0x3F
|
||||||
|
#define OLED_32 0x1F
|
||||||
|
|
||||||
|
#define OLED_DISPLAY_OFF 0xAE
|
||||||
|
#define OLED_DISPLAY_ON 0xAF
|
||||||
|
|
||||||
|
#define OLED_COMMAND_MODE 0x00
|
||||||
|
#define OLED_ONE_COMMAND_MODE 0x80
|
||||||
|
#define OLED_DATA_MODE 0x40
|
||||||
|
#define OLED_ONE_DATA_MODE 0xC0
|
||||||
|
|
||||||
|
#define OLED_ADDRESSING_MODE 0x20
|
||||||
|
#define OLED_HORIZONTAL 0x00
|
||||||
|
#define OLED_VERTICAL 0x01
|
||||||
|
|
||||||
|
#define OLED_NORMAL_V 0xC8
|
||||||
|
#define OLED_FLIP_V 0xC0
|
||||||
|
#define OLED_NORMAL_H 0xA1
|
||||||
|
#define OLED_FLIP_H 0xA0
|
||||||
|
|
||||||
|
#define OLED_CONTRAST 0x81
|
||||||
|
#define OLED_SETCOMPINS 0xDA
|
||||||
|
#define OLED_SETVCOMDETECT 0xDB
|
||||||
|
#define OLED_CLOCKDIV 0xD5
|
||||||
|
#define OLED_SETMULTIPLEX 0xA8
|
||||||
|
#define OLED_COLUMNADDR 0x21
|
||||||
|
#define OLED_PAGEADDR 0x22
|
||||||
|
#define OLED_CHARGEPUMP 0x8D
|
||||||
|
|
||||||
|
#define OLED_NORMALDISPLAY 0xA6
|
||||||
|
#define OLED_INVERTDISPLAY 0xA7
|
||||||
|
|
||||||
|
#define BUFSIZE_128x64 (128 * 64 / 8)
|
||||||
|
#define BUFSIZE_128x32 (128 * 32 / 8)
|
||||||
|
|
||||||
|
#ifndef OLED_SPI_SPEED
|
||||||
|
#define OLED_SPI_SPEED 1000000ul
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//static SPISettings OLED_SPI_SETT(OLED_SPI_SPEED, MSBFIRST, SPI_MODE0);
|
||||||
|
|
||||||
|
// список инициализации
|
||||||
|
static const uint8_t _oled_init[] PROGMEM = {
|
||||||
|
OLED_DISPLAY_OFF,
|
||||||
|
OLED_CLOCKDIV,
|
||||||
|
0x80, // value
|
||||||
|
OLED_CHARGEPUMP,
|
||||||
|
0x14, // value
|
||||||
|
OLED_ADDRESSING_MODE,
|
||||||
|
OLED_VERTICAL,
|
||||||
|
OLED_NORMAL_H,
|
||||||
|
OLED_NORMAL_V,
|
||||||
|
OLED_CONTRAST,
|
||||||
|
0x7F, // value
|
||||||
|
OLED_SETVCOMDETECT,
|
||||||
|
0x40, // value
|
||||||
|
OLED_NORMALDISPLAY,
|
||||||
|
OLED_DISPLAY_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ========================== КЛАСС КЛАСС КЛАСС =============================
|
||||||
|
template<int _TYPE, int _BUFF = OLED_BUFFER, int _CONN = OLED_I2C, int8_t _CS = -1, int8_t _DC = -1, int8_t _RST = -1 >
|
||||||
|
#ifndef OLED_NO_PRINT
|
||||||
|
class OLEDI2C : public Print {
|
||||||
|
#else
|
||||||
|
class OLEDI2C {
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
// ========================== КОНСТРУКТОР =============================
|
||||||
|
OLEDI2C(uint8_t address = 0x3C)
|
||||||
|
: _address(address) {}
|
||||||
|
|
||||||
|
// ============================= СЕРВИС ===============================
|
||||||
|
// инициализация
|
||||||
|
void init(int __attribute__((unused)) sda = 0, int __attribute__((unused)) scl = 0) {
|
||||||
|
#if defined(ESP32) || defined(ESP8266)
|
||||||
|
if (sda || scl) Wire.begin(sda, scl);
|
||||||
|
else Wire.begin();
|
||||||
|
#else
|
||||||
|
Wire.begin();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
beginCommand();
|
||||||
|
for (uint8_t i = 0; i < 15; i++) sendByte(pgm_read_byte(&_oled_init[i]));
|
||||||
|
endTransm();
|
||||||
|
beginCommand();
|
||||||
|
sendByte(OLED_SETCOMPINS);
|
||||||
|
sendByte(_TYPE ? OLED_HEIGHT_64 : OLED_HEIGHT_32);
|
||||||
|
sendByte(OLED_SETMULTIPLEX);
|
||||||
|
sendByte(_TYPE ? OLED_64 : OLED_32);
|
||||||
|
endTransm();
|
||||||
|
|
||||||
|
setCursorXY(0, 0);
|
||||||
|
if (_BUFF) setWindow(0, 0, _maxX, _maxRow); // для буфера включаем всю область
|
||||||
|
}
|
||||||
|
|
||||||
|
// очистить дисплей
|
||||||
|
void clear() {
|
||||||
|
fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// очистить область
|
||||||
|
void clear(int x0, int y0, int x1, int y1) {
|
||||||
|
if (_TYPE < 2) { // для SSD1306
|
||||||
|
if (_BUFF) rect(x0, y0, x1, y1, OLED_CLEAR);
|
||||||
|
else {
|
||||||
|
x1++;
|
||||||
|
y1++;
|
||||||
|
y0 >>= 3;
|
||||||
|
y1 = (y1 - 1) >> 3;
|
||||||
|
y0 = constrain(y0, 0, _maxRow);
|
||||||
|
y1 = constrain(y1, 0, _maxRow);
|
||||||
|
x0 = constrain(x0, 0, _maxX);
|
||||||
|
x1 = constrain(x1, 0, _maxX);
|
||||||
|
setWindow(x0, y0, x1, y1);
|
||||||
|
beginData();
|
||||||
|
for (int x = x0; x < x1; x++)
|
||||||
|
for (int y = y0; y < y1 + 1; y++)
|
||||||
|
writeData(0, y, x, 2);
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// для SSH1108
|
||||||
|
}
|
||||||
|
setCursorXY(_x, _y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// яркость 0-255
|
||||||
|
void setContrast(uint8_t value) {
|
||||||
|
sendCommand(OLED_CONTRAST, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// вкл/выкл
|
||||||
|
void setPower(bool mode) {
|
||||||
|
sendCommand(mode ? OLED_DISPLAY_ON : OLED_DISPLAY_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// отразить по горизонтали
|
||||||
|
void flipH(bool mode) {
|
||||||
|
sendCommand(mode ? OLED_FLIP_H : OLED_NORMAL_H);
|
||||||
|
}
|
||||||
|
|
||||||
|
// инвертировать дисплей
|
||||||
|
void invertDisplay(bool mode) {
|
||||||
|
sendCommand(mode ? OLED_INVERTDISPLAY : OLED_NORMALDISPLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// отразить по вертикали
|
||||||
|
void flipV(bool mode) {
|
||||||
|
sendCommand(mode ? OLED_FLIP_V : OLED_NORMAL_V);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================= ПЕЧАТЬ ==================================
|
||||||
|
virtual size_t write(uint8_t data) {
|
||||||
|
#ifndef OLED_NO_PRINT
|
||||||
|
// переносы и пределы
|
||||||
|
bool newPos = false;
|
||||||
|
if (data == '\r') {
|
||||||
|
_x = 0;
|
||||||
|
newPos = true;
|
||||||
|
data = 0;
|
||||||
|
} // получен возврат каретки
|
||||||
|
if (data == '\n') {
|
||||||
|
_y += _scaleY;
|
||||||
|
newPos = true;
|
||||||
|
data = 0;
|
||||||
|
_getn = 1;
|
||||||
|
} // получен перевод строки
|
||||||
|
if (_println && (_x + 6 * _scaleX) >= _maxX) {
|
||||||
|
_x = 0;
|
||||||
|
_y += _scaleY;
|
||||||
|
newPos = true;
|
||||||
|
} // строка переполненена, перевод и возврат
|
||||||
|
if (newPos) setCursorXY(_x, _y); // переставляем курсор
|
||||||
|
if (_y + _scaleY > _maxY + 1) data = 0; // дисплей переполнен
|
||||||
|
if (_getn && _println && data == ' ' && _x == 0) {
|
||||||
|
_getn = 0;
|
||||||
|
data = 0;
|
||||||
|
} // убираем первый пробел в строке
|
||||||
|
|
||||||
|
// фикс русских букв и некоторых символов
|
||||||
|
if (data > 127) {
|
||||||
|
uint8_t thisData = data;
|
||||||
|
// data = 0 - флаг на пропуск
|
||||||
|
if (data > 191) data = 0;
|
||||||
|
else if (_lastChar == 209 && data == 145) data = 192; // ё кастомная
|
||||||
|
else if (_lastChar == 208 && data == 129) data = 149; // Е вместо Ё
|
||||||
|
else if (_lastChar == 226 && data == 128) data = 0; // тире вместо длинного тире (начало)
|
||||||
|
else if (_lastChar == 128 && data == 148) data = 45; // тире вместо длинного тире
|
||||||
|
_lastChar = thisData;
|
||||||
|
}
|
||||||
|
if (data == 0) return 1;
|
||||||
|
// если тут не вылетели - печатаем символ
|
||||||
|
|
||||||
|
if (_TYPE < 2 || 1) { // для SSD1306
|
||||||
|
int newX = _x + _scaleX * 6;
|
||||||
|
if (newX < 0 || _x > _maxX) _x = newX; // пропускаем вывод "за экраном"
|
||||||
|
else {
|
||||||
|
if (!_BUFF) beginData();
|
||||||
|
for (uint8_t col = 0; col < 6; col++) { // 6 стобиков буквы
|
||||||
|
uint8_t bits = getFont(data, col); // получаем байт
|
||||||
|
if (_invState) bits = ~bits; // инверсия
|
||||||
|
if (_scaleX == 1) { // если масштаб 1
|
||||||
|
if (_x >= 0 && _x <= _maxX) { // внутри дисплея
|
||||||
|
if (_shift == 0) { // если вывод без сдвига на строку
|
||||||
|
writeData(bits, 0, 0, _mode); // выводим
|
||||||
|
} else { // со сдвигом
|
||||||
|
writeData(bits << _shift, 0, 0, _mode); // верхняя часть
|
||||||
|
writeData(bits >> (8 - _shift), 1, 0, _mode); // нижняя часть
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // масштаб 2, 3 или 4 - растягиваем шрифт
|
||||||
|
uint32_t newData = 0; // буфер
|
||||||
|
for (uint8_t i = 0, count = 0; i < 8; i++)
|
||||||
|
for (uint8_t j = 0; j < _scaleX; j++, count++)
|
||||||
|
bitWrite(newData, count, bitRead(bits, i)); // пакуем растянутый шрифт
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < _scaleX; i++) { // выводим. По Х
|
||||||
|
byte prevData = 0;
|
||||||
|
if (_x + i >= 0 && _x + i <= _maxX) // внутри дисплея
|
||||||
|
for (uint8_t j = 0; j < _scaleX; j++) { // выводим. По Y
|
||||||
|
byte data = newData >> (j * 8); // получаем кусок буфера
|
||||||
|
if (_shift == 0) { // если вывод без сдвига на строку
|
||||||
|
writeData(data, j, i, _mode); // выводим
|
||||||
|
} else { // со сдвигом
|
||||||
|
writeData((prevData >> (8 - _shift)) | (data << _shift), j, i, _mode); // склеиваем и выводим
|
||||||
|
prevData = data; // запоминаем предыдущий
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_shift != 0) writeData(prevData >> (8 - _shift), _scaleX, i, _mode); // выводим нижний кусочек, если со сдвигом
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_x += _scaleX; // двигаемся на ширину пикселя (1-4)
|
||||||
|
}
|
||||||
|
if (!_BUFF) endTransm();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// для SSH1106
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// автоматически переносить текст
|
||||||
|
void autoPrintln(bool mode) {
|
||||||
|
_println = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// отправить курсор в 0,0
|
||||||
|
void home() {
|
||||||
|
setCursorXY(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// поставить курсор для символа 0-127, 0-8(4)
|
||||||
|
void setCursor(int x, int y) {
|
||||||
|
setCursorXY(x, y << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// поставить курсор для символа 0-127, 0-63(31)
|
||||||
|
void setCursorXY(int x, int y) {
|
||||||
|
_x = x;
|
||||||
|
_y = y;
|
||||||
|
setWindowShift(x, y, _maxX, _scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// масштаб шрифта (1-4)
|
||||||
|
void setScale(uint8_t scale) {
|
||||||
|
scale = constrain(scale, 1, 4); // защита от нечитающих доку
|
||||||
|
_scaleX = scale;
|
||||||
|
_scaleY = scale * 8;
|
||||||
|
setCursorXY(_x, _y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// инвертировать текст (0-1)
|
||||||
|
void invertText(bool inv) {
|
||||||
|
_invState = inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void textMode(byte mode) {
|
||||||
|
_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// возвращает true, если дисплей "кончился" - при побуквенном выводе
|
||||||
|
bool isEnd() {
|
||||||
|
return (_y > _maxRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================== ГРАФИКА ==================================
|
||||||
|
// точка (заливка 1/0)
|
||||||
|
void dot(int x, int y, byte fill = 1) {
|
||||||
|
if (x < 0 || x > _maxX || y < 0 || y > _maxY) return;
|
||||||
|
_x = 0;
|
||||||
|
_y = 0;
|
||||||
|
if (_BUFF) {
|
||||||
|
bitWrite(_oled_buffer[_bufIndex(x, y)], y & 0b111, fill);
|
||||||
|
} else {
|
||||||
|
if (!_buf_flag) {
|
||||||
|
setWindow(x, y >> 3, _maxX, _maxRow);
|
||||||
|
beginData();
|
||||||
|
sendByte(1 << (y & 0b111)); // задвигаем 1 на высоту y
|
||||||
|
endTransm();
|
||||||
|
} else {
|
||||||
|
x -= _bufX;
|
||||||
|
y -= _bufY;
|
||||||
|
if (x < 0 || x > _bufsizeX || y < 0 || y > (_bufsizeY << 3)) return;
|
||||||
|
bitWrite(_buf_ptr[(y >> 3) + x * _bufsizeY], y & 0b111, fill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// линия
|
||||||
|
void line(int x0, int y0, int x1, int y1, byte fill = 1) {
|
||||||
|
_x = 0;
|
||||||
|
_y = 0;
|
||||||
|
if (x0 == x1) fastLineV(x0, y0, y1, fill);
|
||||||
|
else if (y0 == y1) fastLineH(y0, x0, x1, fill);
|
||||||
|
else {
|
||||||
|
int sx, sy, e2, err;
|
||||||
|
int dx = abs(x1 - x0);
|
||||||
|
int dy = abs(y1 - y0);
|
||||||
|
sx = (x0 < x1) ? 1 : -1;
|
||||||
|
sy = (y0 < y1) ? 1 : -1;
|
||||||
|
err = dx - dy;
|
||||||
|
for (;;) {
|
||||||
|
dot(x0, y0, fill);
|
||||||
|
if (x0 == x1 && y0 == y1) return;
|
||||||
|
e2 = err << 1;
|
||||||
|
if (e2 > -dy) {
|
||||||
|
err -= dy;
|
||||||
|
x0 += sx;
|
||||||
|
}
|
||||||
|
if (e2 < dx) {
|
||||||
|
err += dx;
|
||||||
|
y0 += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// горизонтальная линия
|
||||||
|
void fastLineH(int y, int x0, int x1, byte fill = 1) {
|
||||||
|
_x = 0;
|
||||||
|
_y = 0;
|
||||||
|
if (x0 > x1) _swap(x0, x1);
|
||||||
|
if (y < 0 || y > _maxY) return;
|
||||||
|
if (x0 == x1) {
|
||||||
|
dot(x0, y, fill);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
x1++;
|
||||||
|
x0 = constrain(x0, 0, _maxX);
|
||||||
|
x1 = constrain(x1, 0, _maxX);
|
||||||
|
if (_BUFF) {
|
||||||
|
for (int x = x0; x < x1; x++) dot(x, y, fill);
|
||||||
|
} else {
|
||||||
|
if (_buf_flag) {
|
||||||
|
for (int x = x0; x < x1; x++) dot(x, y, fill);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte data = 0b1 << (y & 0b111);
|
||||||
|
y >>= 3;
|
||||||
|
setWindow(x0, y, x1, y);
|
||||||
|
beginData();
|
||||||
|
for (int x = x0; x < x1; x++) writeData(data, y, x);
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// вертикальная линия
|
||||||
|
void fastLineV(int x, int y0, int y1, byte fill = 1) {
|
||||||
|
_x = 0;
|
||||||
|
_y = 0;
|
||||||
|
if (y0 > y1) _swap(y0, y1);
|
||||||
|
if (x < 0 || x > _maxX) return;
|
||||||
|
if (y0 == y1) {
|
||||||
|
dot(x, y0, fill);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y1++;
|
||||||
|
if (_BUFF) {
|
||||||
|
for (int y = y0; y < y1; y++) dot(x, y, fill);
|
||||||
|
} else {
|
||||||
|
if (_buf_flag) {
|
||||||
|
for (int y = y0; y < y1; y++) dot(x, y, fill);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fill) fill = 255;
|
||||||
|
byte shift = y0 & 0b111;
|
||||||
|
byte shift2 = 8 - (y1 & 0b111);
|
||||||
|
if (shift2 == 8) shift2 = 0;
|
||||||
|
int height = y1 - y0;
|
||||||
|
y0 >>= 3;
|
||||||
|
y1 = (y1 - 1) >> 3;
|
||||||
|
byte numBytes = y1 - y0;
|
||||||
|
setWindow(x, y0, x, y1);
|
||||||
|
|
||||||
|
beginData();
|
||||||
|
if (numBytes == 0) {
|
||||||
|
if (_inRange(y0, 0, _maxRow)) writeData((fill >> (8 - height)) << shift, y0, x);
|
||||||
|
} else {
|
||||||
|
if (_inRange(y0, 0, _maxRow)) writeData(fill << shift, y0, x); // начальный кусок
|
||||||
|
y0++;
|
||||||
|
for (byte i = 0; i < numBytes - 1; i++, y0++)
|
||||||
|
if (_inRange(y0, 0, _maxRow)) writeData(fill, y0, x); // столбик
|
||||||
|
if (_inRange(y0, 0, _maxRow)) writeData(fill >> shift2, y0, x); // нижний кусок
|
||||||
|
}
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// прямоугольник (лев. верхн, прав. нижн)
|
||||||
|
void rect(int x0, int y0, int x1, int y1, byte fill = 1) {
|
||||||
|
_x = 0;
|
||||||
|
_y = 0;
|
||||||
|
if (x0 > x1) _swap(x0, x1);
|
||||||
|
if (y0 > y1) _swap(y0, y1);
|
||||||
|
if (fill == OLED_STROKE) {
|
||||||
|
fastLineH(y0, x0 + 1, x1 - 1);
|
||||||
|
fastLineH(y1, x0 + 1, x1 - 1);
|
||||||
|
fastLineV(x0, y0, y1);
|
||||||
|
fastLineV(x1, y0, y1);
|
||||||
|
} else {
|
||||||
|
if (x0 == x1 && y0 == y1) {
|
||||||
|
dot(x0, y0, fill);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (x0 == x1) {
|
||||||
|
fastLineV(x0, y0, y1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (y0 == y1) {
|
||||||
|
fastLineH(y0, x0, x1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!_BUFF && fill == OLED_CLEAR) {
|
||||||
|
clear(x0, y0, x1, y1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// если рисуем в мини-буфер
|
||||||
|
if (_buf_flag) {
|
||||||
|
x0 = constrain(x0, 0, _maxX);
|
||||||
|
x1 = constrain(x1, 0, _maxX);
|
||||||
|
for (byte x = x0; x <= x1; x++) fastLineV(x, y0, y1, fill == OLED_FILL ? 1 : 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte thisFill = (fill == OLED_FILL ? 0 : 1);
|
||||||
|
// рисуем в олед и в большой буфер
|
||||||
|
x1++;
|
||||||
|
y1++;
|
||||||
|
byte shift = y0 & 0b111;
|
||||||
|
byte shift2 = 8 - (y1 & 0b111);
|
||||||
|
if (shift2 == 8) shift2 = 0;
|
||||||
|
int height = y1 - y0;
|
||||||
|
y0 >>= 3;
|
||||||
|
y1 = (y1 - 1) >> 3;
|
||||||
|
byte numBytes = y1 - y0;
|
||||||
|
x0 = constrain(x0, 0, _maxX);
|
||||||
|
x1 = constrain(x1, 0, _maxX);
|
||||||
|
|
||||||
|
if (!_BUFF) setWindow(x0, y0, x1, y1);
|
||||||
|
if (!_BUFF) beginData();
|
||||||
|
for (byte x = x0; x < x1; x++) {
|
||||||
|
int y = y0;
|
||||||
|
if (numBytes == 0) {
|
||||||
|
if (_inRange(y, 0, _maxRow)) writeData((255 >> (8 - height)) << shift, y, x, thisFill);
|
||||||
|
} else {
|
||||||
|
if (_inRange(y, 0, _maxRow)) writeData(255 << shift, y, x, thisFill); // начальный кусок
|
||||||
|
y++;
|
||||||
|
for (byte i = 0; i < numBytes - 1; i++, y++)
|
||||||
|
if (_inRange(y, 0, _maxRow)) writeData(255, y, x, thisFill); // столбик
|
||||||
|
if (_inRange(y, 0, _maxRow)) writeData(255 >> shift2, y, x, thisFill); // нижний кусок
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_BUFF) endTransm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// прямоугольник скруглённый (лев. верхн, прав. нижн)
|
||||||
|
void roundRect(int x0, int y0, int x1, int y1, byte fill = OLED_FILL) {
|
||||||
|
if (fill == OLED_STROKE) {
|
||||||
|
fastLineV(x0, y0 + 2, y1 - 2);
|
||||||
|
fastLineV(x1, y0 + 2, y1 - 2);
|
||||||
|
fastLineH(y0, x0 + 2, x1 - 2);
|
||||||
|
fastLineH(y1, x0 + 2, x1 - 2);
|
||||||
|
dot(x0 + 1, y0 + 1);
|
||||||
|
dot(x1 - 1, y0 + 1);
|
||||||
|
dot(x1 - 1, y1 - 1);
|
||||||
|
dot(x0 + 1, y1 - 1);
|
||||||
|
} else {
|
||||||
|
fastLineV(x0, y0 + 2, y1 - 2, fill);
|
||||||
|
fastLineV(x0 + 1, y0 + 1, y1 - 1, fill);
|
||||||
|
fastLineV(x1 - 1, y0 + 1, y1 - 1, fill);
|
||||||
|
fastLineV(x1, y0 + 2, y1 - 2, fill);
|
||||||
|
rect(x0 + 2, y0, x1 - 2, y1, fill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// окружность (центр х, центр у, радиус, заливка)
|
||||||
|
void circle(int x, int y, int radius, byte fill = OLED_FILL) {
|
||||||
|
//if (!_BUFF) createBuffer(x - radius, y - radius, x + radius + 1, y + radius);
|
||||||
|
int f = 1 - radius;
|
||||||
|
int ddF_x = 1;
|
||||||
|
int ddF_y = -2 * radius;
|
||||||
|
int x1 = 0;
|
||||||
|
int y1 = radius;
|
||||||
|
|
||||||
|
byte fillLine = (fill == OLED_CLEAR) ? 0 : 1;
|
||||||
|
dot(x, y + radius, fillLine);
|
||||||
|
dot(x, y - radius, fillLine);
|
||||||
|
dot(x + radius, y, fillLine);
|
||||||
|
dot(x - radius, y, fillLine);
|
||||||
|
//if (fill != OLED_STROKE) fastLineH(y, x - radius, x + radius-1, fillLine);
|
||||||
|
if (fill != OLED_STROKE) fastLineV(x, y - radius, y + radius - 1, fillLine);
|
||||||
|
while (x1 < y1) {
|
||||||
|
if (f >= 0) {
|
||||||
|
y1--;
|
||||||
|
ddF_y += 2;
|
||||||
|
f += ddF_y;
|
||||||
|
}
|
||||||
|
x1++;
|
||||||
|
ddF_x += 2;
|
||||||
|
f += ddF_x;
|
||||||
|
if (fill == OLED_STROKE) {
|
||||||
|
dot(x + x1, y + y1);
|
||||||
|
dot(x - x1, y + y1);
|
||||||
|
dot(x + x1, y - y1);
|
||||||
|
dot(x - x1, y - y1);
|
||||||
|
dot(x + y1, y + x1);
|
||||||
|
dot(x - y1, y + x1);
|
||||||
|
dot(x + y1, y - x1);
|
||||||
|
dot(x - y1, y - x1);
|
||||||
|
} else { // FILL / CLEAR
|
||||||
|
|
||||||
|
fastLineV(x + x1, y - y1, y + y1, fillLine);
|
||||||
|
fastLineV(x - x1, y - y1, y + y1, fillLine);
|
||||||
|
fastLineV(x + y1, y - x1, y + x1, fillLine);
|
||||||
|
fastLineV(x - y1, y - x1, y + x1, fillLine);
|
||||||
|
/*
|
||||||
|
fastLineH(y + y1, x - x1, x + x1-1, fillLine);
|
||||||
|
fastLineH(y - y1, x - x1, x + x1-1, fillLine);
|
||||||
|
fastLineH(y + x1, x - y1, x + y1-1, fillLine);
|
||||||
|
fastLineH(y - x1, x - y1, x + y1-1, fillLine);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (!_BUFF) sendBuffer();
|
||||||
|
}
|
||||||
|
void bezier(int* arr, uint8_t size, uint8_t dense, uint8_t fill = 1) {
|
||||||
|
int a[size * 2];
|
||||||
|
for (int i = 0; i < (1 << dense); i++) {
|
||||||
|
for (int j = 0; j < size * 2; j++) a[j] = arr[j];
|
||||||
|
for (int j = (size - 1) * 2 - 1; j > 0; j -= 2)
|
||||||
|
for (int k = 0; k <= j; k++)
|
||||||
|
a[k] = a[k] + (((a[k + 2] - a[k]) * i) >> dense);
|
||||||
|
dot(a[0], a[1], fill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// вывести битмап
|
||||||
|
void drawBitmap(int x, int y, const uint8_t* frame, int width, int height, uint8_t invert = 0, byte mode = 0) {
|
||||||
|
_x = 0;
|
||||||
|
_y = 0;
|
||||||
|
if (invert) invert = 255;
|
||||||
|
byte left = height & 0b111;
|
||||||
|
if (left != 0) height += (8 - left); // округляем до ближайшего кратного степени 2
|
||||||
|
int shiftY = (y >> 3) + (height >> 3); // строка (row) крайнего байта битмапа
|
||||||
|
setWindowShift(x, y, width, height); // выделяем окно
|
||||||
|
bool bottom = (_shift != 0 && shiftY >= 0 && shiftY <= _maxRow); // рисовать ли нижний сдвинутый байт
|
||||||
|
|
||||||
|
if (!_BUFF) beginData();
|
||||||
|
for (int X = x, countX = 0; X < x + width; X++, countX++) { // в пикселях
|
||||||
|
byte prevData = 0;
|
||||||
|
if (_inRange(X, 0, _maxX)) { // мы внутри дисплея по X
|
||||||
|
for (int Y = y >> 3, countY = 0; Y < shiftY; Y++, countY++) { // в строках (пикс/8)
|
||||||
|
byte data = pgm_read_word(&(frame[countY * width + countX])) ^ invert; // достаём байт
|
||||||
|
if (_shift == 0) { // без сдвига по Y
|
||||||
|
if (_inRange(Y, 0, _maxRow)) writeData(data, Y, X, mode); // мы внутри дисплея по Y
|
||||||
|
} else { // со сдвигом по Y
|
||||||
|
if (_inRange(Y, 0, _maxRow)) writeData((prevData >> (8 - _shift)) | (data << _shift), Y, X, mode); // задвигаем
|
||||||
|
prevData = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bottom) writeData(prevData >> (8 - _shift), shiftY, X, mode); // нижний байт
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_BUFF) endTransm();
|
||||||
|
}
|
||||||
|
|
||||||
|
// залить весь дисплей указанным байтом
|
||||||
|
void fill(uint8_t data) {
|
||||||
|
if (_BUFF) memset(_oled_buffer, data, _bufSize);
|
||||||
|
else {
|
||||||
|
if (_TYPE < 2 || 1) { // для SSD1306
|
||||||
|
setWindow(0, 0, _maxX, _maxRow);
|
||||||
|
beginData();
|
||||||
|
for (int i = 0; i < (_TYPE ? 1024 : 512); i++) sendByte(data);
|
||||||
|
endTransm();
|
||||||
|
} else { // для SSH1108
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCursorXY(_x, _y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// шлёт байт в "столбик" setCursor() и setCursorXY()
|
||||||
|
void drawByte(uint8_t data) {
|
||||||
|
if (++_x > _maxX) return;
|
||||||
|
if (_TYPE < 2 || 1) { // для SSD1306
|
||||||
|
if (!_BUFF) beginData();
|
||||||
|
if (_shift == 0) { // если вывод без сдвига на строку
|
||||||
|
writeData(data); // выводим
|
||||||
|
} else { // со сдвигом
|
||||||
|
writeData(data << _shift); // верхняя часть
|
||||||
|
writeData(data >> (8 - _shift), 1); // нижняя часть со сдвигом на 1
|
||||||
|
}
|
||||||
|
if (!_BUFF) endTransm();
|
||||||
|
} else {
|
||||||
|
// для SSH1106
|
||||||
|
/*
|
||||||
|
int h = y & 0x07;
|
||||||
|
if (_BUFF) {
|
||||||
|
for (int p = 0; p < 2; p++) {
|
||||||
|
Wire.beginTransmission(_address);
|
||||||
|
continueCmd(0xB0 + (y >> 3) + p); // Page
|
||||||
|
continueCmd(0x00 + ((x + 2) & 0x0F)); // Column low nibble
|
||||||
|
continueCmd(0x10 + ((x + 2) >> 4)); // Column high nibble
|
||||||
|
continueCmd(0xE0); // Read modify write
|
||||||
|
Wire.write(OLED_ONE_DATA_MODE);
|
||||||
|
Wire.endTransmission();
|
||||||
|
Wire.requestFrom((int)_address, 2);
|
||||||
|
Wire.read(); // Dummy read
|
||||||
|
int j = Wire.read();
|
||||||
|
Wire.beginTransmission(_address);
|
||||||
|
Wire.write(OLED_ONE_DATA_MODE);
|
||||||
|
Wire.write((data << h) >> (p << 3) | j);
|
||||||
|
continueCmd(0xEE); // Cancel read modify write
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int p = 0; p < 2; p++) {
|
||||||
|
Wire.beginTransmission(_address);
|
||||||
|
continueCmd(0xB0 + (y >> 3) + p); // Page
|
||||||
|
continueCmd(0x00 + ((x + 2) & 0x0F)); // Column low nibble
|
||||||
|
continueCmd(0x10 + ((x + 2) >> 4)); // Column high nibble
|
||||||
|
Wire.write(OLED_ONE_DATA_MODE);
|
||||||
|
Wire.write((data << h) >> (p << 3));
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// вывести одномерный байтовый массив (линейный битмап высотой 8)
|
||||||
|
void drawBytes(uint8_t* data, byte size) {
|
||||||
|
if (!_BUFF) beginData();
|
||||||
|
for (byte i = 0; i < size; i++) {
|
||||||
|
if (++_x > _maxX) return;
|
||||||
|
if (_shift == 0) { // если вывод без сдвига на строку
|
||||||
|
writeData(data[i]); // выводим
|
||||||
|
} else { // со сдвигом
|
||||||
|
writeData(data[i] << _shift); // верхняя часть
|
||||||
|
writeData(data[i] >> (8 - _shift), 1); // нижняя часть со сдвигом на 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_BUFF) endTransm();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================== СИСТЕМНОЕ ===================================
|
||||||
|
// полностью обновить дисплей из буфера
|
||||||
|
void update() {
|
||||||
|
if (_BUFF) {
|
||||||
|
if (_TYPE < 2) { // для 1306
|
||||||
|
setWindow(0, 0, _maxX, _maxRow);
|
||||||
|
beginData();
|
||||||
|
for (int i = 0; i < (_TYPE ? 1024 : 512); i++) sendByte(_oled_buffer[i]);
|
||||||
|
endTransm();
|
||||||
|
} else { // для 1106
|
||||||
|
sendCommand(0x00);
|
||||||
|
sendCommand(0x10);
|
||||||
|
sendCommand(0x40);
|
||||||
|
uint16_t ptr = 0;
|
||||||
|
for (uint8_t i = 0; i < (64 >> 3); i++) {
|
||||||
|
sendCommand(0xB0 + i + 0); //set page address
|
||||||
|
sendCommand(2 & 0xf); //set lower column address
|
||||||
|
sendCommand(0x10); //set higher column address
|
||||||
|
for (uint8_t a = 0; a < 8; a++) {
|
||||||
|
beginData();
|
||||||
|
for (uint8_t b = 0; b < (OLED_WIDTH >> 3); b++) {
|
||||||
|
sendByteRaw(_oled_buffer[((ptr & 0x7F) << 3) + (ptr >> 7)]);
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// выборочно обновить дисплей из буфера (x0, y0, x1, y1)
|
||||||
|
void update(int x0, int y0, int x1, int y1) {
|
||||||
|
if (_BUFF) {
|
||||||
|
y0 >>= 3;
|
||||||
|
y1 >>= 3;
|
||||||
|
setWindow(x0, y0, x1, y1);
|
||||||
|
beginData();
|
||||||
|
for (int x = x0; x < x1; x++)
|
||||||
|
for (int y = y0; y < y1 + 1; y++)
|
||||||
|
if (x >= 0 && x <= _maxX && y >= 0 && y <= _maxRow)
|
||||||
|
sendByte(_oled_buffer[y + x * (_TYPE ? 8 : 4)]);
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// отправить байт по i2с или в буфер
|
||||||
|
void writeData(byte data, byte offsetY = 0, byte offsetX = 0, int mode = 0) {
|
||||||
|
if (_BUFF) {
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
_oled_buffer[_bufIndex(_x + offsetX, _y) + offsetY] |= data; // добавить
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
_oled_buffer[_bufIndex(_x + offsetX, _y) + offsetY] &= ~data; // вычесть
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
_oled_buffer[_bufIndex(_x + offsetX, _y) + offsetY] = data; // заменить
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_buf_flag) {
|
||||||
|
int x = _x - _bufX;
|
||||||
|
int y = _y - _bufY;
|
||||||
|
if (x < 0 || x > _bufsizeX || y < 0 || y > (_bufsizeY << 3)) return;
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
_buf_ptr[(y >> 3) + x * _bufsizeY] |= data; // добавить
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
_buf_ptr[(y >> 3) + x * _bufsizeY] &= ~data; // вычесть
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
_buf_ptr[(y >> 3) + x * _bufsizeY] = data; // заменить
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendByte(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// окно со сдвигом. x 0-127, y 0-63 (31), ширина в пикселях, высота в пикселях
|
||||||
|
void setWindowShift(int x0, int y0, int sizeX, int sizeY) {
|
||||||
|
_shift = y0 & 0b111;
|
||||||
|
if (!_BUFF) setWindow(x0, (y0 >> 3), x0 + sizeX, (y0 + sizeY - 1) >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== ДИНАМИЧЕСКИЙ БУФЕР ================
|
||||||
|
// создать
|
||||||
|
bool createBuffer(int x0, int y0, int x1, int y1, byte fill = 0) {
|
||||||
|
if (!_BUFF) {
|
||||||
|
_bufX = x0;
|
||||||
|
_bufY = y0;
|
||||||
|
_bufsizeX = x1 - x0 + 1;
|
||||||
|
_bufsizeY = ((y1 - y0) >> 3) + 1;
|
||||||
|
|
||||||
|
int bufSize = _bufsizeX * _bufsizeY;
|
||||||
|
_buf_ptr = (byte*)malloc(bufSize);
|
||||||
|
if (_buf_ptr != NULL) {
|
||||||
|
_buf_flag = true;
|
||||||
|
memset(_buf_ptr, fill, bufSize);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
_buf_flag = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// отправить
|
||||||
|
void sendBuffer() {
|
||||||
|
if (!_BUFF) {
|
||||||
|
if (_buf_flag) {
|
||||||
|
setWindow(_bufX, _bufY >> 3, _bufX + _bufsizeX, (_bufY >> 3) + _bufsizeY - 1);
|
||||||
|
beginData();
|
||||||
|
for (int i = 0; i < _bufsizeX * _bufsizeY; i++) {
|
||||||
|
sendByte(_buf_ptr[i]);
|
||||||
|
}
|
||||||
|
endTransm();
|
||||||
|
_buf_flag = false;
|
||||||
|
free(_buf_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========= ЛОУ-ЛЕВЕЛ ОТПРАВКА =========
|
||||||
|
|
||||||
|
// супер-костыль для либы Wire. Привет индусам!
|
||||||
|
void sendByte(uint8_t data) {
|
||||||
|
sendByteRaw(data);
|
||||||
|
#if !defined(microWire_h)
|
||||||
|
if (!_CONN) {
|
||||||
|
_writes++;
|
||||||
|
if (_writes >= 16) {
|
||||||
|
endTransm();
|
||||||
|
beginData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void sendByteRaw(uint8_t data) {
|
||||||
|
Wire.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// отправить команду
|
||||||
|
void sendCommand(uint8_t cmd1) {
|
||||||
|
beginOneCommand();
|
||||||
|
sendByteRaw(cmd1);
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
|
||||||
|
// отправить код команды и команду
|
||||||
|
void sendCommand(uint8_t cmd1, uint8_t cmd2) {
|
||||||
|
beginCommand();
|
||||||
|
sendByteRaw(cmd1);
|
||||||
|
sendByteRaw(cmd2);
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
|
||||||
|
// выбрать "окно" дисплея
|
||||||
|
void setWindow(int x0, int y0, int x1, int y1) {
|
||||||
|
beginCommand();
|
||||||
|
sendByteRaw(OLED_COLUMNADDR);
|
||||||
|
sendByteRaw(constrain(x0, 0, _maxX));
|
||||||
|
sendByteRaw(constrain(x1, 0, _maxX));
|
||||||
|
sendByteRaw(OLED_PAGEADDR);
|
||||||
|
sendByteRaw(constrain(y0, 0, _maxRow));
|
||||||
|
sendByteRaw(constrain(y1, 0, _maxRow));
|
||||||
|
endTransm();
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginData() {
|
||||||
|
startTransm();
|
||||||
|
if (_CONN) fastWrite(_DC, 1);
|
||||||
|
else sendByteRaw(OLED_DATA_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginCommand() {
|
||||||
|
startTransm();
|
||||||
|
if (_CONN) fastWrite(_DC, 0);
|
||||||
|
else sendByteRaw(OLED_COMMAND_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginOneCommand() {
|
||||||
|
startTransm();
|
||||||
|
if (_CONN) fastWrite(_DC, 0);
|
||||||
|
else sendByteRaw(OLED_ONE_COMMAND_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endTransm() {
|
||||||
|
Wire.endTransmission();
|
||||||
|
_writes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startTransm() {
|
||||||
|
Wire.beginTransmission(_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// получить "столбик-байт" буквы
|
||||||
|
uint8_t getFont(uint8_t font, uint8_t row) {
|
||||||
|
#ifndef OLED_NO_PRINT
|
||||||
|
if (row > 4) return 0;
|
||||||
|
font = font - '0' + 16; // перевод код символа из таблицы ASCII
|
||||||
|
if (font <= 95) {
|
||||||
|
return pgm_read_byte(&(_charMap[font][row])); // для английских букв и символов
|
||||||
|
} else if (font >= 96 && font <= 111) { // и пизд*ц для русских
|
||||||
|
return pgm_read_byte(&(_charMap[font + 47][row]));
|
||||||
|
} else if (font <= 159) {
|
||||||
|
return pgm_read_byte(&(_charMap[font - 17][row]));
|
||||||
|
} else {
|
||||||
|
return pgm_read_byte(&(_charMap[font - 1][row])); // для кастомных (ё)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== ПЕРЕМЕННЫЕ И КОНСТАНТЫ ====================
|
||||||
|
const uint8_t _address = 0x3C;
|
||||||
|
const uint8_t _maxRow = (_TYPE ? 8 : 4) - 1;
|
||||||
|
const uint8_t _maxY = (_TYPE ? 64 : 32) - 1;
|
||||||
|
const uint8_t _maxX = OLED_WIDTH - 1; // на случай добавления мелких дисплеев
|
||||||
|
|
||||||
|
// софт. буфер
|
||||||
|
const int _bufSize = ((_BUFF == 1) ? (_TYPE ? BUFSIZE_128x64 : BUFSIZE_128x32) : 0);
|
||||||
|
uint8_t _oled_buffer[((_BUFF == 1) ? (_TYPE ? BUFSIZE_128x64 : BUFSIZE_128x32) : 0)];
|
||||||
|
private:
|
||||||
|
// всякое
|
||||||
|
void fastWrite(const uint8_t pin, bool val) {
|
||||||
|
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||||
|
if (pin < 8) bitWrite(PORTD, pin, val);
|
||||||
|
else if (pin < 14) bitWrite(PORTB, (pin - 8), val);
|
||||||
|
else if (pin < 20) bitWrite(PORTC, (pin - 14), val);
|
||||||
|
#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
|
||||||
|
bitWrite(PORTB, pin, val);
|
||||||
|
#else
|
||||||
|
digitalWrite(pin, val);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// индекс в буфере
|
||||||
|
int _bufIndex(int x, int y) {
|
||||||
|
return ((y) >> 3) + ((x) << (_TYPE ? 3 : 2)); // _y / 8 + _x * (4 или 8)
|
||||||
|
}
|
||||||
|
void _swap(int& x, int& y) {
|
||||||
|
int z = x;
|
||||||
|
x = y;
|
||||||
|
y = z;
|
||||||
|
}
|
||||||
|
bool _inRange(int x, int mi, int ma) {
|
||||||
|
return x >= mi && x <= ma;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _invState = 0;
|
||||||
|
bool _println = false;
|
||||||
|
bool _getn = false;
|
||||||
|
uint8_t _scaleX = 1, _scaleY = 8;
|
||||||
|
int _x = 0, _y = 0;
|
||||||
|
uint8_t _shift = 0;
|
||||||
|
uint8_t _lastChar;
|
||||||
|
uint8_t _writes = 0;
|
||||||
|
uint8_t _mode = 2;
|
||||||
|
|
||||||
|
// дин. буфер
|
||||||
|
int _bufsizeX, _bufsizeY;
|
||||||
|
int _bufX, _bufY;
|
||||||
|
uint8_t* _buf_ptr;
|
||||||
|
bool _buf_flag = false;
|
||||||
|
};
|
||||||
|
#endif
|
233
OLED-I2C/charMap.h
Normal file
233
OLED-I2C/charMap.h
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
#pragma once
|
||||||
|
// шрифты для вывода текста
|
||||||
|
const uint8_t _charMap[][5] PROGMEM = {
|
||||||
|
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 32
|
||||||
|
{0x00, 0x00, 0x6f, 0x00, 0x00}, // ! 0x21 33
|
||||||
|
{0x00, 0x07, 0x00, 0x07, 0x00}, // " 0x22 34
|
||||||
|
{0x14, 0x7f, 0x14, 0x7f, 0x14}, // # 0x23 35
|
||||||
|
{0x8C, 0x92, 0xFF, 0x92, 0x62}, // $ 0x24 36
|
||||||
|
{0x23, 0x13, 0x08, 0x64, 0x62}, // % 0x25 37
|
||||||
|
{0x36, 0x49, 0x56, 0x20, 0x50}, // & 0x26 38
|
||||||
|
{0x00, 0x00, 0x07, 0x00, 0x00}, // ' 0x27 39
|
||||||
|
{0x00, 0x1c, 0x22, 0x41, 0x00}, // ( 0x28 40
|
||||||
|
{0x00, 0x41, 0x22, 0x1c, 0x00}, // ) 0x29 41
|
||||||
|
{0x14, 0x08, 0x3e, 0x08, 0x14}, // * 0x2a 42
|
||||||
|
{0x08, 0x08, 0x3e, 0x08, 0x08}, // + 0x2b 43
|
||||||
|
{0x00, 0x50, 0x30, 0x00, 0x00}, // , 0x2c 44
|
||||||
|
{0x08, 0x08, 0x08, 0x08, 0x08}, // - 0x2d 45
|
||||||
|
{0x00, 0x60, 0x60, 0x00, 0x00}, // . 0x2e 46
|
||||||
|
{0x20, 0x10, 0x08, 0x04, 0x02}, // / 0x2f 47
|
||||||
|
{0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0 0x30 48
|
||||||
|
{0x00, 0x42, 0x7f, 0x40, 0x00}, // 1 0x31 49
|
||||||
|
{0x42, 0x61, 0x51, 0x49, 0x46}, // 2 0x32 50
|
||||||
|
{0x21, 0x41, 0x45, 0x4b, 0x31}, // 3 0x33 51
|
||||||
|
{0x18, 0x14, 0x12, 0x7f, 0x10}, // 4 0x34 52
|
||||||
|
{0x27, 0x45, 0x45, 0x45, 0x39}, // 5 0x35 53
|
||||||
|
{0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6 0x36 54
|
||||||
|
{0x01, 0x71, 0x09, 0x05, 0x03}, // 7 0x37 55
|
||||||
|
{0x36, 0x49, 0x49, 0x49, 0x36}, // 8 0x38 56
|
||||||
|
{0x06, 0x49, 0x49, 0x29, 0x1e}, // 9 0x39 57
|
||||||
|
{0x00, 0x36, 0x36, 0x00, 0x00}, // : 0x3a 58
|
||||||
|
{0x00, 0x56, 0x36, 0x00, 0x00}, // ; 0x3b 59
|
||||||
|
{0x08, 0x14, 0x22, 0x41, 0x00}, // < 0x3c 60
|
||||||
|
{0x14, 0x14, 0x14, 0x14, 0x14}, // = 0x3d 61
|
||||||
|
{0x00, 0x41, 0x22, 0x14, 0x08}, // > 0x3e 62
|
||||||
|
{0x02, 0x01, 0x51, 0x09, 0x06}, // ? 0x3f 63
|
||||||
|
{0x3e, 0x41, 0x5d, 0x49, 0x4e}, // @ 0x40 64
|
||||||
|
{0x7e, 0x09, 0x09, 0x09, 0x7e}, // A 0x41 65
|
||||||
|
{0x7f, 0x49, 0x49, 0x49, 0x36}, // B 0x42 66
|
||||||
|
{0x3e, 0x41, 0x41, 0x41, 0x22}, // C 0x43 67
|
||||||
|
{0x7f, 0x41, 0x41, 0x41, 0x3e}, // D 0x44 68
|
||||||
|
{0x7f, 0x49, 0x49, 0x49, 0x41}, // E 0x45 69
|
||||||
|
{0x7f, 0x09, 0x09, 0x09, 0x01}, // F 0x46 70
|
||||||
|
{0x3e, 0x41, 0x49, 0x49, 0x7a}, // G 0x47 71
|
||||||
|
{0x7f, 0x08, 0x08, 0x08, 0x7f}, // H 0x48 72
|
||||||
|
{0x00, 0x41, 0x7f, 0x41, 0x00}, // I 0x49 73
|
||||||
|
{0x20, 0x40, 0x41, 0x3f, 0x01}, // J 0x4a 74
|
||||||
|
{0x7f, 0x08, 0x14, 0x22, 0x41}, // K 0x4b 75
|
||||||
|
{0x7f, 0x40, 0x40, 0x40, 0x40}, // L 0x4c 76
|
||||||
|
{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M 0x4d 77
|
||||||
|
{0x7f, 0x04, 0x08, 0x10, 0x7f}, // N 0x4e 78
|
||||||
|
{0x3e, 0x41, 0x41, 0x41, 0x3e}, // O 0x4f 79
|
||||||
|
{0x7f, 0x09, 0x09, 0x09, 0x06}, // P 0x50 80
|
||||||
|
{0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q 0x51 81
|
||||||
|
{0x7f, 0x09, 0x19, 0x29, 0x46}, // R 0x52 82
|
||||||
|
{0x46, 0x49, 0x49, 0x49, 0x31}, // S 0x53 83
|
||||||
|
{0x01, 0x01, 0x7f, 0x01, 0x01}, // T 0x54 84
|
||||||
|
{0x3f, 0x40, 0x40, 0x40, 0x3f}, // U 0x55 85
|
||||||
|
{0x0f, 0x30, 0x40, 0x30, 0x0f}, // V 0x56 86
|
||||||
|
{0x3f, 0x40, 0x30, 0x40, 0x3f}, // W 0x57 87
|
||||||
|
{0x63, 0x14, 0x08, 0x14, 0x63}, // X 0x58 88
|
||||||
|
{0x07, 0x08, 0x70, 0x08, 0x07}, // Y 0x59 89
|
||||||
|
{0x61, 0x51, 0x49, 0x45, 0x43}, // Z 0x5a 90
|
||||||
|
{0x00, 0x00, 0x7f, 0x41, 0x00}, // [ 0x5b 91
|
||||||
|
{0x02, 0x04, 0x08, 0x10, 0x20}, // \ 0x5c 92
|
||||||
|
{0x00, 0x41, 0x7f, 0x00, 0x00}, // ] 0x5d 93
|
||||||
|
{0x04, 0x02, 0x01, 0x02, 0x04}, // ^ 0x5e 94
|
||||||
|
{0x40, 0x40, 0x40, 0x40, 0x40}, // _ 0x5f 95
|
||||||
|
{0x00, 0x00, 0x03, 0x04, 0x00}, // ` 0x60 96
|
||||||
|
{0x20, 0x54, 0x54, 0x54, 0x78}, // a 0x61 97
|
||||||
|
{0x7f, 0x48, 0x44, 0x44, 0x38}, // b 0x62 98
|
||||||
|
{0x38, 0x44, 0x44, 0x44, 0x20}, // c 0x63 99
|
||||||
|
{0x38, 0x44, 0x44, 0x48, 0x7f}, // d 0x64 100
|
||||||
|
{0x38, 0x54, 0x54, 0x54, 0x18}, // e 0x65 101
|
||||||
|
{0x08, 0x7e, 0x09, 0x01, 0x02}, // f 0x66 102
|
||||||
|
{0x0c, 0x52, 0x52, 0x52, 0x3e}, // g 0x67 103
|
||||||
|
{0x7f, 0x08, 0x04, 0x04, 0x78}, // h 0x68 104
|
||||||
|
{0x00, 0x44, 0x7d, 0x40, 0x00}, // i 0x69 105
|
||||||
|
{0x20, 0x40, 0x44, 0x3d, 0x00}, // j 0x6a 106
|
||||||
|
{0x00, 0x7f, 0x10, 0x28, 0x44}, // k 0x6b 107
|
||||||
|
{0x00, 0x41, 0x7f, 0x40, 0x00}, // l 0x6c 108
|
||||||
|
{0x7c, 0x04, 0x18, 0x04, 0x78}, // m 0x6d 109
|
||||||
|
{0x7c, 0x08, 0x04, 0x04, 0x78}, // n 0x6e 110
|
||||||
|
{0x38, 0x44, 0x44, 0x44, 0x38}, // o 0x6f 111
|
||||||
|
{0x7c, 0x14, 0x14, 0x14, 0x08}, // p 0x70 112
|
||||||
|
{0x08, 0x14, 0x14, 0x18, 0x7c}, // q 0x71 113
|
||||||
|
{0x7c, 0x08, 0x04, 0x04, 0x08}, // r 0x72 114
|
||||||
|
{0x48, 0x54, 0x54, 0x54, 0x20}, // s 0x73 115
|
||||||
|
{0x04, 0x3f, 0x44, 0x40, 0x20}, // t 0x74 116
|
||||||
|
{0x3c, 0x40, 0x40, 0x20, 0x7c}, // u 0x75 117
|
||||||
|
{0x1c, 0x20, 0x40, 0x20, 0x1c}, // v 0x76 118
|
||||||
|
{0x3c, 0x40, 0x30, 0x40, 0x3c}, // w 0x77 119
|
||||||
|
{0x44, 0x28, 0x10, 0x28, 0x44}, // x 0x78 120
|
||||||
|
{0x0c, 0x50, 0x50, 0x50, 0x3c}, // y 0x79 121
|
||||||
|
{0x44, 0x64, 0x54, 0x4c, 0x44}, // z 0x7a 122
|
||||||
|
{0x00, 0x08, 0x36, 0x41, 0x41}, // { 0x7b 123
|
||||||
|
{0x00, 0x00, 0x7f, 0x00, 0x00}, // | 0x7c 124
|
||||||
|
{0x41, 0x41, 0x36, 0x08, 0x00}, // } 0x7d 125
|
||||||
|
{0x04, 0x02, 0x04, 0x08, 0x04}, // ~ 0x7e 126
|
||||||
|
|
||||||
|
{0x7E, 0x11, 0x11, 0x11, 0x7E}, //__А (0xC0).
|
||||||
|
{0x7F, 0x49, 0x49, 0x49, 0x33}, //__Б (0xC1).
|
||||||
|
{0x7F, 0x49, 0x49, 0x49, 0x36}, //__В (0xC2).
|
||||||
|
{0x7F, 0x01, 0x01, 0x01, 0x03}, //__Г (0xC3).
|
||||||
|
{0xE0, 0x51, 0x4F, 0x41, 0xFF}, //__Д (0xC4).
|
||||||
|
{0x7F, 0x49, 0x49, 0x49, 0x41}, //__Е (0xC5).
|
||||||
|
{0x77, 0x08, 0x7F, 0x08, 0x77}, //__Ж (0xC6).
|
||||||
|
{0x41, 0x49, 0x49, 0x49, 0x36}, //__З (0xC7).
|
||||||
|
{0x7F, 0x10, 0x08, 0x04, 0x7F}, //__И (0xC8).
|
||||||
|
{0x7C, 0x21, 0x12, 0x09, 0x7C}, //__Й (0xC9).
|
||||||
|
{0x7F, 0x08, 0x14, 0x22, 0x41}, //__К (0xCA).
|
||||||
|
{0x20, 0x41, 0x3F, 0x01, 0x7F}, //__Л (0xCB).
|
||||||
|
{0x7F, 0x02, 0x0C, 0x02, 0x7F}, //__М (0xCC).
|
||||||
|
{0x7F, 0x08, 0x08, 0x08, 0x7F}, //__Н (0xCD).
|
||||||
|
{0x3E, 0x41, 0x41, 0x41, 0x3E}, //__О (0xCE).
|
||||||
|
{0x7F, 0x01, 0x01, 0x01, 0x7F}, //__П (0xCF).
|
||||||
|
{0x7F, 0x09, 0x09, 0x09, 0x06}, //__Р (0xD0).
|
||||||
|
{0x3E, 0x41, 0x41, 0x41, 0x22}, //__С (0xD1).
|
||||||
|
{0x01, 0x01, 0x7F, 0x01, 0x01}, //__Т (0xD2).
|
||||||
|
{0x47, 0x28, 0x10, 0x08, 0x07}, //__У (0xD3).
|
||||||
|
{0x1C, 0x22, 0x7F, 0x22, 0x1C}, //__Ф (0xD4).
|
||||||
|
{0x63, 0x14, 0x08, 0x14, 0x63}, //__Х (0xD5).
|
||||||
|
{0x7F, 0x40, 0x40, 0x40, 0xFF}, //__Ц (0xD6).
|
||||||
|
{0x07, 0x08, 0x08, 0x08, 0x7F}, //__Ч (0xD7).
|
||||||
|
{0x7F, 0x40, 0x7F, 0x40, 0x7F}, //__Ш (0xD8).
|
||||||
|
{0x7F, 0x40, 0x7F, 0x40, 0xFF}, //__Щ (0xD9).
|
||||||
|
{0x01, 0x7F, 0x48, 0x48, 0x30}, //__Ъ (0xDA).
|
||||||
|
{0x7F, 0x48, 0x30, 0x00, 0x7F}, //__Ы (0xDB).
|
||||||
|
{0x00, 0x7F, 0x48, 0x48, 0x30}, //__Ь (0xDC).
|
||||||
|
{0x22, 0x41, 0x49, 0x49, 0x3E}, //__Э (0xDD).
|
||||||
|
{0x7F, 0x08, 0x3E, 0x41, 0x3E}, //__Ю (0xDE).
|
||||||
|
{0x46, 0x29, 0x19, 0x09, 0x7F}, //__Я (0xDF).
|
||||||
|
|
||||||
|
{0x20, 0x54, 0x54, 0x54, 0x78}, //__а (0xE0).
|
||||||
|
{0x3C, 0x4A, 0x4A, 0x49, 0x31}, //__б (0xE1).
|
||||||
|
{0x7C, 0x54, 0x54, 0x28, 0x00}, //__в (0xE2).
|
||||||
|
{0x7C, 0x04, 0x04, 0x0C, 0x00}, //__г (0xE3).
|
||||||
|
{0xE0, 0x54, 0x4C, 0x44, 0xFC}, //__д (0xE4).
|
||||||
|
{0x38, 0x54, 0x54, 0x54, 0x18}, //__е (0xE5).
|
||||||
|
{0x6C, 0x10, 0x7C, 0x10, 0x6C}, //__ж (0xE6).
|
||||||
|
{0x44, 0x54, 0x54, 0x28, 0x00}, //__з (0xE7).
|
||||||
|
{0x7C, 0x20, 0x10, 0x08, 0x7C}, //__и (0xE8).
|
||||||
|
{0x78, 0x42, 0x24, 0x12, 0x78}, //__й (0xE9).
|
||||||
|
{0x7C, 0x10, 0x28, 0x44, 0x00}, //__к (0xEA).
|
||||||
|
{0x20, 0x44, 0x3C, 0x04, 0x7C}, //__л (0xEB).
|
||||||
|
{0x7C, 0x08, 0x10, 0x08, 0x7C}, //__м (0xEC).
|
||||||
|
{0x7C, 0x10, 0x10, 0x10, 0x7C}, //__н (0xED).
|
||||||
|
{0x38, 0x44, 0x44, 0x44, 0x38}, //__о (0xEE).
|
||||||
|
{0x7C, 0x04, 0x04, 0x04, 0x7C}, //__п (0xEF).
|
||||||
|
{0x7C, 0x14, 0x14, 0x14, 0x08}, //__р (0xF0).
|
||||||
|
{0x38, 0x44, 0x44, 0x44, 0x00}, //__с (0xF1).
|
||||||
|
{0x04, 0x04, 0x7C, 0x04, 0x04}, //__т (0xF2).
|
||||||
|
{0x0C, 0x50, 0x50, 0x50, 0x3C}, //__у (0xF3).
|
||||||
|
{0x30, 0x48, 0xFE, 0x48, 0x30}, //__ф (0xF4).
|
||||||
|
{0x44, 0x28, 0x10, 0x28, 0x44}, //__х (0xF5).
|
||||||
|
{0x7C, 0x40, 0x40, 0x7C, 0xC0}, //__ц (0xF6).
|
||||||
|
{0x0C, 0x10, 0x10, 0x10, 0x7C}, //__ч (0xF7).
|
||||||
|
{0x7C, 0x40, 0x7C, 0x40, 0x7C}, //__ш (0xF8).
|
||||||
|
{0x7C, 0x40, 0x7C, 0x40, 0xFC}, //__щ (0xF9).
|
||||||
|
{0x04, 0x7C, 0x50, 0x50, 0x20}, //__ъ (0xFA).
|
||||||
|
{0x7C, 0x50, 0x50, 0x20, 0x7C}, //__ы (0xFB).
|
||||||
|
{0x7C, 0x50, 0x50, 0x20, 0x00}, //__ь (0xFC).
|
||||||
|
{0x28, 0x44, 0x54, 0x54, 0x38}, //__э (0xFD).
|
||||||
|
{0x7C, 0x10, 0x38, 0x44, 0x38}, //__ю (0xFE).
|
||||||
|
{0x08, 0x54, 0x34, 0x14, 0x7C}, //__я (0xFF).
|
||||||
|
{0x38, 0x55, 0x54, 0x55, 0x18}, //__ё (0xFF).
|
||||||
|
/*
|
||||||
|
{0x7e, 0x09, 0x09, 0x09, 0x7e}, // А 192
|
||||||
|
{0x7F, 0x49, 0x49, 0x49, 0x71}, // Б
|
||||||
|
{0x7f, 0x49, 0x49, 0x49, 0x36}, // В
|
||||||
|
{0x7F, 0x01, 0x01, 0x01, 0x01}, // Г
|
||||||
|
{0x60, 0x3E, 0x21, 0x3F, 0x60}, // Д
|
||||||
|
{0x7f, 0x49, 0x49, 0x49, 0x41}, // Е
|
||||||
|
{0x76, 0x08, 0x7F, 0x08, 0x76}, // Ж
|
||||||
|
{0x21, 0x41, 0x45, 0x4b, 0x31}, // З
|
||||||
|
{0x7F, 0x20, 0x10, 0x08, 0x7F}, // И
|
||||||
|
{0x7E, 0x20, 0x11, 0x08, 0x7E}, // Й
|
||||||
|
{0x7f, 0x08, 0x14, 0x22, 0x41}, // К
|
||||||
|
{0x70, 0x0E, 0x01, 0x01, 0x7F}, // Л
|
||||||
|
{0x7f, 0x02, 0x0c, 0x02, 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}, // С
|
||||||
|
{0x01, 0x01, 0x7f, 0x01, 0x01}, // Т
|
||||||
|
{0x07, 0x48, 0x48, 0x48, 0x7F}, // У
|
||||||
|
{0x1C, 0x22, 0x7F, 0x22, 0x1C}, // Ф
|
||||||
|
{0x63, 0x14, 0x08, 0x14, 0x63}, // Х
|
||||||
|
{0x7F, 0x40, 0x40, 0x7F, 0xC0}, // Ц
|
||||||
|
{0x07, 0x08, 0x08, 0x08, 0x7F}, // Ч
|
||||||
|
{0x7F, 0x40, 0x7F, 0x40, 0x7F}, // Ш
|
||||||
|
{0x7F, 0x40, 0x7F, 0x40, 0xFF}, // Щ
|
||||||
|
{0x01, 0x7F, 0x48, 0x48, 0x70}, // Ъ
|
||||||
|
{0x7F, 0x48, 0x70, 0x00, 0x7F}, // Ы
|
||||||
|
{0x00, 0x7F, 0x48, 0x48, 0x70}, // Ь
|
||||||
|
{0x22, 0x41, 0x49, 0x49, 0x3E}, // Э
|
||||||
|
{0x7F, 0x08, 0x3E, 0x41, 0x3E}, // Ю
|
||||||
|
{0x46, 0x29, 0x19, 0x09, 0x7F}, // Я 223
|
||||||
|
|
||||||
|
{0x20, 0x54, 0x54, 0x54, 0x78}, //a 224
|
||||||
|
{0x3c, 0x4a, 0x4a, 0x49, 0x31}, //б
|
||||||
|
{0x7c, 0x54, 0x54, 0x28, 0x00}, //в
|
||||||
|
{0x7c, 0x04, 0x04, 0x04, 0x0c}, //г
|
||||||
|
{0xe0, 0x54, 0x4c, 0x44, 0xfc}, //д
|
||||||
|
{0x38, 0x54, 0x54, 0x54, 0x18}, //e
|
||||||
|
{0x6c, 0x10, 0x7c, 0x10, 0x6c}, //ж
|
||||||
|
{0x44, 0x44, 0x54, 0x54, 0x28}, //з
|
||||||
|
{0x7c, 0x20, 0x10, 0x08, 0x7c}, //и
|
||||||
|
{0x7c, 0x41, 0x22, 0x11, 0x7c}, //й
|
||||||
|
{0x7c, 0x10, 0x28, 0x44, 0x00}, //к
|
||||||
|
{0x20, 0x44, 0x3c, 0x04, 0x7c}, //л
|
||||||
|
{0x7c, 0x08, 0x10, 0x08, 0x7c}, //м
|
||||||
|
{0x7c, 0x10, 0x10, 0x10, 0x7c}, //н
|
||||||
|
{0x38, 0x44, 0x44, 0x44, 0x38}, //o
|
||||||
|
{0x7c, 0x04, 0x04, 0x04, 0x7c}, //п
|
||||||
|
{0x7C, 0x14, 0x14, 0x14, 0x08}, //p
|
||||||
|
{0x38, 0x44, 0x44, 0x44, 0x20}, //c
|
||||||
|
{0x04, 0x04, 0x7c, 0x04, 0x04}, //т
|
||||||
|
{0x0C, 0x50, 0x50, 0x50, 0x3C}, //у
|
||||||
|
{0x30, 0x48, 0xfc, 0x48, 0x30}, //ф
|
||||||
|
{0x44, 0x28, 0x10, 0x28, 0x44}, //x
|
||||||
|
{0x7c, 0x40, 0x40, 0x40, 0xfc}, //ц
|
||||||
|
{0x0c, 0x10, 0x10, 0x10, 0x7c}, //ч
|
||||||
|
{0x7c, 0x40, 0x7c, 0x40, 0x7c}, //ш
|
||||||
|
{0x7c, 0x40, 0x7c, 0x40, 0xfc}, //щ
|
||||||
|
{0x04, 0x7c, 0x50, 0x50, 0x20}, //ъ
|
||||||
|
{0x7c, 0x50, 0x50, 0x20, 0x7c}, //ы
|
||||||
|
{0x7c, 0x50, 0x50, 0x20, 0x00}, //ь
|
||||||
|
{0x28, 0x44, 0x54, 0x54, 0x38}, //э
|
||||||
|
{0x7c, 0x10, 0x38, 0x44, 0x38}, //ю
|
||||||
|
{0x08, 0x54, 0x34, 0x14, 0x7c}, //я 255
|
||||||
|
*/
|
||||||
|
};
|
16
OLED-I2C/sketch_i2c_martin_v2.ino
Normal file
16
OLED-I2C/sketch_i2c_martin_v2.ino
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// #include <GyverOLED.h>
|
||||||
|
// GyverOLED<SSD1306_128x64, OLED_NO_BUFFER> oled;
|
||||||
|
|
||||||
|
#include "OLEDI2C.h"
|
||||||
|
OLEDI2C<SSD1306_128x64, OLED_NO_BUFFER> oled;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
oled.init(); // инициализация
|
||||||
|
oled.clear(); // очистка
|
||||||
|
oled.setScale(3); // масштаб текста (1..4)
|
||||||
|
oled.home(); // курсор в 0,0
|
||||||
|
oled.println("22222");
|
||||||
|
oled.println("33333");
|
||||||
|
}
|
||||||
|
void loop() {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user