#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
// U8GLIB_SSD1306_128X64 u8g(13, 11, 8, 9, 10); // SPI connection
// for SPI connection, use this wiring:
// GND > GND
// VCC > 5V
// SCL > 13
// SDA > 11
// RES > 10
// DC > 9
// CS > 8
// 'alarm', 104x14px
const unsigned char menu_icon_alarm [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x37, 0x98, 0x5d, 0x10, 0xb7, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xd7, 0x6b, 0x49, 0xb6, 0x97, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x17, 0x08, 0xd5,
0xb6, 0xa7, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xd7, 0x6b, 0x5d, 0xb6, 0xb7, 0xff,
0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xd1, 0x6b, 0x5d, 0xb0, 0xb7, 0xff, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'brightness', 104x14px
const unsigned char menu_icon_brightness [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0xd0, 0xbb, 0xa1, 0x50, 0xa3, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xd7, 0xbb, 0xaf, 0x57, 0xb7, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x11, 0xbb, 0xa9,
0x31, 0xb7, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xd7, 0xbb, 0xad, 0x57, 0xb7, 0xff,
0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xd0, 0x88, 0xa1, 0x50, 0xb7, 0xff, 0xbd, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'calibrate', 104x14px
const unsigned char menu_icon_calibrate [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0xd9, 0xba, 0x61, 0x42, 0x10, 0xb7, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xb6, 0xba, 0xad, 0x5e, 0xd7, 0x97, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x70, 0xba, 0x63,
0x46, 0x31, 0xa7, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb6, 0xba, 0xad, 0x5e, 0xd7, 0xb7,
0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xd6, 0x8a, 0x6d, 0x42, 0xd0, 0xb7, 0xe7, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'info', 104x14px
const unsigned char menu_icon_info [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x16, 0x84, 0x42, 0xea, 0xd0, 0x87, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xf6, 0xbe, 0xde, 0x4a, 0x57, 0xb7, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x19, 0x86, 0xc6,
0xaa, 0x91, 0xb7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xf6, 0xde, 0xea, 0xd7, 0xb7,
0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1b, 0x86, 0xc2, 0xea, 0xd7, 0x87, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'signal', 104x14px
const unsigned char menu_icon_signal [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x14, 0x2d, 0x9b, 0x88, 0x5b, 0xff, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xf5, 0xe5, 0x6b, 0xdb, 0x4b, 0xff, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x15, 0x29, 0x0b,
0xdb, 0x53, 0xff, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xad, 0x6b, 0xdb, 0x5b, 0xff,
0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x14, 0x2d, 0x68, 0xd8, 0x5b, 0xff, 0xdf, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// 'stealth', 104x14px
const unsigned char menu_icon_stealth [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x11, 0x0c, 0xdc, 0x7f, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xfb, 0x7b, 0x5e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1b, 0x18, 0x5e,
0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x7b, 0x5e, 0xff, 0xff, 0xff,
0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1b, 0x0b, 0x46, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 1248)
const int menu_icon_allArray_LEN = 6;
const unsigned char* bitmap_icons[6] = {
menu_icon_alarm,
menu_icon_brightness,
menu_icon_calibrate,
menu_icon_info,
menu_icon_signal,
menu_icon_stealth
};
// 'scrollbar', 5x50px
const unsigned char menu_part_scrollbar [] PROGMEM = {
0x1f, 0x1f, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04,
0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04,
0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04, 0x0a, 0x04,
0x1f, 0x1f
};
// 'selector', 11x14px
const unsigned char menu_part_selector [] PROGMEM = {
0x1f, 0x00, 0x3f, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0xff, 0x07,
0xff, 0x03, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x1f, 0x00
};
// 'title', 69x13px
const unsigned char menu_part_title [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x07, 0x0f, 0xb5, 0x88, 0xd0, 0xdd, 0x5a, 0x08, 0xed, 0x07, 0xef, 0xa5, 0xde,
0xde, 0xdd, 0x52, 0xef, 0xe9, 0x03, 0x8f, 0x95, 0xd8, 0xd8, 0xdd, 0x4a, 0x89, 0xe5, 0x03, 0xef,
0xb5, 0xdb, 0xde, 0xdd, 0x5a, 0xeb, 0xed, 0x01, 0x0f, 0xb5, 0xd8, 0x10, 0x31, 0x5b, 0x08, 0xed,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x7f, 0x00
};
const int NUM_ITEMS = 6; // number of items in the list and also the number of screenshots and screenshots with QR codes (other screens)
#define BUTTON_UP_PIN 12 // pin for UP button
#define BUTTON_SELECT_PIN 8 // pin for SELECT button
#define BUTTON_DOWN_PIN 4 // pin for DOWN button
int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above
int item_selected = 0; // which item in the menu is selected
int item_sel_previous; // previous item - used in the menu screen to draw the item before the selected one
int item_sel_next; // next item - used in the menu screen to draw next item after the selected one
int current_screen = 0; // 0 = menu, 1 = screenshot, 2 = qr
void setup() {
u8g.setColorIndex(1); // set the color to white
// define pins for buttons
// INPUT_PULLUP means the button is HIGH when not pressed, and LOW when pressed
// since it´s connected between some pin and GND
pinMode(BUTTON_UP_PIN, INPUT_PULLUP); // up button
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP); // select button
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); // down button
pinMode(DEMO_PIN, INPUT_PULLUP);
}
void loop() {
// when pin 13 is LOW (DEMO_PIN), enable demo mode
// this could be done either by using a switch
// or simply by connecting the wire between pin 13 and GND
// (those pins are next to each other)
if (digitalRead(DEMO_PIN) == LOW) {
demo_mode = 1; // enable demo mode
}
else {
demo_mode = 0; // disable demo mode
}
if (demo_mode == 1) { // when demo mode is active, automatically switch between all the screens and menu items
demo_mode_delay++; // increase demo mode delay
if (demo_mode_delay > 15) { // after some time, switch to another screen - change this value to make it slower/faster
demo_mode_delay = 0;
demo_mode_state++; // increase counter
if (demo_mode_state >= NUM_ITEMS*3) {demo_mode_state=0;} // jump back to the first screen
}
if (demo_mode_state % 3 == 0) {current_screen = 0; item_selected = demo_mode_state/3; } // menu screen
else if (demo_mode_state % 3 == 1) {current_screen = 1; item_selected = demo_mode_state/3;} // screenshots screen
else if (demo_mode_state % 3 == 2) {current_screen = 2; item_selected = demo_mode_state/3;} // qr codes screen
} // end demo mode section
if (current_screen == 0) { // MENU SCREEN
// up and down buttons only work for the menu screen
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0)) { // up button clicked - jump to previous menu item
item_selected = item_selected - 1; // select previous item
button_up_clicked = 1; // set button to clicked to only perform the action once
if (item_selected < 0) { // if first item was selected, jump to last item
item_selected = NUM_ITEMS-1;
}
}
else if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0)) { // down button clicked - jump to next menu item
item_selected = item_selected + 1; // select next item
button_down_clicked = 1; // set button to clicked to only perform the action once
if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
item_selected = 0;
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) { // unclick
button_up_clicked = 0;
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) { // unclick
button_down_clicked = 0;
}
}
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
button_select_clicked = 1; // set button to clicked to only perform the action once
if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
else {current_screen = 0;} // qr codes screen --> menu items screen
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) { // unclick
button_select_clicked = 0;
}
// set correct values for the previous and next items
item_sel_previous = item_selected - 1;
if (item_sel_previous < 0) {item_sel_previous = NUM_ITEMS - 1;} // previous item would be below first = make it the last
item_sel_next = item_selected + 1;
if (item_sel_next >= NUM_ITEMS) {item_sel_next = 0;} // next item would be after last = make it the first
u8g.firstPage(); // required for page drawing mode for u8g library
do {
if (current_screen == 0) { // MENU SCREEN
// selected item background
u8g.drawBitmapP(0, 22, 128/8, 21, menu_part_selector);
// draw previous item as icon + label
u8g.drawBitmapP( 4, 2, 16/8, 16, bitmap_icons[item_sel_previous]);
// draw selected item as icon + label in bold font
u8g.setFont(u8g_font_7x14B);
u8g.drawStr(25, 15+20+2, menu_items[item_selected]);
u8g.drawBitmapP( 4, 24, 16/8, 16, bitmap_icons[item_selected]);
// draw next item as icon + label
u8g.setFont(u8g_font_7x14);
u8g.drawStr(25, 15+20+20+2+2, menu_items[item_sel_next]);
u8g.drawBitmapP( 4, 46, 16/8, 16, bitmap_icons[item_sel_next]);
// draw scrollbar background
u8g.drawBitmapP(128-8, 0, 8/8, 64, bitmap_scrollbar_background);
// draw scrollbar handle
u8g.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
// draw upir logo
u8g.drawBitmapP(128-16-4, 64-4, 16/8, 4, upir_logo);
}
else if (current_screen == 1) { // SCREENSHOTS SCREEN
u8g.drawBitmapP( 0, 0, 128/8, 64, bitmap_screenshots[item_selected]); // draw screenshot
}
else if (current_screen == 2) { // QR SCREEN
u8g.drawBitmapP( 0, 0, 128/8, 64, bitmap_qr_codes[item_selected]); // draw qr code screenshot
}
} while ( u8g.nextPage() ); // required for page drawing mode with u8g library
}