// МЕНЮ С ВЕРТИКАЛЬНЫМ СКРОЛЛИНГОМ И УПРАВЛЕНИЕМ ПАРАМЕТРАМИ
#include <GyverOLED.h> // Библиотека дисплея
GyverOLED<SSD1306_128x64, OLED_BUFFER> oled(0x3C); // Обьект дисплея
//GyverOLED<SSD1306_128x64, OLED_BUFFER> oled(0x3D); // Для Proteus
#include <GyverButton.h> // Библиотека кнопок
GButton up(4, HIGH_PULL); // Кнопка Вверх
GButton ok(3, HIGH_PULL); // Кнопка ОК
GButton down(2, HIGH_PULL); // Кнопка Вниз
#define ITEMS 12 // Общее количество пунктов
// Массивы строк с именами пунктов
const char i0[] PROGMEM = " Пункт 0:";
const char i1[] PROGMEM = " Пункт 1:";
const char i2[] PROGMEM = " Пункт 2:";
const char i3[] PROGMEM = " Пункт 3:";
const char i4[] PROGMEM = " Пункт 4:";
const char i5[] PROGMEM = " Пункт 5:";
const char i6[] PROGMEM = " Пункт 6:";
const char i7[] PROGMEM = " Пункт 7:";
const char i8[] PROGMEM = " Пункт 8:";
const char i9[] PROGMEM = " Пункт 9:";
const char i10[] PROGMEM = " Пункт 10:";
const char i11[] PROGMEM = " Пункт 11:";
// Массив ссылок, обращение к пунктам по их номеру
const char* const names[] PROGMEM =
{ i0, i1, i2, i3,
i4, i5, i6, i7,
i8, i9, i10, i11 };
uint8_t data[ITEMS]; // Массив для параметров
bool flag = true; // Флаг выбора
void setup() {
oled.init(); // Инциализация дисплея
oled.setContrast(255); // Макс. яркость
}
void loop() {
static int8_t pointer = 0; // Переменная указатель
// Опрос кнопок
up.tick();
down.tick();
ok.tick();
// Обработка кнопки Вверх
if (up.isClick() or up.isHold()) { // Если кнопку нажали или удерживают
if (flag) { // Если флаг установлен
pointer = constrain(pointer - 1, 0, ITEMS - 1); // Двигаем указатель в пределах дисплея
}
else { // Иначе
data[pointer]++; // Увеличиваем параметр на 1
}
}
// Обработка кнопки Вниз
if (down.isClick() or down.isHold()) {
if (flag) { // Если флаг установлен
pointer = constrain(pointer + 1, 0, ITEMS - 1); // Двигаем указатель в пределах дисплея
}
else { // Иначе
data[pointer]--; // Уменьшаем параметр на 1
}
}
// Обработка кнопки ОК
if (ok.isClick()) { // Нажатие на ОК - переключение цели параметр/значение параметра
flag = !flag; // Инвертируем флаг
}
// Отображение Меню
oled.clear(); // Очищаем буфер
oled.home(); // Курсор в левый верхний угол
for (uint8_t i = 0; i < 8; i++) { // Цикл, выводящий 8 пунктов на дисплей
printMenuItem(pointer > 7 ? i + (pointer - 7) : i); // Выводим пункты
} // Если указатель > 7, то сдвигаем список
for (uint8_t i = 0; i < 8; i++) { // Выводим параметры в цикле
oled.setCursor(100, i); // Ставим курсор на нужную строку и позицию
oled.print(data[pointer > 7 ? i + (pointer - 7) : i]); // Условие для вывода аналогично строкам
}
printPointer(constrain(pointer, 0, 7)); // Вывод указателя, в пределах 0-7
oled.update(); // Выводим кадр на дисплей
}
void printPointer(uint8_t pointer) {
if (flag) { // Если флаг установлен
oled.setCursor(0, pointer); // Указываем на параметр
oled.print(">");
}
else { // Иначе
oled.setCursor(120, pointer); // Указываем на значение параметра
oled.print("<");
}
}
// Функция для печати строки из prm
void printMenuItem(uint8_t num) {
char buffer[21]; // Буфер на полную строку
uint16_t ptr = pgm_read_word(&(names[num])); // Получаем указатель на первый символ строки
uint8_t i = 0; // Переменная - счетчик
do { // Начало цикла
buffer[i] = (char)(pgm_read_byte(ptr++)); // Чтение в буфере одного символа из PGM и сдвиг указателя на 1
} while (buffer[i++] != NULL); // Если это не конец строки - вернуться в начало цикла
oled.println(buffer); // Вывод готовой строки с переносом на следующую
}
Loading
ssd1306
ssd1306