Menu dan submenu LCD TFT dengan arduino

Sistem menu bertingkat (menu dan sub menu) adalah sistem pilihan/pengaturan yang terstruktur dalam kelompok-kelompok (sub menu).

Menu arduino juga bisa diterapkan pada lcd TFT (2.4″). Keunggulan sistem menu ini adalah pengaturan item menu bisa dengan mudah dimodifikasi, karena disusun dalam ‘struct’.

 
komponen yang digunakan:

  1. Arduino Mega 2560
  2. LCD TFT 2.4″

Pengaturan menu

menu dalam program ini menggunakan struktur :

struct Menu
{
  byte tipe;
  void *variabel;
  uint16_t nilaiMin;
  uint16_t nilaiMax;
  void *subMenu;
};

struktur menu harus dibuat mengikuti struktur diatas yaitu:

  1. tipe dapat berupa UInt8, UInt16, Float, textDropDown, subMenu, dll
  2. variabel merupakan alamat dari nilai setting sesuai tipe yang diberikan
  3. nilaiMin dan nilaiMax merupakan batas setting.
  4. subMenu alamat struktur menu apabila tipenya adalah subMenu.

coding arduino menu tft lcd:

#define LCD_CS                A3
#define LCD_CD                A2
#define LCD_WR                A1
#define LCD_RD                A0

#define LCD_RESET             A4

#define YP                    A1
#define XM                    A2
#define YM                    7
#define XP                    6

#define jumlahLevelMenu       2
#define panjangTextMenu       17
#define jumlahMenuDalamSatuLayar         4

#define lebarKolom1           210
#define tengahKolom1          (lebarKolom1/2)
#define tinggiBaris1          197
#define lebarKolom2           106
#define tengahKolom2          (214 + (lebarKolom2/2))
#define ringXPos              0
#define ringYPos              0
#define ringRadius            100

#define TS_MINX 130
#define TS_MINY 141
#define TS_MAXX 920
#define TS_MAXY 935

#define TS_MINPRESSURE 10
#define TS_MAXPRESSURE 1000

//========================================================
#include <Adafruit_GFX.h>
#include <SPFD5408_Adafruit_TFTLCD.h>
#include <SPFD5408_TouchScreen.h>

#define BLACK   0x0000
#define WHITE   0xFFFF
#define RED     0xF800
#define GREEN   0x07E0
#define BLUE    0x001F
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define GREY    0x2108

#define RED2RED 0
#define GREEN2GREEN 1
#define BLUE2BLUE 2
#define BLUE2RED 3
#define GREEN2RED 4
#define RED2GREEN 5

enum MenuMode
{
  UInt8,
  UInt16,
  Float,
  textDropDown,
  subMenu,
  commandSettingPabrik,
};

struct Menu
{
  byte tipe;
  void *variabel;
  uint16_t nilaiMin;
  uint16_t nilaiMax;
  void *subMenu;
};

struct MenuIndex
{
  byte index;
  char *menutext;
  Menu *menu;
  byte showIndex;
  byte menuLength;
  char *dropDown;
  byte dropDownLength;
};

struct Setting
{
  byte lampu;
  byte alarm;
  byte kipas;
  byte kontras;
  byte kecerahan;
  byte suhuSet;
  byte kelembabanSet;
  byte rollerMode;
  long rollerJeda;
  long rollerDurasi;
  long istirahatMode;
  long istirahatkipas;
  long istirahatJeda;
  long istirahatDurasi;
  byte lampuLatar;
  byte humidifier;
  long rollerSebelumnya;
  long istirahatSebelumnya;
  byte tombol;
};

struct TouchScreenKode
{
  uint16_t x1;
  uint16_t y1;
  uint16_t x2;
  uint16_t y2;
  byte kode;
};

//variabel
bool aktif;
float suhu;
float kelembaban;

uint16_t intensitasCahaya;
uint16_t aliranUdara;
uint16_t levelSuara;
uint16_t warnaLampu;

uint8_t jam;
uint8_t menit;
uint8_t detik;
uint8_t hari;
uint8_t tanggal;
uint8_t bulan;
uint8_t tahun;

Setting setting;

//Dropdown menu
const char aktifText[][panjangTextMenu] PROGMEM =
{
  "Tidak",
  "Ya",
};
const char pilihanBatalLanjut[][panjangTextMenu] PROGMEM  =
{
  "Batal",
  "Lanjut",
};
const char pilihanHidupMati[][panjangTextMenu] PROGMEM  =
{
  "Hidup",
  "Mati",
};
const char pilihanHidupMatiAuto[][panjangTextMenu] PROGMEM  =
{
  "Hidup",
  "Mati",
  "Auto",
};

const char pilihanKipas[][panjangTextMenu] PROGMEM =
{
  "Hidup",
  "Mati",
  "Humidity",
  "Lampu",
};

const char pilihanAlarm[][panjangTextMenu] PROGMEM =
{
  "Temp",
  "roll",
  "istrh",
  "Mati"
};

const char menuStrWaktu[][panjangTextMenu] PROGMEM =
{
  "1. Jam",
  "2. Menit",
  "3. Detik",
  "4. Tanggal",
  "5. Bulan",
  "6. Tahun",
};

//Sub menu
//tipe            variabel  nilaiMin nilaiMax submenu  jumlahBaris
const Menu menuWaktu[] =
{
  {UInt8         , &jam     , 1     , 24    , 0 },
  {UInt8         , &menit   , 0     , 59    , 0 },
  {UInt8         , &detik   , 0     , 59    , 0 },
  {UInt8         , &tanggal , 1     , 31    , 0 },
  {UInt8         , &bulan   , 1     , 12    , 0 },
  {UInt8         , &tahun   , 0     , 99    , 0 },
};

const char menuStrPeralatan[][panjangTextMenu] PROGMEM =
{
  "1. Kipas",
  "2. Alarm",
  "3. Kontras",
  "4. Kecerahan",
  "5. Lampu Latar",
  "6. Bunyi Tmbol",
};

const Menu menuPeralatan[] =
{
  {textDropDown  , &setting.kipas      , 0     , (sizeof(pilihanKipas) / sizeof(pilihanKipas[0]) - 1)                , &pilihanKipas         },
  {textDropDown  , &setting.alarm      , 0     , (sizeof(pilihanAlarm) / sizeof(pilihanAlarm[0]) - 1)                  , &pilihanAlarm         },
  {UInt8         , &setting.kontras    , 0     , 99                                                                  , 0                     },
  {UInt8         , &setting.kecerahan  , 0     , 99                                                                  , 0                     },
  {textDropDown  , &setting.lampuLatar , 0     , (sizeof(pilihanHidupMatiAuto) / sizeof(pilihanHidupMatiAuto[0]) - 1)  , &pilihanHidupMatiAuto },
  {textDropDown  , &setting.tombol     , 0     , (sizeof(pilihanHidupMati) / sizeof(pilihanHidupMati[0]) - 1)          , &pilihanHidupMati     },
};

const char menuStrRoller[][panjangTextMenu] PROGMEM =
{
  "1. Mode",
  "2. Jeda (jam)",
  "3. Lama(menit)",
};

const Menu menuRoller[] =
{
  {textDropDown  , &setting.rollerMode      , 0     , (sizeof(pilihanHidupMati) / sizeof(pilihanHidupMati[0])) - 1     , &pilihanHidupMati  },
  {UInt8         , &setting.rollerJeda      , 1     , 24                                                               , 0                  },
  {UInt8         , &setting.rollerDurasi    , 1     , 59                                                               , 0                  },
};

const char menuStrIstirahat[][panjangTextMenu] PROGMEM =
{
  "1. Istirahat",
  "2. Kipas",
  "3. Jeda (jam)",
  "4. Lama(menit)",
};

const Menu menuIstirahat[] =
{
  {textDropDown  , &setting.istirahatMode    , 0     , (sizeof(pilihanHidupMati) / sizeof(pilihanHidupMati[0])) - 1    , &pilihanHidupMati },
  {textDropDown  , &setting.istirahatkipas   , 0     , (sizeof(pilihanHidupMati) / sizeof(pilihanHidupMati[0])) - 1    , &pilihanHidupMati },
  {UInt8         , &setting.istirahatJeda    , 10    , 23                                                              , 0                 },
  {UInt8         , &setting.istirahatDurasi  , 1     , 59                                                              , 0                 },
};

//Menu utama
const char menuStrUtama[][panjangTextMenu] PROGMEM  =
{
  "1.Waktu",
  "2.Peralatan",
  "3.Temperatur",
  "4.Kelembaban",
  "5.Roller",
  "6.Istirahat",
  "7.Set. pabrik",
};

const Menu menuUtama[] =
{
  {subMenu                , &menuStrWaktu          , 0    , sizeof(menuWaktu) / sizeof(menuWaktu[0])                    , &menuWaktu          },
  {subMenu                , &menuStrPeralatan      , 0    , sizeof(menuPeralatan) / sizeof(menuPeralatan[0])            , &menuPeralatan      },
  {UInt8                  , &setting.suhuSet       , 0    , 99                                                          , 0                   },
  {UInt8                  , &setting.kelembabanSet , 0    , 99                                                          , 0                   },
  {subMenu                , &menuStrRoller         , 0    , sizeof(menuRoller) / sizeof(menuRoller[0])                  , &menuRoller         },
  {subMenu                , &menuStrIstirahat      , 0    , sizeof(menuIstirahat) / sizeof(menuIstirahat[0])            , &menuIstirahat      },
  {commandSettingPabrik   , 0                      , 0    , sizeof(pilihanBatalLanjut) / sizeof(pilihanBatalLanjut[0])  , &pilihanBatalLanjut },
};
//========================================================



TouchScreenKode tcKodeIdle[] = {
  {305, 730, 191, 943, 'M'},//menu utama
  {670, 716, 319, 928, 'T'},
  {867, 717, 724, 931, 'W'},
};
TouchScreenKode tcKodeMenu[] = {
  {745, 180, 692, 660, '1'},
  {634, 180, 554, 660, '2'},
  {511, 180, 442, 660, '3'},
  {390, 180, 316, 660, '4'},
  {263, 189, 176, 424, '<'},
  {263, 444, 190, 667, '>'},
  {305, 730, 191, 943, 'B'},
};

TouchScreenKode tcKodeEdit[] = {
  {416, 297, 327, 547, 'S'},
  {263, 189, 176, 424, '-'},
  {263, 444, 190, 667, '+'},
  {305, 730, 191, 943, 'B'},
};


MenuIndex menuIndex[jumlahLevelMenu];

long millismenuText;
int8_t levelMenu = -1;
bool menuEntriNilai;
char *judulMenu;
byte judulMenuTampil;
byte menu_Value8;
uint16_t menu_Value16;
float menu_ValueFloat;

float suhuSebelumnya;
float kelembabanSebelumnya;

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

byte lebarText;
byte ukuranText;

bool statusLampu;
bool statusKipas;
bool statusHumidifier;
bool rollerStatus;
bool istirahatStatus;

long millisRoller;
long millisIstirahat;

bool alarmStatus;
bool alarmPinStatus;

void setup()
{
  Serial.begin(9600);
  Serial.println("Menu dan submenu menggunakan LCD TFT 2.4\" berbasis arduino");
  Serial.println("https://www.project.semesin.com/");
  Serial.println();
  
  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(1);

  idle();

  suhu = 32;
  kelembaban = 65;

  ambilDefault();
}

void loop()
{
  char tcKode = 0;
  if (levelMenu == -1)
  {
    tcKode = ambilKodeTouchScreen((TouchScreenKode*)&tcKodeIdle, sizeof(tcKodeIdle) / sizeof(TouchScreenKode));
  }
  else if (menuEntriNilai)
  {
    tcKode = ambilKodeTouchScreen((TouchScreenKode*)&tcKodeEdit, sizeof(tcKodeEdit) / sizeof(TouchScreenKode));
  }
  else
  {
    tcKode = ambilKodeTouchScreen((TouchScreenKode*)&tcKodeMenu, sizeof(tcKodeMenu) / sizeof(TouchScreenKode));
  }
  if (tcKode)
  {
    switch (tcKode)
    {
      case 'M':
        levelMenu++;
        menu_Display();
        break;
      case '>':
        menuIndex[levelMenu].showIndex++;
        if (menuIndex[levelMenu].showIndex > (menuIndex[levelMenu].menuLength - (jumlahMenuDalamSatuLayar / 2)))
        {
          menuIndex[levelMenu].showIndex = 0;
        }
        menu_ShowItem();
        break;
      case '<':
        if (menuIndex[levelMenu].showIndex == 0)
        {
          menuIndex[levelMenu].showIndex = (menuIndex[levelMenu].menuLength - (jumlahMenuDalamSatuLayar / 2));
        }
        else
        {
          menuIndex[levelMenu].showIndex--;
        }
        menu_ShowItem();
        break;
      case '1':
      case '2':
      case '3':
      case '4':
        menuIndex[levelMenu].index = menuIndex[levelMenu].showIndex + (tcKode - '1');
        levelMenu++;
        menu_Display();
        break;
      case 'B':
        menuEntriNilai = false;
        levelMenu--;
        menu_Display();
        break;
      case 'S':
        menu_EditSelesai();
        break;
      case '-':
        menu_KurangNilai();
        break;
      case '+':
        menu_TambahNilai();
        break;

    }
  }
}

void menu_Display()
{
  if (levelMenu == -1)
  {
    idle();
    menuIndex[levelMenu].dropDownLength = 0;
  }
  else if (levelMenu == 0)
  {
    menuIndex[levelMenu].index = 0;
    menuIndex[levelMenu].menutext = (char*)menuStrUtama;
    menuIndex[levelMenu].menu = menuUtama;
    menuIndex[levelMenu].showIndex = 0;
    menuIndex[levelMenu].menuLength = sizeof(menuUtama) / sizeof(menuUtama[0]);
    menuIndex[levelMenu].dropDownLength = 0;

    tft.fillRect(0, tinggiBaris1 + 4, 208, 35, BLACK);

    ukuranText = 3;
    tft.setFont();
    tft.setTextColor (WHITE, BLACK);

    tft.fillRect(0, 0, lebarKolom1, tinggiBaris1, BLACK);
    tft.setTextSize (ukuranText);
    lebarText = 10 * ukuranText * 6;
    tft.setCursor(tengahKolom1 - (lebarText / 2), 0);
    tft.print("MENU UTAMA");

    menu_TcMenu();
    menu_ShowItem();
  }
  else
  {
    char buf[panjangTextMenu];
    Menu menuLama = menuIndex[levelMenu - 1].menu[menuIndex[levelMenu - 1].index];

    ukuranText = 3;
    tft.setFont();
    tft.setTextColor (WHITE, BLACK);

    tft.fillRect(0, 0, lebarKolom1, ukuranText * 8, BLACK);
    tft.setTextSize (ukuranText);

    copyFlashString(buf, menuIndex[levelMenu - 1].menutext + (menuIndex[levelMenu - 1].index * panjangTextMenu));

    lebarText = strlen(buf) * ukuranText * 6;
    tft.setCursor(tengahKolom1 - (lebarText / 2), 0);
    tft.print(buf);

    switch (menuLama.tipe)
    {
      case UInt8:
      case textDropDown:
        menu_Value8 = *(uint8_t*)menuLama.variabel;
        menuEntriNilai = true;
        break;
      case UInt16:
        menu_Value16 = *(uint16_t*)menuLama.variabel;
        menuEntriNilai = true;
        break;
      case Float:
        menu_Value16 = *(float*)menuLama.variabel;
        menuEntriNilai = true;
        break;
      case subMenu:
        menuIndex[levelMenu].index = 0;
        menuIndex[levelMenu].menutext = menuLama.variabel;
        menuIndex[levelMenu].menu = menuLama.subMenu;
        menuIndex[levelMenu].showIndex = 0;
        menuIndex[levelMenu].menuLength = menuLama.nilaiMax;
        menuIndex[levelMenu].dropDownLength = 0;

        menu_TcMenu();
        menu_ShowItem();
        break;
      case commandSettingPabrik:
        menu_Value8 = 0;
        menuEntriNilai = true;
        break;
    }
    if (menuEntriNilai)
    {
      menu_TcEdit();
      menu_ShowNilai();
    }
  }
}
void menu_tcIdle()
{
  tft.fillRect(210, 200, 110, 40, YELLOW);
  ukuranText = 3;
  tft.setFont();
  tft.setTextColor (BLACK, YELLOW);
  tft.setTextSize (ukuranText);
  lebarText = 4 * ukuranText * 6;
  tft.setCursor(tengahKolom2 - (lebarText / 2), 208);
  tft.print("MENU");

}
void menu_TcMenu()
{
  tft.fillRect(0, tinggiBaris1 + 4, (lebarKolom1 / 2) - 2, 36, YELLOW);
  tft.fillRect((lebarKolom1 / 2) - 2, tinggiBaris1 + 4, 4, 40, BLUE);
  tft.fillRect((lebarKolom1 / 2) + 2, tinggiBaris1 + 4, (lebarKolom1 / 2) - 2, 36, YELLOW);
  tft.fillRect(lebarKolom1 + 4, tinggiBaris1 + 4, 106, 36, YELLOW);

  ukuranText = 3;
  tft.setFont();
  tft.setTextColor (BLACK, YELLOW);
  tft.setTextSize (ukuranText);
  lebarText = 1 * ukuranText * 6;
  tft.setCursor(((lebarKolom1 / 2) - lebarText) / 2, 208);
  tft.print("<");

  tft.setCursor((((lebarKolom1 / 2) - lebarText) / 2) + (lebarKolom1 / 2), 208);
  tft.print(">");


  tft.setTextSize (ukuranText);
  lebarText = 5 * ukuranText * 6;
  tft.setCursor(tengahKolom2 - (lebarText / 2), 208);
  tft.print("BALIK");
}

void menu_TcEdit()
{
  tft.fillRect(0, tinggiBaris1 - 44, lebarKolom1, 44, BLACK);
  tft.fillRect((lebarKolom1 / 4) - 4, tinggiBaris1 - 44 - 4, (lebarKolom1 / 2) + 8, 36 + 8, BLUE);
  tft.fillRect((lebarKolom1 / 4), tinggiBaris1 - 44, (lebarKolom1 / 2), 36, YELLOW);

  tft.fillRect(0, tinggiBaris1 + 4, (lebarKolom1 / 2) - 2, 36, YELLOW);
  tft.fillRect((lebarKolom1 / 2) - 2, tinggiBaris1 + 4, 4, 40, BLUE);
  tft.fillRect((lebarKolom1 / 2) + 2, tinggiBaris1 + 4, (lebarKolom1 / 2) - 2, 36, YELLOW);
  tft.fillRect(lebarKolom1 + 4, tinggiBaris1 + 4, 106, 36, YELLOW);

  ukuranText = 3;
  lebarText = 3 * ukuranText * 6;
  tft.setFont();
  tft.setTextColor (BLACK, YELLOW);
  tft.setTextSize (ukuranText);
  tft.setCursor((lebarKolom1 - lebarText) / 2, tinggiBaris1 - 40);
  tft.print("Set");

  lebarText = 1 * ukuranText * 6;
  tft.setCursor(((lebarKolom1 / 2) - lebarText) / 2, 208);
  tft.print("-");

  tft.setCursor((((lebarKolom1 / 2) - lebarText) / 2) + (lebarKolom1 / 2), 208);
  tft.print("+");


  tft.setTextSize (ukuranText);
  lebarText = 5 * ukuranText * 6;
  tft.setCursor(tengahKolom2 - (lebarText / 2), 208);
  tft.print("BALIK");
}
void menu_ShowItem()
{
  char buf[panjangTextMenu];
  byte indexMenuMulai;

  ukuranText = 3;
  tft.fillRect(0, ukuranText * 8, lebarKolom1, tinggiBaris1 - ukuranText * 8, BLACK);

  ukuranText = 2;
  tft.setTextSize (ukuranText);
  tft.setFont();
  tft.setTextColor (WHITE, BLACK);

  byte menuItemSize = min(jumlahMenuDalamSatuLayar, menuIndex[levelMenu].menuLength - menuIndex[levelMenu].showIndex);

  for ( byte i = 0; i < menuItemSize; i++)
  {
    byte showIndex = menuIndex[levelMenu].showIndex + i;
    tft.setTextSize (ukuranText);
    tft.setCursor(0, (i * ukuranText * 20) + 50);
    copyFlashString(buf, menuIndex[levelMenu].menutext + (showIndex * panjangTextMenu));
    tft.print(buf);

    char *alamat;

    switch (menuIndex[levelMenu].menu[showIndex].tipe)
    {
      case UInt8:
        itoa(*(uint8_t*)menuIndex[levelMenu].menu[showIndex].variabel, buf, 10);
        lebarText = strlen(buf) * ukuranText * 6;
        tft.setCursor(lebarKolom1 - (lebarText + 10), (i * ukuranText * 20) + 50);
        tft.print(buf);
        break;
      case UInt16:
        itoa(*(uint16_t*)menuIndex[levelMenu].menu[showIndex].variabel, buf, 10);
        lebarText = strlen(buf) * ukuranText * 6;
        tft.setCursor(lebarKolom1 - (lebarText + 10), (i * ukuranText * 20) + 50);
        tft.print(buf);
        break;
      case Float:
        dtostrf(*(float*)menuIndex[levelMenu].menu[showIndex].variabel, 6, 2, buf);
        lebarText = strlen(buf) * ukuranText * 6;
        tft.setCursor(lebarKolom1 - (lebarText + 10), (i * ukuranText * 20) + 50);
        tft.print(buf);
        break;
      case textDropDown:
        copyFlashString(buf, menuIndex[levelMenu].menu[showIndex].subMenu + (*(uint8_t*)menuIndex[levelMenu].menu[showIndex].variabel * panjangTextMenu));
        lebarText = strlen(buf) * ukuranText * 6;
        tft.setCursor(lebarKolom1 - (lebarText + 10), (i * ukuranText * 20) + 50);
        tft.print(buf);
        break;
      case subMenu:
        lebarText = 1 * ukuranText * 6;
        tft.setCursor(lebarKolom1 - (lebarText + 10), (i * ukuranText * 20) + 50);
        tft.print('>');
        break;
      case commandSettingPabrik:
        break;
    }
  }
}

void menu_ShowNilai()
{
  char buf[panjangTextMenu];

  tft.fillRect(0, 50, lebarKolom1, 100, BLACK);
  Menu menuEdit = menuIndex[levelMenu - 1].menu[menuIndex[levelMenu - 1].index];
  switch (menuEdit.tipe)
  {
    case UInt8:
      itoa(menu_Value8, buf, 10);
      break;
    case UInt16:
      itoa(menu_Value16, buf, 10);
      break;
    case Float:
      dtostrf(menu_ValueFloat, 6, 2, buf);
      break;
    case textDropDown:
    case commandSettingPabrik:
      copyFlashString(buf, menuEdit.subMenu + (menu_Value8 * panjangTextMenu));
      break;
  }
  ukuranText = 5;
  tft.setFont();
  tft.setTextColor (WHITE, BLACK);
  tft.setTextSize (ukuranText);
  lebarText = strlen(buf) * ukuranText * 6;

  tft.setCursor((lebarKolom1 - lebarText) / 2, 70);
  tft.print(buf);
}

void menu_TambahNilai()
{
  Menu menuEdit = menuIndex[levelMenu - 1].menu[menuIndex[levelMenu - 1].index];
  switch (menuEdit.tipe)
  {
    case UInt8:
    case textDropDown:
    case commandSettingPabrik:
      if (menu_Value8 < menuEdit.nilaiMax)
      {
        menu_Value8++;
      }
      else
      {
        menu_Value8 = menuEdit.nilaiMin;
      }
      break;
    case UInt16:
      if (menu_Value16 < menuEdit.nilaiMax)
      {
        menu_Value16++;
      }
      else
      {
        menu_Value16 = menuEdit.nilaiMin;
      }
      break;
    case Float:
      if (menu_Value8 < menuEdit.nilaiMax)
      {
        menu_ValueFloat += 0.1;
      }
      else
      {
        menu_ValueFloat = menuEdit.nilaiMin;
      }
      break;
  }
  menu_ShowNilai();

}
void menu_KurangNilai()
{
  Menu menuEdit = menuIndex[levelMenu - 1].menu[menuIndex[levelMenu - 1].index];
  switch (menuEdit.tipe)
  {
    case UInt8:
    case textDropDown:
    case commandSettingPabrik:
      if (menu_Value8 != menuEdit.nilaiMin)
      {
        menu_Value8--;
      }
      else
      {
        menu_Value8 = menuEdit.nilaiMax;
      }
      break;
    case UInt16:
      if (menu_Value16 != menuEdit.nilaiMax)
      {
        menu_Value16--;
      }
      else
      {
        menu_Value16 = menuEdit.nilaiMax;
      }
      break;
    case Float:
      if (menu_Value8 != menuEdit.nilaiMax)
      {
        menu_ValueFloat -= 0.1;
      }
      else
      {
        menu_ValueFloat = menuEdit.nilaiMax;
      }
      break;
  }
  menu_ShowNilai();
}
void menu_EditSelesai()
{
  Menu menuEdit = menuIndex[levelMenu - 1].menu[menuIndex[levelMenu - 1].index];

  switch (menuEdit.tipe)
  {
    case UInt8:
    case textDropDown:
      *(uint8_t*)menuEdit.variabel = menu_Value8;
      break;
    case UInt16:
      *(uint8_t*)menuEdit.variabel = menu_Value16;
      break;
    case Float:
      *(uint8_t*)menuEdit.variabel = menu_ValueFloat;
      break;
    case commandSettingPabrik:
      ambilDefault();
      break;
  }
  menuEntriNilai = false;

  tft.fillRect(0, 50, lebarKolom1, 100, BLACK);
  ukuranText = 3;
  tft.setFont();
  tft.setTextColor (WHITE, BLACK);
  tft.setTextSize (ukuranText);
  lebarText = strlen("Tersimpan") * ukuranText * 6;

  tft.setCursor((lebarKolom1 - lebarText) / 2, 70);
  tft.print("Tersimpan");

  delay(1000);

  levelMenu--;
  menu_Display();

}
void idle()
{
  tft.fillScreen(BLACK);
  tft.setFont();

  menu_tcIdle();
}

char ambilKodeTouchScreen(TouchScreenKode *tcKode, byte jumlahArea)
{
  TSPoint p = ts.getPoint();
  char returnValue = 0;
  if ((p.z > TS_MINPRESSURE ) && (p.z < TS_MAXPRESSURE))
  {
    for (byte i = 0; i < jumlahArea; i++)
    {
      if ((tcKode[i].x1 > p.x) && (tcKode[i].x2 < p.x) && (tcKode[i].y1 < p.y) && (tcKode[i].y2 > p.y))
      {
        byte tsCounter;
        do
        {
          p = ts.getPoint();
          if ((p.z < TS_MINPRESSURE ) || (p.z > TS_MAXPRESSURE))
          {
            tsCounter++;
          }
          else
          {
            tsCounter = 0;
          }
        }
        while (tsCounter < 20);
        returnValue = tcKode[i].kode;
        break;
      }
    }
  }

  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

  return returnValue;
}
void ambilDefault()
{
  setting.lampu = 2;
  setting.alarm = 0;
  setting.kipas = 2;
  setting.kontras = 55;
  setting.kecerahan = 100;
  setting.suhuSet = 30;
  setting.kelembabanSet = 80;
  setting.rollerMode = 0;
  setting.rollerJeda = 1;
  setting.rollerDurasi = 1;
  setting.istirahatMode = 0;
  setting.istirahatkipas = 0;
  setting.istirahatJeda = 1;
  setting.istirahatDurasi = 1;
  setting.lampuLatar = 0;
  setting.tombol = 0;
  setting.humidifier = 2;
}
byte copyFlashString(char* buf, const char* alamat)
{
  char c;
  byte l = 0;
  while (c = pgm_read_byte(alamat++))
  {
    *buf++ = c;
    l++;
  }
  *buf = 0;
  return l;

}

 
library yang digunakan :

  1. Adafruit_GFX_Library.zip
  2. SPFD5408.zip