#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
// ' icon_bowl', 16x16px
const unsigned char bitmap_icon_bowl [] PROGMEM = {
0x00, 0x24, 0x00, 0x80, 0x00, 0x14, 0x01, 0x40, 0x00, 0x10, 0x02, 0x40, 0x00, 0x00, 0x0f, 0xf0,
0x18, 0x18, 0x10, 0x08, 0x3c, 0x3c, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x1f, 0xf8, 0x00, 0x00
};
// ' icon_clock', 16x16px
const unsigned char bitmap_icon_clock [] PROGMEM = {
0x1c, 0x38, 0x32, 0x4c, 0x62, 0x46, 0x47, 0xe2, 0x48, 0x12, 0x70, 0x8e, 0x20, 0x84, 0x24, 0x84,
0x42, 0x82, 0x41, 0x82, 0x40, 0x04, 0x20, 0x04, 0x20, 0x08, 0x18, 0x10, 0x0f, 0xf0, 0x1c, 0x38
};
// ' icon_settings', 16x16px
const unsigned char bitmap_icon_settings [] PROGMEM = {
0x00, 0x00, 0x03, 0xc0, 0x1b, 0xd8, 0x3f, 0xfc, 0x3f, 0xfc, 0x1c, 0x38, 0x78, 0x1e, 0x78, 0x1e,
0x78, 0x1e, 0x78, 0x1e, 0x1c, 0x38, 0x3f, 0xfc, 0x3f, 0xfc, 0x1b, 0xd8, 0x03, 0xc0, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 144)
const int icons_array_LENGTH = 3;
const unsigned char* icons_array[3] = {
bitmap_icon_bowl,
bitmap_icon_clock,
bitmap_icon_settings
};
// ' scrollbar', 8x64px
const unsigned char bitmap_scrollbar [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// ' selector', 128x20px
const unsigned char bitmap_selector [] PROGMEM = {
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0,
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00
};
const int NUM_ITEMS = 3; // number of items in the list
const int MAX_ITEM_LENGTH = 20; // maximum characters for the item name
char menu_items [NUM_ITEMS] [MAX_ITEM_LENGTH] = { // array with item names
{ "Feed now!" },
{ "Feed later" },
{ "Settings" }
};
#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
#define FONT_HEIGHT u8g.getFontAscent()-u8g.getFontDescent()
#define FONT_WIDTH u8g.getStrWidth("a")
#define MENU_SCREEN 0
#define FEED_NOW_SCREEN 1
#define FEED_LATER_SCREEN 2
#define SETTINGS_SCREEN 3
#define EDITOR_SCREEN 10
int current_screen = MENU_SCREEN;
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 MAIN_MENU_SCREEN_items_idx = 0; // which item in the menu is selected
bool edit_mode_on = false;
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
struct feedingTime{
uint32_t id;
char type; // 'W' - weekly on, 'O' - one time on, 'w' - weekly off, 'o' - one time off
char day; // 00000001 - Monday, 01000010 - Sunday and Tuesday
int year;
int month;
int date;
int hour;
int minute;
int rations;
String toString() //"( ) O 2 2023:9:14 07:50"
{
String s = "";
// is active?
if (type == 'W' || type == 'O')
s += "(x) ";
else
s += "( ) ";
// type
if (type == 'W' || type == 'w')
s += "W ";
else if (type == 'O' || type == 'o')
s += "O ";
// rations
s += rations;
s += " ";
// date
if (month != 0){
s += year;
s += ".";
if (month / 10 == 0) s += "0";
s += month;
s += ".";
if (date / 10 == 0) s += "0";
s += date;
s += ".";
} // or days
else{
s += day & 0b00000001 ? "M" : "_";
s += day & 0b00000010 ? "T" : "_";
s += day & 0b00000100 ? "W" : "_";
s += day & 0b00001000 ? "T" : "_";
s += day & 0b00010000 ? "F" : "_";
s += day & 0b00100000 ? "S" : "_";
s += day & 0b01000000 ? "S" : "_";
}
s += " ";
// time
if (hour / 10 == 0) s += "0";
s += hour;
s += ":";
if (minute / 10 == 0) s += "0";
s += minute;
return s;
}
};
int feedingTimes_count = 9;
feedingTime feedingTimes[] = {
{1, 'w', 0b00000001, 0, 0, 0, 10, 45, 3},
{2, 'o', 0b01111111, 2023, 6, 30, 13, 45, 2},
{3, 'W', 0b01010101, 0, 0, 0, 23, 1, 3},
{4, 'O', 0, 2023, 10, 15, 10, 30, 4},
{5, 'w', 0b01111111, 0, 0, 0, 3, 0, 5},
{6, 'w', 0b00000001, 0, 0, 0, 13, 45, 6},
{7, 'W', 0b01010101, 0, 0, 0, 23, 1, 7},
{8, 'o', 0, 2024, 5, 1, 20, 59, 8},
{9, 'O', 0, 2023, 10, 15, 10, 30, 9}
};
feedingTime* selectedFeedingTime;
struct selectableItem
{
void (*action)();
int x;
int y;
String text;
int* value;
String toString()
{
if (text.length() == 0)
{
return text + *value;
}
return text;
}
};
selectableItem* selectedItem;
// EDITOR CONTEXT:
struct editorContext
{
uint32_t id;
bool isActive;
bool isWeekly;
int year;
int month;
int date;
int hour;
int minute;
int rations;
bool weekDays[7];
};
editorContext context = {0, true, true, 2023, 10, 30, 12, 30, 1, {true, true, true, true, true, true, true}};
void openEditor(bool editing)
{
if (editing)
{
if (selectedFeedingTime->type == 'W' || selectedFeedingTime->type == 'O')
context.isActive = true;
else
context.isActive = false;
if (selectedFeedingTime->type == 'W' || selectedFeedingTime->type == 'w')
{
context.isWeekly = true;
context.weekDays[0] = 0b00000001 & selectedFeedingTime->day;
context.weekDays[1] = 0b00000010 & selectedFeedingTime->day;
context.weekDays[2] = 0b00000100 & selectedFeedingTime->day;
context.weekDays[3] = 0b00001000 & selectedFeedingTime->day;
context.weekDays[4] = 0b00010000 & selectedFeedingTime->day;
context.weekDays[5] = 0b00100000 & selectedFeedingTime->day;
context.weekDays[6] = 0b01000000 & selectedFeedingTime->day;
}
else
{
context.isWeekly = false;
context.year = selectedFeedingTime->year;
context.month = selectedFeedingTime->month;
context.date = selectedFeedingTime->date;
}
context.rations = selectedFeedingTime->rations;
}
else
{
context = {0, true, true, 2023, 10, 30, 12, 30, 1, {true, true, true, true, true, true, true}};
}
}
void drawSelection(selectableItem si)
{
if (edit_mode_on)
{
u8g.drawStr(si.x - FONT_WIDTH, si.y, "<");
u8g.drawStr(si.x + si.toString().length() * FONT_WIDTH, si.y, ">");
}
else
{
int width = si.toString().length() * FONT_WIDTH + FONT_WIDTH;
u8g.drawRFrame(
si.x - 4,
si.y-1,
width < 120 ? width : 120,
FONT_HEIGHT + 2,
3);
}
}
int rations = 1;
int FEED_NOW_SCREEN_items_idx = 0;
int FEED_NOW_SCREEN_items_count = 3;
selectableItem FEED_NOW_SCREEN_items[] = {
{
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 98,
.y = 10,
.text = "",
.value = &rations
},
{
.action = []{
//run motor
},
.x = 20,
.y = 40,
.text = "OK"
},
{
.action = []{
current_screen = MENU_SCREEN;
},
.x = 60,
.y = 40,
.text = "Go back!"
}
};
int FEED_LATER_SCREEN_items_idx = 0;
int FEED_LATER_SCREEN_items_count = 7;
int FEED_LATER_SCREEN_feedingTime_idx = 0;
selectableItem FEED_LATER_SCREEN_items[] = {
{
.action = []{
current_screen = MENU_SCREEN;
},
.x = 5,
.y = 4,
.text = "Go back!"
},
{
.action = []{
current_screen = EDITOR_SCREEN;
openEditor(false);
},
.x = 70,
.y = 4,
.text = "Create new!"
},
{
.action = []{
current_screen = EDITOR_SCREEN;
openEditor(true);
},
.x = 10,
.y = 15,
.text = feedingTimes[0].toString()
},
{
.action = []{
current_screen = EDITOR_SCREEN;
openEditor(true);
},
.x = 10,
.y = 25,
.text = feedingTimes[1].toString()
},
{
.action = []{
current_screen = EDITOR_SCREEN;
openEditor(true);
},
.x = 10,
.y = 35,
.text = feedingTimes[2].toString()
},
{
.action = []{
current_screen = EDITOR_SCREEN;
openEditor(true);
},
.x = 10,
.y = 45,
.text = feedingTimes[3].toString()
},
{
.action = []{
current_screen = EDITOR_SCREEN;
openEditor(true);
},
.x = 10,
.y = 55,
.text = feedingTimes[4].toString()
}
};
int EDITOR_SCREEN_items_idx = 0;
int EDITOR_SCREEN_items_count = 17;
selectableItem EDITOR_SCREEN_items[] = {
{ //0: go back
.action = []{
current_screen = FEED_LATER_SCREEN;
},
.x = 5,
.y = 4,
.text = "Go back!"
},
{ //1: save
.action = []{
if (context.id == 0)
{
//feedingTimes.push_back(editorContext);
}
else
{
//selectedFeedingTime->type = (char)context.type;
//selectedFeedingTime->day = (char)context.day;
selectedFeedingTime->year = context.year;
selectedFeedingTime->month = context.month;
selectedFeedingTime->date = context.date;
selectedFeedingTime->hour = context.hour;
selectedFeedingTime->minute = context.minute;
selectedFeedingTime->rations = context.rations;
}
current_screen = FEED_LATER_SCREEN;
},
.x = 85,
.y = 4,
.text = "Save!"
},
{ //2: isActive
.action = []{
context.isActive = !context.isActive;
if (context.isActive)
EDITOR_SCREEN_items[2].text = "Yes";
else
EDITOR_SCREEN_items[2].text = "No";
},
.x = 45,
.y = 15,
.text = "Yes"
},
{ //3: type
.action = []{
context.isWeekly = !context.isWeekly;
if (context.isWeekly)
EDITOR_SCREEN_items[3].text = "Weekly";
else
EDITOR_SCREEN_items[3].text = "Once";
},
.x = 94,
.y = 15,
.text = "Weekly"
},
{ //4. rations
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 50,
.y = 25,
.text = "",
.value = &context.rations
},
{ //5: hour
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 40,
.y = 35,
.text = "",
.value = &context.hour
},
{ //6: minute
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 60,
.y = 35,
.text = "",
.value = &context.minute
},
{ //7: monday
.action = []{
context.weekDays[0] = !context.weekDays[0];
EDITOR_SCREEN_items[7].text = context.weekDays[0] ? "M" : "_";
},
.x = 40,
.y = 45,
.text = "M"
},
{ //8: tuesday
.action = []{
context.weekDays[1] = !context.weekDays[1];
EDITOR_SCREEN_items[8].text = context.weekDays[1] ? "T" : "_";
},
.x = 51,
.y = 45,
.text = "T"
},
{ //9: wednesday
.action = []{
context.weekDays[2] = !context.weekDays[2];
EDITOR_SCREEN_items[9].text = context.weekDays[2] ? "W" : "_";
},
.x = 62,
.y = 45,
.text = "W"
},
{ //10: thursday
.action = []{
context.weekDays[3] = !context.weekDays[3];
EDITOR_SCREEN_items[10].text = context.weekDays[3] ? "T" : "_";
},
.x = 73,
.y = 45,
.text = "T"
},
{ //11: friday
.action = []{
context.weekDays[4] = !context.weekDays[4];
EDITOR_SCREEN_items[11].text = context.weekDays[4] ? "F" : "_";
},
.x = 84,
.y = 45,
.text = "F"
},
{ //12: saturday
.action = []{
context.weekDays[5] = !context.weekDays[5];
EDITOR_SCREEN_items[12].text = context.weekDays[5] ? "S" : "_";
},
.x = 95,
.y = 45,
.text = "S"
},
{ //13: sunday
.action = []{
context.weekDays[6] = !context.weekDays[6];
EDITOR_SCREEN_items[13].text = context.weekDays[6] ? "S" : "_";
},
.x = 106,
.y = 45,
.text = "S"
},
{ //14: year
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 40,
.y = 55,
.text = "",
.value = &context.year
},
{ //15: month
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 70,
.y = 55,
.text = "",
.value = &context.month
},
{ //16: date
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 88,
.y = 55,
.text = "",
.value = &context.date
}
};
int SETTINGS_SCREEN_items_idx = 0;
int SETTINGS_SCREEN_items_count = 8;
selectableItem SETTINGS_SCREEN_items[] = {
{ //0: go back
.action = []{
current_screen = MENU_SCREEN;
},
.x = 5,
.y = 4,
.text = "Go back!"
},
{ //1: save
.action = []{
current_screen = MENU_SCREEN;
// set clock
},
.x = 85,
.y = 4,
.text = "Save!"
},
{ //2: hour
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 40,
.y = 15,
.text = "",
.value = &context.hour
},
{ //3: minute
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 60,
.y = 15,
.text = "",
.value = &context.minute
},
{ //4: dayOfWeek
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 40,
.y = 25,
.text = "1"
},
{ //5: year
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 40,
.y = 35,
.text = "",
.value = &context.year
},
{ //6: month
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 70,
.y = 35,
.text = "",
.value = &context.month
},
{ //7: date
.action = []{ edit_mode_on = !edit_mode_on; },
.x = 88,
.y = 35,
.text = "",
.value = &context.date
}
};
void setup() {
u8g.setColorIndex(1); // set the color to white
u8g.setFontPosTop();
// 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
}
void loop()
{
if (current_screen == MENU_SCREEN)
{
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0))
{ // up button clicked - jump to previous menu item
button_up_clicked = 1; // set button to clicked to only perform the action once
MAIN_MENU_SCREEN_items_idx = MAIN_MENU_SCREEN_items_idx - 1; // select previous item
if (MAIN_MENU_SCREEN_items_idx < 0)
{ // if first item was selected, jump to last item
MAIN_MENU_SCREEN_items_idx = NUM_ITEMS-1;
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) button_up_clicked = 0; // unclick
if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0))
{ // down button clicked - jump to next menu item
button_down_clicked = 1; // set button to clicked to only perform the action once
MAIN_MENU_SCREEN_items_idx = MAIN_MENU_SCREEN_items_idx + 1; // select next item
if (MAIN_MENU_SCREEN_items_idx >= NUM_ITEMS)
{ // last item was selected, jump to first menu item
MAIN_MENU_SCREEN_items_idx = 0;
}
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) button_down_clicked = 0; // unclick
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0))
{ // unclick
button_select_clicked = 1;
current_screen = MAIN_MENU_SCREEN_items_idx+1;
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) button_select_clicked = 0; // unclick
}
if (current_screen == FEED_NOW_SCREEN)
{
selectedItem = &FEED_NOW_SCREEN_items[FEED_NOW_SCREEN_items_idx];
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0))
{ // up button clicked - jump to previous menu item
button_up_clicked = 1;
if (edit_mode_on)
{
(*(selectedItem->value))--;
}
else if (FEED_NOW_SCREEN_items_idx != 0)
{
FEED_NOW_SCREEN_items_idx--; // select previous item
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) button_up_clicked = 0; // unclick
if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0))
{ // down button clicked - jump to next menu item
button_down_clicked = 1;
if (edit_mode_on)
{
(*(selectedItem->value))++;
}
else if (FEED_NOW_SCREEN_items_idx < FEED_NOW_SCREEN_items_count - 1)
{
FEED_NOW_SCREEN_items_idx++; // select previous item
}
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) button_down_clicked = 0; // unclick
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0))
{ // select button clicked
button_select_clicked = 1; // set button to clicked to only perform the action once
selectedItem->action();
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) button_select_clicked = 0; // unclick
}
if (current_screen == FEED_LATER_SCREEN)
{
selectedItem = &FEED_LATER_SCREEN_items[FEED_LATER_SCREEN_items_idx];
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0))
{ // up button clicked - jump to previous menu item
button_up_clicked = 1;
if ((FEED_LATER_SCREEN_feedingTime_idx != 0 && FEED_LATER_SCREEN_items_idx == 2) || FEED_LATER_SCREEN_items_idx == 0) ; //do nothing
else FEED_LATER_SCREEN_items_idx--;
if (FEED_LATER_SCREEN_items_idx >= 2)
{
// Select previous feeding time if there is one
if (FEED_LATER_SCREEN_feedingTime_idx - 1 >= 0)
{
FEED_LATER_SCREEN_feedingTime_idx--;
selectedFeedingTime = &feedingTimes[FEED_LATER_SCREEN_feedingTime_idx];
// Is redrawing needed?
if (FEED_LATER_SCREEN_items_idx == 2)
{
int print_idx = FEED_LATER_SCREEN_feedingTime_idx;
for (int i = 2; i <= 6; i++)
{
FEED_LATER_SCREEN_items[i].text = feedingTimes[print_idx].toString();
print_idx++;
}
}
}
}
// Move selection
//if (FEED_LATER_SCREEN_feedingTime_idx == 0 || FEED_LATER_SCREEN_items_idx != 0)
// FEED_LATER_SCREEN_items_idx = FEED_LATER_SCREEN_items_idx - 1;
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) button_up_clicked = 0; // unclick
if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0))
{ // down button clicked - jump to next menu item
button_down_clicked = 1;
if (FEED_LATER_SCREEN_items_idx >= 2) // First 2 item is not feedingTime
{
// Select next feeding time if there is one
if (FEED_LATER_SCREEN_feedingTime_idx < feedingTimes_count-1)
{
FEED_LATER_SCREEN_feedingTime_idx++;
selectedFeedingTime = &feedingTimes[FEED_LATER_SCREEN_feedingTime_idx];
// Is redrawing needed?
if (FEED_LATER_SCREEN_items_idx == 6)
{
int print_idx = FEED_LATER_SCREEN_feedingTime_idx-4;
for (int i = 2; i <= 6; i++)
{
FEED_LATER_SCREEN_items[i].text = feedingTimes[print_idx].toString();
print_idx++;
}
}
}
}
// Move selection unless last item
if (FEED_LATER_SCREEN_items_idx < FEED_LATER_SCREEN_items_count - 1)
FEED_LATER_SCREEN_items_idx++;
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) button_down_clicked = 0; // unclick
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0))
{ // select button clicked
button_select_clicked = 1; // set button to clicked to only perform the action once
selectedItem->action();
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) button_select_clicked = 0; // unclick
}
if (current_screen == SETTINGS_SCREEN)
{
selectedItem = &SETTINGS_SCREEN_items[SETTINGS_SCREEN_items_idx];
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0))
{ // up button clicked - jump to previous menu item
button_up_clicked = 1;
if (edit_mode_on)
{
(*(selectedItem->value))--;
}
else if (SETTINGS_SCREEN_items_idx != 0)
{
SETTINGS_SCREEN_items_idx--; // select previous item
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) button_up_clicked = 0; // unclick
if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0))
{ // down button clicked - jump to next menu item
button_down_clicked = 1;
if (edit_mode_on)
{
(*(selectedItem->value))++;
}
else if (SETTINGS_SCREEN_items_idx < SETTINGS_SCREEN_items_count - 1)
{
SETTINGS_SCREEN_items_idx++; // select previous item
}
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) button_down_clicked = 0; // unclick
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0))
{ // select button clicked
button_select_clicked = 1; // set button to clicked to only perform the action once
selectedItem->action();
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) button_select_clicked = 0; // unclick
}
if (current_screen == EDITOR_SCREEN)
{
selectedItem = &EDITOR_SCREEN_items[EDITOR_SCREEN_items_idx];
if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0))
{ // up button clicked - jump to previous menu item
button_up_clicked = 1;
if (edit_mode_on)
{
(*(selectedItem->value))--;
}
else if (EDITOR_SCREEN_items_idx != 0)
{
EDITOR_SCREEN_items_idx--; // select previous item
}
}
if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) button_up_clicked = 0; // unclick
if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0))
{ // down button clicked - jump to next menu item
button_down_clicked = 1;
if (edit_mode_on)
{
(*(selectedItem->value))++;
}
else if (EDITOR_SCREEN_items_idx < EDITOR_SCREEN_items_count - 1)
{
EDITOR_SCREEN_items_idx++; // select previous item
}
}
if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) button_down_clicked = 0; // unclick
if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0))
{ // select button clicked
button_select_clicked = 1; // set button to clicked to only perform the action once
selectedItem->action();
}
if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) button_select_clicked = 0; // unclick
}
// set correct values for the previous and next items
item_sel_previous = MAIN_MENU_SCREEN_items_idx - 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 = MAIN_MENU_SCREEN_items_idx + 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 == MENU_SCREEN) {
// selected item background
u8g.drawBitmapP(0, 22, 128/8, 20, bitmap_selector);
// draw previous item as icon + label
u8g.setFont(u8g_font_7x14);
u8g.drawStr(25, 15, menu_items[item_sel_previous]);
u8g.drawBitmapP( 4, 2, 16/8, 16, icons_array[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[MAIN_MENU_SCREEN_items_idx]);
u8g.drawBitmapP( 4, 24, 16/8, 16, icons_array[MAIN_MENU_SCREEN_items_idx]);
// 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, icons_array[item_sel_next]);
// draw scrollbar handle
u8g.drawBox(126, 64/NUM_ITEMS * MAIN_MENU_SCREEN_items_idx, 1, 64/NUM_ITEMS);
}
else if (current_screen == FEED_NOW_SCREEN) {
u8g.setFontPosTop();
u8g.setColorIndex(1);
u8g.setFont(u8g_font_7x14);
u8g.drawStr(26, 10, "Rations: ");
for (auto item : FEED_NOW_SCREEN_items)
{
u8g.drawStr(item.x, item.y, item.toString().c_str());
}
drawSelection(*selectedItem);
}
else if (current_screen == FEED_LATER_SCREEN)
{
u8g.setFontPosTop();
u8g.setColorIndex(1);
u8g.setFont(u8g_font_04b_03r);
//u8g.drawStr(55, 5, String(FEED_LATER_SCREEN_feedingTime_idx).c_str());
//u8g.drawStr(48, 5, String(FEED_LATER_SCREEN_items_idx).c_str());
for (auto item : FEED_LATER_SCREEN_items)
{
u8g.drawStr(item.x, item.y, item.toString().c_str());
}
drawSelection(*selectedItem);
}
else if (current_screen == SETTINGS_SCREEN)
{
u8g.setFontPosTop();
u8g.setColorIndex(1);
u8g.setFont(u8g_font_04b_03r);
u8g.drawStr(8, 15, "Time:");
u8g.drawStr(8, 25, "Day:");
u8g.drawStr(8, 35, "Date:");
for (auto item : SETTINGS_SCREEN_items)
{
u8g.drawStr(item.x, item.y, item.toString().c_str());
}
drawSelection(*selectedItem);
}
else if (current_screen == EDITOR_SCREEN)
{
u8g.setFontPosTop();
u8g.setColorIndex(1);
u8g.setFont(u8g_font_04b_03r);
u8g.drawStr(8, 15, "Enabled:");
u8g.drawStr(66, 15, "Type:");
u8g.drawStr(8, 25, "Rations:");
u8g.drawStr(8, 35, "Time:");
u8g.drawStr(8, 45, "Days:");
u8g.drawStr(8, 55, "Date:");
for (auto item : EDITOR_SCREEN_items)
{
u8g.drawStr(item.x, item.y, item.toString().c_str());
}
drawSelection(*selectedItem);
}
} while ( u8g.nextPage() ); // required for page drawing mode with u8g library
}