Initial commit
This commit is contained in:
1168
example/Graphics.h
Normal file
1168
example/Graphics.h
Normal file
File diff suppressed because it is too large
Load Diff
79
example/main.cpp
Normal file
79
example/main.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <U8g2lib.h>
|
||||||
|
#include "MenuSystem.h"
|
||||||
|
#include "Graphics.h"
|
||||||
|
|
||||||
|
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
|
||||||
|
MenuSystem menu(&u8g2);
|
||||||
|
|
||||||
|
bool buttonDown = false;
|
||||||
|
bool buttonRight = false;
|
||||||
|
bool buttonUp = false;
|
||||||
|
|
||||||
|
// Actions for menu items
|
||||||
|
void action3DCube() {
|
||||||
|
Serial.println("3D Cube selected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void actionBattery() {
|
||||||
|
Serial.println("Battery selected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void actionDashboard() {
|
||||||
|
Serial.println("Dashboard selected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void actionFireworks() {
|
||||||
|
Serial.println("Fireworks selected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// Initialize serial communication
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
Wire.begin(); // Initialize I2C bus
|
||||||
|
Wire.setClock(400000); // Set to 400kHz (standard speed for most displays)
|
||||||
|
|
||||||
|
// Clear and initialize the display
|
||||||
|
u8g2.begin();
|
||||||
|
u8g2.clearBuffer();
|
||||||
|
u8g2.sendBuffer();
|
||||||
|
|
||||||
|
// Initialize the menu
|
||||||
|
menu.begin();
|
||||||
|
|
||||||
|
// Add menu items
|
||||||
|
menu.addMenuItem("3D Cube", bitmap_icons[0]);
|
||||||
|
menu.addMenuItem("Battery", bitmap_icons[1]);
|
||||||
|
menu.addMenuItem("Dashboard", bitmap_icons[2]);
|
||||||
|
menu.addMenuItem("Fireworks", bitmap_icons[3]);
|
||||||
|
menu.addMenuItem("WEEEEE", bitmap_icons[4]);
|
||||||
|
|
||||||
|
// Add action callbacks for menu items
|
||||||
|
menu.setItemCallback(0, action3DCube);
|
||||||
|
menu.setItemCallback(1, actionBattery);
|
||||||
|
menu.setItemCallback(2, actionDashboard);
|
||||||
|
menu.setItemCallback(3, actionFireworks);
|
||||||
|
|
||||||
|
// Clear the display once more
|
||||||
|
u8g2.clearBuffer();
|
||||||
|
u8g2.sendBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
//Set according to your button setup or use the booleans in another configuration
|
||||||
|
buttonUp = digitalRead(D0);
|
||||||
|
buttonUp = digitalRead(D1);
|
||||||
|
buttonUp = digitalRead(D2);
|
||||||
|
|
||||||
|
// Update menu button states
|
||||||
|
menu.setButtons(buttonDown, buttonRight, buttonUp);
|
||||||
|
|
||||||
|
// Update and draw the menu
|
||||||
|
menu.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
33
src/MenuGraphics.h
Normal file
33
src/MenuGraphics.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// 'scrollbar_background', 8x64px
|
||||||
|
const unsigned char bitmap_scrollbar_background [] PROGMEM = {
|
||||||
|
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
|
||||||
|
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
|
||||||
|
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
|
||||||
|
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
// 'item_sel_outline', 128x21px
|
||||||
|
const unsigned char bitmap_item_sel_outline [] PROGMEM = {
|
||||||
|
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
|
||||||
|
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
|
||||||
|
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0
|
||||||
|
};
|
||||||
|
|
152
src/MenuSystem.cpp
Normal file
152
src/MenuSystem.cpp
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#include "MenuSystem.h"
|
||||||
|
#include "MenuGraphics.h"
|
||||||
|
|
||||||
|
MenuSystem::MenuSystem(U8G2_SSD1306_128X64_NONAME_F_HW_I2C* display) {
|
||||||
|
_display = display;
|
||||||
|
_itemCount = 0;
|
||||||
|
_selectedItem = 0;
|
||||||
|
_screen = 0;
|
||||||
|
|
||||||
|
_btnUp = false;
|
||||||
|
_btnSelect = false;
|
||||||
|
_btnDown = false;
|
||||||
|
_prevBtnUp = false;
|
||||||
|
_prevBtnSelect = false;
|
||||||
|
_prevBtnDown = false;
|
||||||
|
|
||||||
|
// Initialize arrays
|
||||||
|
for (int i = 0; i < MAX_ITEMS; i++) {
|
||||||
|
_itemNames[i][0] = '\0';
|
||||||
|
_itemIcons[i] = nullptr;
|
||||||
|
_itemScreens[i] = nullptr;
|
||||||
|
_itemCallbacks[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::begin() {
|
||||||
|
// Ensure display is properly initialized
|
||||||
|
_display->begin();
|
||||||
|
_display->clearBuffer();
|
||||||
|
_display->sendBuffer();
|
||||||
|
delay(100); // Short delay to ensure display is ready
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::addMenuItem(const char* name, const uint8_t* icon) {
|
||||||
|
if (_itemCount < MAX_ITEMS) {
|
||||||
|
strncpy(_itemNames[_itemCount], name, MAX_NAME_LEN-1);
|
||||||
|
_itemNames[_itemCount][MAX_NAME_LEN-1] = '\0'; // Ensure null termination
|
||||||
|
_itemIcons[_itemCount] = icon;
|
||||||
|
_itemCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::setItemCallback(int index, void (*callback)()) {
|
||||||
|
if (index >= 0 && index < _itemCount) {
|
||||||
|
_itemCallbacks[index] = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::setButtons(bool up, bool select, bool down) {
|
||||||
|
// Save previous button states
|
||||||
|
_prevBtnUp = _btnUp;
|
||||||
|
_prevBtnSelect = _btnSelect;
|
||||||
|
_prevBtnDown = _btnDown;
|
||||||
|
|
||||||
|
// Set new button states
|
||||||
|
_btnUp = up;
|
||||||
|
_btnSelect = select;
|
||||||
|
_btnDown = down;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::update() {
|
||||||
|
// Process button inputs before drawing
|
||||||
|
handleButtons();
|
||||||
|
|
||||||
|
// Simple drawing approach (not using page buffer mode)
|
||||||
|
_display->clearBuffer();
|
||||||
|
|
||||||
|
if (_screen == 0) {
|
||||||
|
// Draw the main menu screen
|
||||||
|
drawMenu();
|
||||||
|
} else if (_screen == 1 && _itemScreens[_selectedItem] != nullptr) {
|
||||||
|
// Draw the full-screen bitmap for the selected item
|
||||||
|
_display->drawXBM(0, 0, 128, 64, _itemScreens[_selectedItem]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_display->sendBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::drawMenu() {
|
||||||
|
if (_itemCount == 0) return; // Nothing to draw
|
||||||
|
|
||||||
|
// Calculate which items to show (previous, current, next)
|
||||||
|
int prevItem = (_selectedItem > 0) ? _selectedItem - 1 : _itemCount - 1;
|
||||||
|
int nextItem = (_selectedItem < _itemCount - 1) ? _selectedItem + 1 : 0;
|
||||||
|
|
||||||
|
// Draw the background with the item selector outline (if enabled)
|
||||||
|
// _display->drawXBM(0, 0, 128, 64, bitmap_item_sel_outline);
|
||||||
|
|
||||||
|
// Instead, draw a simple selection highlight
|
||||||
|
_display->drawFrame(0, 20, 128, 24); // Highlight the middle selection
|
||||||
|
|
||||||
|
// Draw previous item (top position)
|
||||||
|
_display->setFont(u8g2_font_6x10_tf); // Use a different, simpler font
|
||||||
|
_display->drawStr(25, 15, _itemNames[prevItem]);
|
||||||
|
if (_itemIcons[prevItem] != nullptr) {
|
||||||
|
_display->drawXBM(4, 2, 16, 16, _itemIcons[prevItem]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw selected item (middle position)
|
||||||
|
_display->setFont(u8g2_font_6x10_tf); // Use same font for consistency
|
||||||
|
_display->drawStr(25, 35, _itemNames[_selectedItem]);
|
||||||
|
if (_itemIcons[_selectedItem] != nullptr) {
|
||||||
|
_display->drawXBM(4, 24, 16, 16, _itemIcons[_selectedItem]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw next item (bottom position)
|
||||||
|
_display->setFont(u8g2_font_6x10_tf); // Use same font for consistency
|
||||||
|
_display->drawStr(25, 55, _itemNames[nextItem]);
|
||||||
|
if (_itemIcons[nextItem] != nullptr) {
|
||||||
|
_display->drawXBM(4, 46, 16, 16, _itemIcons[nextItem]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a simple scrollbar instead of using bitmap
|
||||||
|
if (_itemCount > 1) {
|
||||||
|
_display->drawVLine(125, 0, 64); // Scrollbar background
|
||||||
|
int barHeight = 64 / _itemCount;
|
||||||
|
int barY = (_selectedItem * 64) / _itemCount;
|
||||||
|
_display->drawBox(123, barY, 4, barHeight); // Scrollbar handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuSystem::handleButtons() {
|
||||||
|
// Only respond to button press events (not holds)
|
||||||
|
// Button rising edge detection for up
|
||||||
|
if (_btnUp && !_prevBtnUp) {
|
||||||
|
_selectedItem = (_selectedItem > 0) ? _selectedItem - 1 : _itemCount - 1;
|
||||||
|
Serial.print("Selected item: ");
|
||||||
|
Serial.println(_selectedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button rising edge detection for down
|
||||||
|
if (_btnDown && !_prevBtnDown) {
|
||||||
|
_selectedItem = (_selectedItem < _itemCount - 1) ? _selectedItem + 1 : 0;
|
||||||
|
Serial.print("Selected item: ");
|
||||||
|
Serial.println(_selectedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button rising edge detection for select
|
||||||
|
if (_btnSelect && !_prevBtnSelect) {
|
||||||
|
// Execute callback if it exists
|
||||||
|
if (_itemCallbacks[_selectedItem] != nullptr) {
|
||||||
|
_itemCallbacks[_selectedItem]();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle between menu and item screen if screen exists
|
||||||
|
if (_itemScreens[_selectedItem] != nullptr) {
|
||||||
|
_screen = (_screen == 0) ? 1 : 0;
|
||||||
|
Serial.print("Screen changed to: ");
|
||||||
|
Serial.println(_screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
src/MenuSystem.h
Normal file
58
src/MenuSystem.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef MENU_SYSTEM_H
|
||||||
|
#define MENU_SYSTEM_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <U8g2lib.h>
|
||||||
|
|
||||||
|
class MenuSystem {
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
MenuSystem(U8G2_SSD1306_128X64_NONAME_F_HW_I2C* display);
|
||||||
|
|
||||||
|
// Initialize menu
|
||||||
|
void begin();
|
||||||
|
|
||||||
|
// Add menu item with icon
|
||||||
|
void addMenuItem(const char* name, const uint8_t* icon);
|
||||||
|
|
||||||
|
// Set callback function for item
|
||||||
|
void setItemCallback(int index, void (*callback)());
|
||||||
|
|
||||||
|
// Set button states
|
||||||
|
void setButtons(bool up, bool select, bool down);
|
||||||
|
|
||||||
|
// Update and draw menu
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
U8G2_SSD1306_128X64_NONAME_F_HW_I2C* _display;
|
||||||
|
|
||||||
|
// Menu items
|
||||||
|
static const int MAX_ITEMS = 10;
|
||||||
|
static const int MAX_NAME_LEN = 20;
|
||||||
|
char _itemNames[MAX_ITEMS][MAX_NAME_LEN];
|
||||||
|
const uint8_t* _itemIcons[MAX_ITEMS];
|
||||||
|
const uint8_t* _itemScreens[MAX_ITEMS];
|
||||||
|
void (*_itemCallbacks[MAX_ITEMS])();
|
||||||
|
|
||||||
|
// Menu state
|
||||||
|
int _itemCount;
|
||||||
|
int _selectedItem;
|
||||||
|
int _screen; // 0 = menu, 1 = item screen
|
||||||
|
|
||||||
|
// Button handling
|
||||||
|
bool _btnUp;
|
||||||
|
bool _btnSelect;
|
||||||
|
bool _btnDown;
|
||||||
|
bool _prevBtnUp;
|
||||||
|
bool _prevBtnSelect;
|
||||||
|
bool _prevBtnDown;
|
||||||
|
|
||||||
|
// Draw the menu
|
||||||
|
void drawMenu();
|
||||||
|
|
||||||
|
// Update button states
|
||||||
|
void handleButtons();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user