mirror of
https://gitlab.waag.org/make/fablab/interns/2025/sam.git
synced 2025-08-03 11:54:58 +00:00
docs
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
@@ -423,5 +423,748 @@ A portion of this code was taken from the machining week group project. But what
|
||||
```
|
||||
This is the full code of the screen. The schematic for the pcb can be found in [the final project page](/docs/final_project/final_project.md)
|
||||
|
||||
## Turning it into a library
|
||||
So I asked Copilot (Claude 3.7 Sonnet) to turn this above into a library. Using this prompt "turn the screen thing into a library so i can easily create menus and stuff" and using the context from my files it came up with this broken and oversized mess.
|
||||
??? Failure.cpp
|
||||
```cpp
|
||||
#ifndef OLED_MENU_H
|
||||
#define OLED_MENU_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <U8g2lib.h>
|
||||
|
||||
// Maximum number of menu items and item name length
|
||||
#define MAX_MENU_ITEMS 20
|
||||
#define MAX_ITEM_LENGTH 20
|
||||
|
||||
// Button states
|
||||
#define BUTTON_RELEASED 0
|
||||
#define BUTTON_PRESSED 1
|
||||
|
||||
class OLEDMenu {
|
||||
public:
|
||||
// Constructor
|
||||
OLEDMenu(U8G2_SSD1306_128X64_NONAME_F_HW_I2C* display);
|
||||
|
||||
// Initialize the menu
|
||||
void begin();
|
||||
|
||||
// Set button states
|
||||
void setButtons(bool up, bool select, bool down);
|
||||
|
||||
// Add a menu item
|
||||
bool addMenuItem(const char* item_name, const uint8_t* icon = nullptr);
|
||||
|
||||
// Set custom bitmaps for menu items
|
||||
void setItemBitmap(int item_index, const uint8_t* bitmap);
|
||||
|
||||
// Set custom screen for a menu item
|
||||
void setItemScreen(int item_index, const uint8_t* screen);
|
||||
|
||||
// Update and draw the menu
|
||||
void update();
|
||||
|
||||
// Get currently selected item
|
||||
int getSelectedItem();
|
||||
|
||||
// Set selected item
|
||||
void setSelectedItem(int item);
|
||||
|
||||
// Change to specific screen
|
||||
void setScreen(int screen_number);
|
||||
|
||||
// Get current screen
|
||||
int getCurrentScreen();
|
||||
|
||||
// Set scrollbar visibility
|
||||
void showScrollbar(bool show);
|
||||
|
||||
// Add custom screen drawing callback
|
||||
typedef void (*DrawCallback)(U8G2_SSD1306_128X64_NONAME_F_HW_I2C* display, int item_index);
|
||||
void setCustomScreenCallback(int item_index, DrawCallback callback);
|
||||
|
||||
private:
|
||||
U8G2_SSD1306_128X64_NONAME_F_HW_I2C* _display;
|
||||
|
||||
// Menu items
|
||||
char _menu_items[MAX_MENU_ITEMS][MAX_ITEM_LENGTH];
|
||||
const uint8_t* _item_icons[MAX_MENU_ITEMS];
|
||||
const uint8_t* _item_screens[MAX_MENU_ITEMS];
|
||||
DrawCallback _custom_callbacks[MAX_MENU_ITEMS];
|
||||
|
||||
int _item_count;
|
||||
int _selected_item;
|
||||
int _prev_item;
|
||||
int _next_item;
|
||||
|
||||
// Screen control
|
||||
int _current_screen;
|
||||
bool _show_scrollbar;
|
||||
|
||||
// Button states
|
||||
bool _button_up;
|
||||
bool _button_select;
|
||||
bool _button_down;
|
||||
bool _button_up_clicked;
|
||||
bool _button_select_clicked;
|
||||
bool _button_down_clicked;
|
||||
|
||||
// Internal methods
|
||||
void drawMenuScreen();
|
||||
void handleButtonEvents();
|
||||
void updateNavigation();
|
||||
};
|
||||
|
||||
#endif // OLED_MENU_H
|
||||
```
|
||||
|
||||
??? Failure.h
|
||||
```cpp
|
||||
#include "OLEDMenu.h"
|
||||
|
||||
// Constructor
|
||||
OLEDMenu::OLEDMenu(U8G2_SSD1306_128X64_NONAME_F_HW_I2C* display) {
|
||||
_display = display;
|
||||
_item_count = 0;
|
||||
_selected_item = 0;
|
||||
_current_screen = 0;
|
||||
_show_scrollbar = true;
|
||||
|
||||
// Initialize button states
|
||||
_button_up = false;
|
||||
_button_select = false;
|
||||
_button_down = false;
|
||||
_button_up_clicked = false;
|
||||
_button_select_clicked = false;
|
||||
_button_down_clicked = false;
|
||||
|
||||
// Initialize arrays
|
||||
for (int i = 0; i < MAX_MENU_ITEMS; i++) {
|
||||
_menu_items[i][0] = '\0';
|
||||
_item_icons[i] = nullptr;
|
||||
_item_screens[i] = nullptr;
|
||||
_custom_callbacks[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::begin() {
|
||||
updateNavigation();
|
||||
}
|
||||
|
||||
void OLEDMenu::setButtons(bool up, bool select, bool down) {
|
||||
_button_up = up;
|
||||
_button_select = select;
|
||||
_button_down = down;
|
||||
}
|
||||
|
||||
bool OLEDMenu::addMenuItem(const char* item_name, const uint8_t* icon) {
|
||||
// Check if we have space for another item
|
||||
if (_item_count >= MAX_MENU_ITEMS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the item name
|
||||
strncpy(_menu_items[_item_count], item_name, MAX_ITEM_LENGTH);
|
||||
_menu_items[_item_count][MAX_ITEM_LENGTH - 1] = '\0'; // Ensure null termination
|
||||
|
||||
// Store the icon
|
||||
_item_icons[_item_count] = icon;
|
||||
|
||||
// Increment the item count
|
||||
_item_count++;
|
||||
|
||||
// Update navigation
|
||||
updateNavigation();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OLEDMenu::setItemBitmap(int item_index, const uint8_t* bitmap) {
|
||||
if (item_index >= 0 && item_index < _item_count) {
|
||||
_item_icons[item_index] = bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::setItemScreen(int item_index, const uint8_t* screen) {
|
||||
if (item_index >= 0 && item_index < _item_count) {
|
||||
_item_screens[item_index] = screen;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::setCustomScreenCallback(int item_index, DrawCallback callback) {
|
||||
if (item_index >= 0 && item_index < _item_count) {
|
||||
_custom_callbacks[item_index] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::update() {
|
||||
// Handle button events
|
||||
handleButtonEvents();
|
||||
|
||||
// Draw the appropriate screen
|
||||
_display->firstPage();
|
||||
do {
|
||||
if (_current_screen == 0) {
|
||||
// Draw the menu screen
|
||||
drawMenuScreen();
|
||||
} else if (_current_screen == 1 && _item_screens[_selected_item] != nullptr) {
|
||||
// Draw item screen
|
||||
_display->drawBitmap(0, 0, 128/8, 64, _item_screens[_selected_item]);
|
||||
} else if (_current_screen == 2 && _custom_callbacks[_selected_item] != nullptr) {
|
||||
// Draw custom screen using callback
|
||||
_custom_callbacks[_selected_item](_display, _selected_item);
|
||||
}
|
||||
} while (_display->nextPage());
|
||||
}
|
||||
|
||||
int OLEDMenu::getSelectedItem() {
|
||||
return _selected_item;
|
||||
}
|
||||
|
||||
void OLEDMenu::setSelectedItem(int item) {
|
||||
if (item >= 0 && item < _item_count) {
|
||||
_selected_item = item;
|
||||
updateNavigation();
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::setScreen(int screen_number) {
|
||||
_current_screen = screen_number;
|
||||
}
|
||||
|
||||
int OLEDMenu::getCurrentScreen() {
|
||||
return _current_screen;
|
||||
}
|
||||
|
||||
void OLEDMenu::showScrollbar(bool show) {
|
||||
_show_scrollbar = show;
|
||||
}
|
||||
|
||||
void OLEDMenu::drawMenuScreen() {
|
||||
// Draw menu background elements
|
||||
// You might want to add the bitmap_item_sel_outline here
|
||||
|
||||
// Draw previous item
|
||||
_display->setFont(u8g_font_7x14);
|
||||
_display->drawStr(25, 15, _menu_items[_prev_item]);
|
||||
if (_item_icons[_prev_item] != nullptr) {
|
||||
_display->drawBitmap(4, 2, 16/8, 16, _item_icons[_prev_item]);
|
||||
}
|
||||
|
||||
// Draw selected item
|
||||
_display->setFont(u8g_font_7x14B);
|
||||
_display->drawStr(25, 15+20+2, _menu_items[_selected_item]);
|
||||
if (_item_icons[_selected_item] != nullptr) {
|
||||
_display->drawBitmap(4, 24, 16/8, 16, _item_icons[_selected_item]);
|
||||
}
|
||||
|
||||
// Draw next item
|
||||
_display->setFont(u8g_font_7x14);
|
||||
_display->drawStr(25, 15+20+20+2+2, _menu_items[_next_item]);
|
||||
if (_item_icons[_next_item] != nullptr) {
|
||||
_display->drawBitmap(4, 46, 16/8, 16, _item_icons[_next_item]);
|
||||
}
|
||||
|
||||
// Draw scrollbar if enabled
|
||||
if (_show_scrollbar && _item_count > 1) {
|
||||
// Draw scrollbar background
|
||||
// You might want to add bitmap_scrollbar_background here
|
||||
|
||||
// Draw scrollbar handle
|
||||
_display->drawBox(125, 64/_item_count * _selected_item, 3, 64/_item_count);
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::handleButtonEvents() {
|
||||
if (_current_screen == 0) {
|
||||
// Handle up button for menu navigation
|
||||
if (_button_up && !_button_up_clicked) {
|
||||
_selected_item = _selected_item - 1;
|
||||
_button_up_clicked = true;
|
||||
if (_selected_item < 0) {
|
||||
_selected_item = _item_count - 1;
|
||||
}
|
||||
updateNavigation();
|
||||
} else if (!_button_up && _button_up_clicked) {
|
||||
_button_up_clicked = false;
|
||||
}
|
||||
|
||||
// Handle down button for menu navigation
|
||||
if (_button_down && !_button_down_clicked) {
|
||||
_selected_item = _selected_item + 1;
|
||||
_button_down_clicked = true;
|
||||
if (_selected_item >= _item_count) {
|
||||
_selected_item = 0;
|
||||
}
|
||||
updateNavigation();
|
||||
} else if (!_button_down && _button_down_clicked) {
|
||||
_button_down_clicked = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle select button for screen switching
|
||||
if (_button_select && !_button_select_clicked) {
|
||||
_button_select_clicked = true;
|
||||
|
||||
// Cycle through screens
|
||||
_current_screen = (_current_screen + 1) % 3;
|
||||
|
||||
// Skip screens that don't have content
|
||||
if (_current_screen == 1 && _item_screens[_selected_item] == nullptr) {
|
||||
_current_screen = 2;
|
||||
}
|
||||
if (_current_screen == 2 && _custom_callbacks[_selected_item] == nullptr) {
|
||||
_current_screen = 0;
|
||||
}
|
||||
} else if (!_button_select && _button_select_clicked) {
|
||||
_button_select_clicked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OLEDMenu::updateNavigation() {
|
||||
// Update previous and next item indices
|
||||
_prev_item = _selected_item - 1;
|
||||
if (_prev_item < 0) _prev_item = _item_count - 1;
|
||||
|
||||
_next_item = _selected_item + 1;
|
||||
if (_next_item >= _item_count) _next_item = 0;
|
||||
}
|
||||
```
|
||||
Then I asked it to rewrite it and make it simpler and to add in a way to call functions using these menu tabs and to use the original graphics.
|
||||
|
||||
Then it came up with this
|
||||
??? AI generated.cpp
|
||||
```cpp
|
||||
#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::setItemScreen(int index, const uint8_t* screen) {
|
||||
if (index >= 0 && index < _itemCount) {
|
||||
_itemScreens[index] = screen;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
??? AI generated.h
|
||||
```cpp
|
||||
#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
|
||||
```
|
||||
Which worked really well with my code
|
||||
|
||||
??? My code
|
||||
```cpp
|
||||
#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, /* reset=*/ U8X8_PIN_NONE);
|
||||
MenuSystem menu(&u8g2);
|
||||
|
||||
//=====================================================================================//
|
||||
// Struct declarations
|
||||
typedef struct struct_message
|
||||
{
|
||||
int PWMCH1;
|
||||
int PWMCH2;
|
||||
int PWMCH3;
|
||||
int PWMCH4;
|
||||
} struct_message;
|
||||
struct_message JoystickData; // declare the struct as JoystickData
|
||||
|
||||
struct hardJoystickValues
|
||||
{
|
||||
int LXU; // Left joystick X axis up
|
||||
int LXD; // Left joystick X axis down
|
||||
int RXU; // Right joystick X axis up
|
||||
int RXD; // Right joystick X axis down
|
||||
};
|
||||
hardJoystickValues JoystickDataHard; // declare the struct as JoystickDataHard
|
||||
|
||||
//=====================================================================================//
|
||||
//declarations
|
||||
void MUXSetup();
|
||||
hardJoystickValues GUIParser();
|
||||
int analogReadMultiPlexer(int addressA, int addressB, int addressC, int addressD, int pin);
|
||||
int mapPot(int normalizedValue);
|
||||
|
||||
// Controller declarations
|
||||
const int MAXPWMVALUE = 1000;
|
||||
const int MINPWMVALUE = 2000;
|
||||
|
||||
bool buttonRight;
|
||||
bool buttonLeft;
|
||||
|
||||
// Actions for menu items
|
||||
void action3DCube() {
|
||||
Serial.println("3D Cube selected!");
|
||||
// Your 3D cube function code here
|
||||
}
|
||||
|
||||
void actionBattery() {
|
||||
Serial.println("Battery selected!");
|
||||
// Your battery function code here
|
||||
}
|
||||
|
||||
void actionDashboard() {
|
||||
Serial.println("Dashboard selected!");
|
||||
// Your dashboard function code here
|
||||
}
|
||||
|
||||
void actionFireworks() {
|
||||
Serial.println("Fireworks selected!");
|
||||
// Your fireworks function code here
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
delay(100); // Small delay to stabilize
|
||||
|
||||
Wire.begin(); // Initialize I2C bus
|
||||
Wire.setClock(400000); // Set to 400kHz (standard speed for most displays)
|
||||
|
||||
u8g2.begin();
|
||||
u8g2.clearBuffer();
|
||||
u8g2.sendBuffer();
|
||||
|
||||
MUXSetup(); // Setup the multiplexer
|
||||
|
||||
// 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();
|
||||
|
||||
Serial.println("Menu system initialized");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Read joystick and button inputs
|
||||
JoystickData.PWMCH1 = mapPot(analogReadMultiPlexer(0, 0, 0, 0, A0)); //Right joystick Y
|
||||
JoystickData.PWMCH2 = mapPot(analogReadMultiPlexer(1, 0, 0, 0, A0)); // Right joystick X
|
||||
JoystickData.PWMCH3 = mapPot(analogReadMultiPlexer(0, 0, 0, 1, A0)); // left joystick Y
|
||||
JoystickData.PWMCH4 = mapPot(analogReadMultiPlexer(1, 0, 0, 1, A0)); // left joystick X
|
||||
buttonRight = analogReadMultiPlexer(0, 0, 1, 0, A0) > 2000; // right button
|
||||
buttonLeft = analogReadMultiPlexer(1, 0, 1, 0, A0) > 2000; // left button
|
||||
|
||||
// Parse joystick data
|
||||
JoystickDataHard = GUIParser();
|
||||
|
||||
// Update menu button states
|
||||
menu.setButtons(JoystickDataHard.LXD, buttonRight, JoystickDataHard.LXU);
|
||||
|
||||
// Update and draw the menu
|
||||
menu.update();
|
||||
|
||||
// Small delay to debounce buttons
|
||||
delay(50);
|
||||
}
|
||||
|
||||
void MUXSetup()
|
||||
{
|
||||
pinMode(D3, OUTPUT); // MUX enable
|
||||
pinMode(D6, OUTPUT); // MUX address A
|
||||
pinMode(D7, OUTPUT); // MUX address B
|
||||
pinMode(D9, OUTPUT); // MUX address C
|
||||
pinMode(D8, OUTPUT); // MUX address D
|
||||
pinMode(A0, INPUT); // MUX input
|
||||
}
|
||||
|
||||
// Function to parse joystick data to hard values
|
||||
hardJoystickValues GUIParser(){
|
||||
// Define joystick offsets (calibrated resting values)
|
||||
const int offsetPWMCH1 = 1090; // Resting value for PWMCH1 (right joystick Y-axis)
|
||||
const int offsetPWMCH2 = 1072; // Resting value for PWMCH2 (right joystick X-axis)
|
||||
const int offsetPWMCH3 = 1043; // Resting value for PWMCH3 (left joystick X-axis)
|
||||
const int offsetPWMCH4 = 1476; // Resting value for PWMCH4 (left joystick Y-axis)
|
||||
|
||||
// Define deadzone threshold
|
||||
const int deadzone = 120;
|
||||
|
||||
// Adjust joystick values by subtracting offsets
|
||||
int adjustedPWMCH1 = JoystickData.PWMCH1 - offsetPWMCH1;
|
||||
int adjustedPWMCH2 = JoystickData.PWMCH2 - offsetPWMCH2;
|
||||
int adjustedPWMCH3 = JoystickData.PWMCH3 - offsetPWMCH3;
|
||||
int adjustedPWMCH4 = JoystickData.PWMCH4 - offsetPWMCH4;
|
||||
|
||||
// Apply deadzone
|
||||
if (abs(adjustedPWMCH1) < deadzone) adjustedPWMCH1 = 0; //abs to avoid negatives
|
||||
if (abs(adjustedPWMCH2) < deadzone) adjustedPWMCH2 = 0;
|
||||
if (abs(adjustedPWMCH3) < deadzone) adjustedPWMCH3 = 0;
|
||||
if (abs(adjustedPWMCH4) < deadzone) adjustedPWMCH4 = 0;
|
||||
|
||||
// Map joystick values to hard values
|
||||
int LXU = 0; // Left joystick X axis up
|
||||
int LXD = 0; // Left joystick X axis down
|
||||
if (adjustedPWMCH1 > 0) {
|
||||
LXU = 1; // Joystick is up
|
||||
} else if (adjustedPWMCH1 < 0) {
|
||||
LXD = 1; // Joystick is down
|
||||
}
|
||||
|
||||
return {LXU, LXD, 0, 0}; // Return the values as a struct
|
||||
}
|
||||
|
||||
int analogReadMultiPlexer(int addressA, int addressB, int addressC, int addressD, int pin)
|
||||
{
|
||||
digitalWrite(D3, LOW);
|
||||
digitalWrite(D6, addressA);
|
||||
digitalWrite(D7, addressB);
|
||||
digitalWrite(D9, addressC);
|
||||
digitalWrite(D8, addressD);
|
||||
return analogRead(pin);
|
||||
}
|
||||
|
||||
int mapPot(int normalizedValue)
|
||||
{
|
||||
return map(normalizedValue, 400, 2500, MINPWMVALUE, MAXPWMVALUE); // map the normalized value to the PWM range
|
||||
}
|
||||
```
|
||||
|
||||
Now I will turn this into a proper library and clean up what the AI made because there are still some things I want different. I first started off removing all of my code and reducing it down to just what's needed to run the screen with the library. Then I replaced all variables with generic ones instead of using my structs and bringing confusion
|
||||
```cpp
|
||||
// Update menu button states
|
||||
menu.setButtons(buttonDown, buttonRight, buttonUp);
|
||||
```
|
||||
Instead of
|
||||
```cpp
|
||||
menu.setButtons(JoystickDataHard.LXD, buttonRight, JoystickDataHard.LXU);
|
||||
```
|
||||
|
||||
I also removed all unused graphics from the file reducing it down to 65 lines instead of 1165 lines. Then I added some documentation to everything using DoxyGen.
|
||||

|
||||
Doxygen makes it so you can hover functions and see what they do and what all parameters are.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Files
|
||||
* [Files test using joysticks](GUI%20Test.zip)
|
||||
* [Last files](GUI%20complete.zip)
|
||||
* [*Library* Only](EasyMenu.zip)
|
Reference in New Issue
Block a user