#include <Wire.h>
#include <EEPROM.h>
// #include "IRLremote.h"
// #include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
#include <IRremote.h>
#define BUTTON_PIN A0
#define REMOTE_PIN 2
#define DS1307_ADDRESS 0x68
#define LCD_ADDRESS 0x27
#define STORE_CODE 20
// #define LCD_ADDRESS 0x3f
#define VIEW_HOME 1
#define VIEW_MENU 2
#define VIEW_INPUT 3
byte viewMode = 0;
#define SAVE_ALL 1
#define SAVE_CUSTOM 2
#define SAVE_CHANEL 3
#define FM_MAX_CHANNEL 15
#pragma region REMOTE Variable
// CNec IRLremote;
IRrecv receiver(REMOTE_PIN);
#define REMOTE_UP 2
#define REMOTE_LEFT 224
#define REMOTE_OK 168
#define REMOTE_RIGHT 144
#define REMOTE_DOWN 152
#define REMOTE_1 48 // 16738455
#define REMOTE_2 24 // 16750695
#define REMOTE_3 122 // 16756815
#define REMOTE_4 16 // 16724175
#define REMOTE_5 56 // 16718055
#define REMOTE_6 90 // 16743045
#define REMOTE_7 66 // 16716015
#define REMOTE_8 74 // 16726215
#define REMOTE_9 82 // 16734885
#define REMOTE_0 104 // 16730805
#define REMOTE_STAR 34
#define REMOTE_SHARP 194
#define REMOTE_EMPTY 0
#define KEY_UP 1
#define KEY_LEFT 2
#define KEY_OK 3
#define KEY_RIGHT 4
#define KEY_DOWN 5
#define KEY_1 6
#define KEY_2 7
#define KEY_3 8
#define KEY_4 9
#define KEY_5 10
#define KEY_6 11
#define KEY_7 12
#define KEY_8 13
#define KEY_9 14
#define KEY_0 15
#define KEY_STAR 16
#define KEY_SHARP 17
#define KEY_EMPTY 18
#pragma endregion
#pragma region LCD Variable;
// LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2);
LiquidCrystal lcd(12, 11, 5, 4, 3, 8);
struct LCDStruct
{
unsigned long timeDelayLight;
byte lightTime;
};
// struct LCDPrintStruct
//{
// bool isNew[2];
// char text[2][16];
// };
//
// LCDPrintStruct lcdPrint;
LCDStruct lcdCon = {
0, // timeDelay
15, // lightTime
};
#pragma endregion
#pragma region INPUT Variable
#define CHAR_EMPTY 0x00
#define INPUT_TYPE_TEXT 1
#define INPUT_TYPE_ARRAY 2
const char INPUT_SUYMBOL[] = "1.-+*/()#";
const char INPUT_CHAR[] = {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+*/()#< "};
const char INPUT_NUMBER[] = {"0123456789 "};
struct InputStructObj
{
char *symbol;
boolean isButtonPress;
unsigned long keyTimeDelay;
byte keyCurrent;
byte keyIndex;
char keyChar;
unsigned long cursorTimeDelay;
boolean isCursor;
String text;
String textOld;
String temp;
byte indexCursor;
byte maxCursorShow;
byte inputType;
byte arrayState;
byte arrayLength;
byte arrayIndex;
String arrayItems[FM_MAX_CHANNEL];
void (*callback)(String text);
boolean isUppercase;
boolean isOnlyNumber;
byte indexSymbol;
byte maxCursorSymbol;
byte indexChar;
};
InputStructObj input = {
"", // symbol
false, // isButtonPress
0, // keyTimeDelay
0, // keyCurrent
0, // keyIndex
CHAR_EMPTY, // keyChar
0, // cursorTimeDelay
false, // isCursor
"", // text
"", // textOld
"", // temp
0, // indexCursor
0, // maxCursorShow
INPUT_TYPE_TEXT, // inputType
0, // arrayState
0, // arrayLength
0, // arrayIndex
{}, // arrayItems
NULL, // callback
false, // isUppercase
false, // isOnlyNumber
0, // indexSymbol
16, // maxCursorSymbol
0, // indexChar
};
#pragma endregion
#pragma region MENU Variable
struct MenuStructObj
{
byte index; // menu current select
byte parentId; // open with parent
byte cursorLevel;
byte cursorIndex[10]; // save index menu
byte cursorOpened[10]; //
byte countShowMenu;
byte menuShow[10];
};
MenuStructObj menu = {
0, // index
0, // parentId
0, // cursorLevel
{}, // cursorIndex
{}, // cursorOpened
0, // countShowMenu
{} // menuShow
};
struct MenuStruct
{
byte menuId;
byte parentId;
byte labelIndex;
};
#define MENU_BEGIN 0
#define MENU_ACCEPT 255
#define MENU_EDIT_ARRAY 254
#define MENU_INPUT_MORE 253
#define MENU_ITEM_EDIT_ARRAY_ADD 101
#define MENU_ITEM_EDIT_ARRAY_EDIT 102
#define MENU_ITEM_EDIT_ARRAY_DELETE 103
#define MENU_ITEM_EDIT_ARRAY_BACK 104
#define MENU_ITEM_ACCEPT_OK 105
#define MENU_ITEM_ACCEPT_CANCEL 106
#define MENU_ITEM_CLOSE 107
#define MENU_ITEM_INPUT_MORE_SYMBOL 108
#define MENU_ITEM_INPUT_MORE_TOGGLE_UPPER_LOWCASE 109
#define MENU_ITEM_INPUT_MORE_TOGGLE_NUMBERIC 110
#define MENU_SYSTEM 1
#define MENU_ITEM_SYSTEM_LIGHT_TIME 2
#define MENU_ITEM_TIME 3
#define MENU_ITEM_DAY 4
#define MENU_RADIO 20
#define MENU_ITEM_RADIO_CHANNEL 21
const char *MENU_LABEL[] = {
/*00*/ "OK",
/*01*/ "Cancel",
/*02*/ "Close",
/*03*/ "Back",
/*04*/ "Add",
/*05*/ "Edit",
/*06*/ "Delete",
/*07*/ "Symbol char",
/*08*/ "Up/Lower case",
/*09*/ "Text/Number",
/*10*/ "System",
/*11*/ "LCD Light Time",
/*12*/ "Set Time",
/*13*/ "Set Day",
/*14*/ "Radio",
/*15*/ "Channel"
//
};
const MenuStruct MENU_LIST[] = {
/*0*/ {MENU_ITEM_ACCEPT_OK, MENU_ACCEPT, 0},
/*1*/ {MENU_ITEM_ACCEPT_CANCEL, MENU_ACCEPT, 1},
/*2*/ {MENU_ITEM_EDIT_ARRAY_BACK, MENU_EDIT_ARRAY, 3},
/*3*/ {MENU_ITEM_CLOSE, MENU_EDIT_ARRAY, 2},
/*4*/ {MENU_ITEM_EDIT_ARRAY_ADD, MENU_EDIT_ARRAY, 4},
/*5*/ {MENU_ITEM_EDIT_ARRAY_EDIT, MENU_EDIT_ARRAY, 5},
/*6*/ {MENU_ITEM_EDIT_ARRAY_DELETE, MENU_EDIT_ARRAY, 6},
/*8*/{MENU_ITEM_ACCEPT_OK, MENU_INPUT_MORE, 0},
/*9*/ {MENU_ITEM_ACCEPT_CANCEL, MENU_INPUT_MORE, 1},
/*7*/{MENU_ITEM_CLOSE, MENU_INPUT_MORE, 2},
/*10*/ {MENU_ITEM_INPUT_MORE_SYMBOL, MENU_INPUT_MORE, 7},
/*11*/ {MENU_ITEM_INPUT_MORE_TOGGLE_UPPER_LOWCASE, MENU_INPUT_MORE, 8},
/*12*/ {MENU_ITEM_INPUT_MORE_TOGGLE_NUMBERIC, MENU_INPUT_MORE, 9},
/*13*/ {MENU_SYSTEM, MENU_BEGIN, 10},
/*14*/ {MENU_ITEM_SYSTEM_LIGHT_TIME, MENU_SYSTEM, 11},
/*15*/ {MENU_ITEM_TIME, MENU_SYSTEM, 12},
/*16*/ {MENU_ITEM_DAY, MENU_SYSTEM, 13},
/*17*/ {MENU_RADIO, MENU_BEGIN, 14},
/*18*/ {MENU_ITEM_RADIO_CHANNEL, MENU_RADIO, 15}
//
};
#define MENU_COUNT_ALL sizeof(MENU_LIST) / sizeof(MENU_LIST[0])
#pragma endregion
#pragma region Button
struct buttonValueStruct
{
byte button;
short value;
byte adjust;
};
buttonValueStruct buttonValues[5] = {
{KEY_UP, 1023, 10},
{KEY_DOWN, 510, 10},
{KEY_LEFT, 339, 10},
{KEY_RIGHT, 254, 10},
{KEY_OK, 203, 10} //
};
byte buttonMapValue(short value)
{
for (byte i = 0; i < 5; i++)
if (abs(buttonValues[i].value - value) <= buttonValues[i].adjust)
return buttonValues[i].button;
return 255;
};
#pragma endregion
#pragma region Keyboard
#define KEYBOARD_DEBOUNCE 300
struct keyboardStruct
{
unsigned long timeDelay;
unsigned long timeRead;
unsigned long timeDebounce;
boolean isButton;
boolean isAvailable;
boolean isPressKey;
boolean isTriggerKeyup;
boolean isStop;
byte press;
byte pressCount;
};
keyboardStruct keyboard = {
0, // timeDelay;
0, // timeRead;
0, // timeDebounce;
false, // isButton;
false, // isAvailable;
false, // isPressKey
false, // isTriggerKeyup
false, // isStop
255, // press;
1, // pressCount
};
void keyboardProcess(byte key)
{
if (keyboard.isAvailable)
keyboard.timeDelay = keyboard.isAvailable = false;
if (keyboard.timeDelay != 0 && keyboard.timeDelay < millis())
keyboard.isAvailable = true;
if (keyboard.timeDebounce != 0 && keyboard.timeDebounce < millis())
{
keyboard.timeDebounce = 0;
keyboard.pressCount = 1;
}
if (key != 255)
{
if (keyboard.isStop && keyboard.isPressKey)
{
keyboard.isAvailable = false;
return;
}
keyboard.timeDelay = keyboard.timeDelay == 0 || keyboard.isTriggerKeyup ? millis() + 200 : keyboard.timeDelay;
keyboard.timeRead = keyboard.press == key && keyboard.timeDebounce > millis() && keyboard.isPressKey ? keyboard.timeRead : millis();
keyboard.pressCount = keyboard.isPressKey ? keyboard.pressCount
: keyboard.press == key && keyboard.timeDebounce > millis() ? keyboard.pressCount + 1
: 1;
keyboard.timeDebounce = millis() + KEYBOARD_DEBOUNCE;
keyboard.press = key;
keyboard.isPressKey = true;
}
else
{
keyboard.isStop = keyboard.isPressKey = false;
// keyboard.isAvailable = false;
}
};
#pragma endregion
#pragma region UTILS
void parse_float(float val, int &prefix, int &suffix)
{
prefix = int(val);
suffix = (val - prefix) * 1000;
}
int convertBCD2DEC(byte num)
{
return ((num / 16 * 10) + (num % 16));
}
int convertDEC2BCD(byte num)
{
return ((num / 10 * 16) + (num % 10));
}
String convertNumToStr(short num)
{
return convertNumToStr(num, 1);
}
String convertNumToStr(short num, byte type)
{
return //
type == 1 ? String(num) : //
type == 2 ? (num < 10 ? "0" : "") + String(num)
: //
type == 3 ? (num < 10 ? "00" : num < 100 ? "0"
: "") +
String(num)
: //
type == 4 ? (num < 10 ? "000" : num < 100 ? "00"
: num < 1000 ? "0"
: "") +
String(num)
: //
"" //
;
}
long convertTimeToSeconds(byte _hour, byte _minute, byte _seconds)
{
return (1000L * 60L * 60L * _hour) + (_minute * 60L * 1000L) + (_seconds * 1000L);
}
String getValueBySeparator(String data, char separator, byte index)
{
byte found = 0;
short strIndex[] = {0, -1};
byte maxIndex = data.length() - 1;
for (byte i = 0; i <= maxIndex && found <= index; i++)
{
if (data.charAt(i) == separator || i == maxIndex)
{
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
char *toLCDLine(short num)
{
return toLCDLine(String(num));
}
char *toLCDLine(String str)
{
char *text = " ";
str.toCharArray(text, 16);
return text;
}
byte findIndex(char *arr, char find)
{
for (byte i = 0; i < strlen(arr); i++)
{
if (arr[i] == find)
return i;
}
return 255;
}
byte findIndex(byte *arr, byte find)
{
for (byte i = 0; i < strlen(arr); i++)
{
if (arr[i] == find)
return i;
}
return 255;
}
#pragma endregion
#pragma region MENU
char *menuGetName(byte index)
{
// return menuNames[index];
// return MENU_LIST[index].name;
return MENU_LABEL[MENU_LIST[index].labelIndex];
}
MenuStruct menuFind(byte menuId)
{
for (byte i = 0; i < MENU_COUNT_ALL; i++)
if (menuId == MENU_LIST[i].menuId)
return MENU_LIST[i];
return;
};
boolean menuHasSub(byte menuId)
{
for (byte i = 0; i < MENU_COUNT_ALL; i++)
if (menuId == MENU_LIST[i].parentId)
return true;
return false;
}
void menuRender()
{
viewMode = VIEW_MENU;
menu.countShowMenu = 0;
for (byte i = 0; i < MENU_COUNT_ALL; i++)
{
if (MENU_LIST[i].parentId == menu.parentId)
{
menu.menuShow[menu.countShowMenu] = i;
menu.countShowMenu++;
}
}
lcd.clear();
lcd.noCursor();
lcd.setCursor(0, 0);
lcd.print(char(126));
lcd.setCursor(1, 0);
lcd.print(menuGetName(menu.menuShow[menu.index]));
lcd.setCursor(0, 1);
if (menu.index < menu.countShowMenu && menu.countShowMenu >= 2)
{
lcd.print(menuGetName(menu.menuShow[menu.index + 1 >= menu.countShowMenu ? 0 : menu.index + 1]));
}
}
void menuBack()
{
menu.cursorLevel--;
menu.index = menu.cursorIndex[menu.cursorLevel];
menu.parentId = menuFind(menu.cursorOpened[menu.cursorLevel]).parentId;
}
void menuPressKey(byte _press)
{
if (_press == KEY_UP || _press == KEY_DOWN)
{
menu.index = _press == KEY_UP ? //
menu.index == 0 ? menu.countShowMenu - 1 : menu.index - 1
: menu.index + 1 >= menu.countShowMenu ? 0 : menu.index + 1;
}
else if (_press == KEY_LEFT)
{
byte parentId = MENU_LIST[menu.menuShow[menu.index]].parentId;
if (parentId == MENU_BEGIN || parentId == MENU_ACCEPT || parentId == MENU_EDIT_ARRAY || parentId == MENU_INPUT_MORE)
{
if (parentId == MENU_BEGIN)
{
viewMode = VIEW_HOME;
}
return;
}
menuBack();
}
else if (_press == KEY_OK || _press == KEY_RIGHT)
{
byte menuId = MENU_LIST[menu.menuShow[menu.index]].menuId;
if (menuId < MENU_ITEM_EDIT_ARRAY_ADD)
{
menu.cursorIndex[menu.cursorLevel] = menu.index;
menu.cursorOpened[menu.cursorLevel] = menuId;
menu.cursorLevel++;
if (menuHasSub(menuId))
{
menu.parentId = menuId;
menu.index = 0;
}
else
{
menuOpen(menuId);
return;
}
}
else if (menuId == MENU_ITEM_INPUT_MORE_TOGGLE_UPPER_LOWCASE || menuId == MENU_ITEM_INPUT_MORE_TOGGLE_NUMBERIC || menuId == MENU_ITEM_INPUT_MORE_SYMBOL)
{
if (menuId == MENU_ITEM_INPUT_MORE_TOGGLE_UPPER_LOWCASE)
input.isUppercase = !input.isUppercase;
else if (menuId == MENU_ITEM_INPUT_MORE_TOGGLE_NUMBERIC)
input.isOnlyNumber = !input.isOnlyNumber;
else if (menuId == MENU_ITEM_INPUT_MORE_SYMBOL)
{
input.indexSymbol = 0;
input.maxCursorSymbol = 15;
input.symbol = keyboard.isButton ? input.isOnlyNumber ? INPUT_NUMBER : INPUT_CHAR : INPUT_SUYMBOL;
//input.symbol = String(INPUT_CHAR);
}
inputPrintLCD();
return;
}
else if (menuId == MENU_ITEM_EDIT_ARRAY_ADD || menuId == MENU_ITEM_EDIT_ARRAY_DELETE || menuId == MENU_ITEM_EDIT_ARRAY_EDIT || menuId == MENU_ITEM_EDIT_ARRAY_BACK)
{
if (menuId == MENU_ITEM_EDIT_ARRAY_BACK)
{
menuBack();
}
else
{
viewMode = VIEW_INPUT;
inputArrayMenuAction(menuId);
return;
}
}
else if (menuId == MENU_ITEM_ACCEPT_OK || menuId == MENU_ITEM_ACCEPT_CANCEL)
{
if (menuId == MENU_ITEM_ACCEPT_OK)
{
if (input.callback != NULL){
(*input.callback)(input.text);
Serial.println(input.text);
}
if (input.arrayState == MENU_ITEM_EDIT_ARRAY_DELETE || input.arrayState == MENU_ITEM_EDIT_ARRAY_ADD || input.arrayState == MENU_ITEM_EDIT_ARRAY_EDIT)
{
// byte tempIndex = input.arrayIndex;
menuOpen(menu.cursorOpened[menu.cursorLevel - 1]);
// input.arrayIndex = tempIndex;
// inputPrintLCD();
return;
}
}
// else
// {
// if (input.inputType == INPUT_TYPE_ARRAY || MENU_LIST[menu.menuShow[menu.index]].parentId == MENU_INPUT_MORE)
// {
// input.indexSymbol = 255;
// inputPrintLCD();
// return;
// }
// }
menuBack();
}
else if (menuId == MENU_ITEM_CLOSE)
{
inputPrintLCD();
return;
}
}
menuRender();
}
void systemSetLCD_TimeLight(String text)
{
lcdCon.lightTime = getValueBySeparator(text, '|', 0).toInt();
lcdCon.timeDelayLight = millis() + lcdCon.lightTime * 1000L;
// fish.eatTestTime = getValueBySeparator(txt, '|', 1).toInt();
}
String tempReplace = "";
void menuOpen(byte menuId){
menuOpen(menuId, 0);
}
void menuOpen(byte menuId, byte arrayIndex)
{
input.symbol = INPUT_SUYMBOL;
input.inputType = INPUT_TYPE_TEXT;
input.keyTimeDelay = 0;
input.callback = NULL;
input.keyChar = CHAR_EMPTY;
input.keyCurrent = 0;
input.text = F("");
input.temp = F("");
input.textOld = F("");
input.maxCursorShow = 15;
input.indexCursor = 0;
input.arrayIndex = arrayIndex;
input.arrayState = 0;
input.arrayLength = 0;
input.indexSymbol = 255;
input.isOnlyNumber = false;
input.maxCursorSymbol = 15;
input.isUppercase = false;
if (MENU_ITEM_SYSTEM_LIGHT_TIME == menuId)
{
tempReplace = F("0");
tempReplace.replace(F("0"), convertNumToStr(lcdCon.lightTime, 2));
// tempReplace.replace("{1}", convertNumToStr(fish.eatTestTime, 2));
input.text = tempReplace;
input.inputType = INPUT_TYPE_TEXT;
input.isOnlyNumber = true;
input.temp = F("**");
input.callback = &systemSetLCD_TimeLight;
inputPrintLCD();
}
else
{
menuOpenExtended(menuId);
}
}
#pragma endregion
#pragma region INPUT
#define KEYBOARD_NUM 10
// const char INPUT_SUYMBOL[] = "1.,'?!\"-()@/:_;+&%*=<>£€$¥•[]{}\\~^˙¡¿§#|";
const char INPUT_KEY_0[] = {"0 "};
const char INPUT_KEY_2[] = {"2abc"};
const char INPUT_KEY_3[] = {"3def"};
const char INPUT_KEY_4[] = {"4ghi"};
const char INPUT_KEY_5[] = {"5jkl"};
const char INPUT_KEY_6[] = {"6mno"};
const char INPUT_KEY_7[] = {"7pqrs"};
const char INPUT_KEY_8[] = {"8tuv"};
const char INPUT_KEY_9[] = {"9wxyz"};
struct inputKeyboardStruct
{
byte Id;
char *Values;
};
const inputKeyboardStruct NUM_WORDS[KEYBOARD_NUM]{
{KEY_0, INPUT_KEY_0},
{KEY_1, INPUT_SUYMBOL},
{KEY_2, INPUT_KEY_2},
{KEY_3, INPUT_KEY_3},
{KEY_4, INPUT_KEY_4},
{KEY_5, INPUT_KEY_5},
{KEY_6, INPUT_KEY_6},
{KEY_7, INPUT_KEY_7},
{KEY_8, INPUT_KEY_8},
{KEY_9, INPUT_KEY_9} //
};
void inputArrayMenuAction(byte menuId)
{
input.arrayState = menuId;
if (MENU_ITEM_EDIT_ARRAY_ADD == menuId || MENU_ITEM_EDIT_ARRAY_EDIT == menuId)
{
input.text = MENU_ITEM_EDIT_ARRAY_EDIT == menuId ? input.arrayItems[input.arrayIndex] : F("");
input.indexCursor = 0;
input.inputType = INPUT_TYPE_TEXT;
input.indexSymbol = 255;
inputPrintLCD();
}
else if (MENU_ITEM_EDIT_ARRAY_DELETE == menuId)
{
menu.parentId = MENU_ACCEPT;
menu.index = 0;
menuRender();
}
}
byte inputGetIndexCursor()
{
if (input.inputType == INPUT_TYPE_ARRAY)
{
input.arrayIndex = input.arrayLength == 0 ? 0 : //
input.arrayIndex == 255 ? input.arrayLength - 1
: //
input.arrayIndex >= input.arrayLength ? 0
: //
input.arrayIndex;
return input.arrayIndex;
}
else if (input.temp.length() > 0)
{
byte index = 255;
for (byte i = 0; i < input.temp.length(); i++)
{
if (input.temp.charAt(i) == '*')
index = index == 255 ? 0 : index + 1;
if (index == input.indexCursor)
return i;
}
input.indexCursor = input.indexCursor == 255 ? index : 0;
return inputGetIndexCursor();
}
else if (input.temp.length() <= 0)
{
input.indexCursor = input.indexCursor == 255 ? input.text.length() : //
input.indexCursor > input.text.length() ? 0
: //
input.indexCursor;
return input.indexCursor;
}
}
void inputPrintLCD()
{
viewMode = VIEW_INPUT;
lcd.clear();
if (input.indexSymbol == 255)
{
byte indexCursor = inputGetIndexCursor();
if (input.inputType == INPUT_TYPE_ARRAY)
{
input.text = input.arrayLength <= 0 ? F("Empty") : input.arrayItems[input.arrayIndex];
if (input.arrayLength > 0)
{
lcd.setCursor(0, 1);
lcd.print("Z - " + convertNumToStr(input.arrayIndex + 1));
}
}
else if (input.temp.length() > 0 && input.text.length() <= 0) // auto gen
{
for (byte i = 0; i < input.temp.length(); i++)
{
char c = input.temp.charAt(i);
input.text += c != '*' ? String(c) : String(char(165));
}
}
lcd.setCursor(0, 0);
if (input.text.length() < 16)
{
lcd.print(input.text);
lcd.setCursor(indexCursor, 0);
}
else
{
byte count = 255;
while ((indexCursor > input.maxCursorShow || indexCursor < input.maxCursorShow - 15) && count > 0)
{
count--;
input.maxCursorShow += indexCursor > input.maxCursorShow ? 1 : -1;
}
lcd.print(input.text.substring(input.maxCursorShow - 15, input.maxCursorShow + 1));
lcd.setCursor(indexCursor - input.maxCursorShow + 15, 0);
}
}
else if (input.indexSymbol != 255)
{
// lcd.setCursor(0, 1);
// lcd.print("SYMBOL SELECTOR");
lcd.setCursor(0, 0);
byte lengthSymbol = strlen(input.symbol);
if (lengthSymbol < 16)
{
lcd.print(input.symbol);
lcd.setCursor(input.indexSymbol, 0);
}
else
{
byte count = 255;
byte indexSymbol = input.indexSymbol;
while ((indexSymbol > input.maxCursorSymbol || indexSymbol < input.maxCursorSymbol - 15) && count > 0)
{
count--;
input.maxCursorSymbol += indexSymbol > input.maxCursorSymbol ? 1 : -1;
}
tempReplace = "";
for (byte i = input.maxCursorSymbol - 15; i < input.maxCursorSymbol + 1; i++){
Serial.println(*(input.symbol + i));
tempReplace += char(*(input.symbol + i));
}
Serial.println(tempReplace);
lcd.print(tempReplace);
lcd.setCursor(indexSymbol - input.maxCursorSymbol + 15, 0);
}
}
}
void inputCharProcess(char text)
{
byte indexCursor = inputGetIndexCursor();
if (input.temp.length() > 0)
{
input.text.setCharAt(indexCursor, text);
}
else
{
input.text = input.textOld.substring(0, indexCursor) + text + input.textOld.substring(indexCursor + 0, input.text.length());
}
inputPrintLCD();
}
void inputPressKey(byte _press)
{
input.isButtonPress = keyboard.isButton;
if (keyboard.isButton && (KEY_UP == _press || KEY_DOWN == _press))
{
byte length = input.isOnlyNumber ? strlen(INPUT_NUMBER) : strlen(INPUT_CHAR);
byte indexCursor = inputGetIndexCursor();
input.keyTimeDelay = millis() + 1000;
input.indexChar = findIndex(!input.isOnlyNumber ? INPUT_CHAR : INPUT_NUMBER, input.text.charAt(indexCursor));
input.indexChar = KEY_DOWN == _press ? (input.indexChar + 1 < length - 1 ? input.indexChar + 1 : 0)
: (input.indexChar == 0 ? length - 1 : input.indexChar - 1);
input.keyChar = (input.isOnlyNumber ? INPUT_NUMBER : INPUT_CHAR)[input.indexChar];
inputCharProcess(input.keyChar);
return;
}
else if (KEY_UP == _press || KEY_DOWN == _press)
{
if (
input.indexSymbol != 255 ||
input.text.length() < 16 || //
(KEY_UP == _press && input.maxCursorShow - 15 <= 0) || //
(KEY_DOWN == _press && input.maxCursorShow >= input.text.length() - 1) //
)
return;
input.maxCursorShow += KEY_UP == _press ? -1 : 1;
lcd.setCursor(0, 0);
lcd.print(input.text.substring(input.maxCursorShow - 15, input.maxCursorShow + 1));
return;
}
else if (KEY_LEFT == _press || KEY_RIGHT == _press)
{
if (input.indexSymbol != 255)
{
input.indexSymbol = KEY_RIGHT == _press ? //
input.indexSymbol >= strlen(input.symbol) - 1 ? 0 : input.indexSymbol + 1
: (input.indexSymbol == 0 ? strlen(input.symbol) - 1 : input.indexSymbol - 1);
}
else if (input.inputType == INPUT_TYPE_ARRAY)
input.arrayIndex = KEY_RIGHT == _press ? input.arrayIndex + 1 : input.arrayIndex == 0 ? 255
: input.arrayIndex - 1;
else
input.indexCursor = KEY_RIGHT == _press ? input.indexCursor + 1 : input.indexCursor == 0 ? 255
: input.indexCursor - 1;
inputPrintLCD();
return;
}
else if (KEY_OK == _press)
{
if (input.indexSymbol != 255)
{
Serial.println(input.symbol);
Serial.println(input.symbol[input.indexSymbol]);
char temp = input.symbol[input.indexSymbol];
input.indexSymbol = 255;
inputCharProcess(temp);
return;
}
else if (input.inputType == INPUT_TYPE_ARRAY)
menu.parentId = MENU_EDIT_ARRAY;
else
{
menu.parentId = keyboard.isButton ? MENU_INPUT_MORE : MENU_ACCEPT;
}
menu.index = 0;
menuRender();
return;
}
else if (KEY_STAR == _press)
{
menu.parentId = MENU_INPUT_MORE;
menu.index = 0;
menuRender();
return;
}
else if (KEY_SHARP == _press)
{
if (millis() < input.keyTimeDelay || input.inputType != INPUT_TYPE_TEXT)
return;
byte indexCursor = inputGetIndexCursor();
if (input.temp.length() > 0)
{
input.text = input.text.substring(0, indexCursor) + ' ' + input.text.substring(indexCursor + 1, input.text.length());
}
else
{
input.text = indexCursor < input.text.length() ? //
indexCursor == 0 ? input.text : input.text.substring(0, indexCursor - 1) + "" + input.text.substring(indexCursor, input.text.length()) //
: input.text.length() > 1 ? input.text.substring(0, input.text.length() - 1) : "";
input.indexCursor -= input.indexCursor == 0 ? 0 : 1;
}
}
else
{
boolean isKeyPressChange = input.keyCurrent != _press;
if (!input.isOnlyNumber && (isKeyPressChange && input.keyChar != CHAR_EMPTY))
{
inputCharProcess(input.keyChar);
input.indexCursor++;
input.keyChar = CHAR_EMPTY;
input.keyTimeDelay = 0;
}
if (millis() > input.keyTimeDelay || isKeyPressChange)
{
input.keyIndex = input.isOnlyNumber ? 0 : 1;
input.textOld = input.text;
}
else
{
input.keyIndex += !input.isOnlyNumber ? 1 : 0;
}
input.keyCurrent = _press;
input.keyTimeDelay = millis() + 1000;
for (byte i = 0; i < KEYBOARD_NUM; i++)
{
if (NUM_WORDS[i].Id == _press)
{
if (input.keyIndex >= strlen(NUM_WORDS[i].Values))
input.keyIndex = 0;
char _char = input.keyChar = input.isUppercase ? toupper(NUM_WORDS[i].Values[input.keyIndex]) : NUM_WORDS[i].Values[input.keyIndex];
inputCharProcess(_char);
if (input.isOnlyNumber)
input.indexCursor++;
break;
}
}
}
inputPrintLCD();
}
void inputProcess()
{
if (viewMode != VIEW_INPUT)
return;
if (millis() >= input.cursorTimeDelay && input.inputType != INPUT_TYPE_ARRAY)
{
input.isCursor ? lcd.noCursor() : lcd.cursor();
input.isCursor = !input.isCursor;
input.cursorTimeDelay = millis() + 500;
}
if (millis() > input.keyTimeDelay && input.keyTimeDelay != 0)
{
input.keyTimeDelay = 0;
input.keyChar = CHAR_EMPTY;
if (input.isButtonPress && input.keyChar == '<')
{
inputPressKey(KEY_SHARP);
}
else if (!input.isButtonPress && !input.isOnlyNumber)
{
input.indexCursor++;
inputPrintLCD();
}
input.isButtonPress = false;
}
}
#pragma endregion
#pragma region Time
const char *TIME_DAY[] = {
"Sun",
"Mon",
"Tue",
"Web",
"Thu",
"Fri",
"Sat",
};
const char *TIME_MONTH[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
struct timeConfigStruct
{
byte hour;
byte minutes;
byte seconds;
byte wday;
byte day;
byte month;
byte year;
};
timeConfigStruct time = {
0, // hour
0, // minutes
0, // seconds
0, // wday
0, // day
1, // month
1, // year
};
void timeSet(byte hr, byte min, byte sec, byte wd, byte d, byte mth, byte yr)
{
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(byte(0x00));
Wire.write(convertDEC2BCD(sec));
Wire.write(convertDEC2BCD(min));
Wire.write(convertDEC2BCD(hr));
Wire.write(convertDEC2BCD(wd)); // day of week: Sunday = 1, Saturday = 7
Wire.write(convertDEC2BCD(d));
Wire.write(convertDEC2BCD(mth));
Wire.write(convertDEC2BCD(yr));
Wire.endTransmission();
}
void timeRead()
{
Wire.beginTransmission(DS1307_ADDRESS);
// if (Wire.endTransmission() == 1)
// {
Wire.write((byte)0x00);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
time.seconds = convertBCD2DEC(Wire.read() & 0x7f);
time.minutes = convertBCD2DEC(Wire.read());
time.hour = convertBCD2DEC(Wire.read() & 0x3f); // chế độ 24h.
time.wday = convertBCD2DEC(Wire.read());
time.day = convertBCD2DEC(Wire.read());
time.month = convertBCD2DEC(Wire.read());
time.year = convertBCD2DEC(Wire.read());
// }
// else
// {
// time.seconds = time.minutes = time.hour = time.wday = time.day = time.month = time.year = 0;
// }
// rtc.formatTime();
// time.hour = rtc.getHour();
// time.minutes = rtc.getMinute();
// time.seconds = rtc.getSecond();
// time.wday = rtc.getWeekday();
// time.day = rtc.getDay();
// time.month = rtc.getMonth();
// time.year = rtc.getYear();
}
void timeSetTimeMenu(String text)
{
byte h = getValueBySeparator(text, ':', 0).toInt();
byte m = getValueBySeparator(text, ':', 1).toInt();
byte s = getValueBySeparator(text, ':', 2).toInt();
// rtc.setTime(h, m, s);
timeSet(h, m, s, time.wday, time.day, time.month, time.year);
}
void timeSetDateMenu(String text)
{
// text = text.substring(9, text.length());
byte wd = getValueBySeparator(text, ',', 0).toInt();
text = text.substring(2, text.length());
byte d = getValueBySeparator(text, '/', 0).toInt();
byte m = getValueBySeparator(text, '/', 1).toInt();
byte y = getValueBySeparator(text, '/', 2).toInt() - 2000;
// day, weekday, month, century(1=1900, 0=2000), year(0-99)
// rtc.setDate(d, wd, m, 0, y);
timeSet(time.hour, time.minutes, time.seconds, wd, d, m, y);
}
#pragma endregion
#pragma region Home
#define HOME_COUNT 3
struct homeConfigStruct
{
unsigned long timeDelay;
byte index;
};
struct homeScreenStruct
{
char text[16];
byte dataCurrent;
void (*process)(byte _press);
};
homeScreenStruct homeScreen[HOME_COUNT] = {
{"", 0, &homeFmProcess}, // FM
{"", 0, &homeRam}, // RAM
{"", 0, &I2CScanner}, // I2CScanner
// {"", 0, &buttonRead}, //button read
};
homeConfigStruct home = {
0, // timeDelay
0, // index
};
void homeRam()
{
strncpy(homeScreen[home.index].text, toLCDLine(getMemoryFree()), 16);
}
void buttonRead()
{
strncpy(homeScreen[home.index].text, toLCDLine(analogRead(BUTTON_PIN)), 16);
}
short getMemoryFree()
{
extern int __heap_start;
extern int *__brkval;
return (int)SP - (__brkval == 0 ? (int)&__heap_start : (int)__brkval);
}
void I2CScanner()
{
tempReplace = F("");
for (byte address = 1; address < 127; address++)
{
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
if (error == 0)
tempReplace += (tempReplace == "" ? "" : " ") + String(address, HEX);
}
strncpy(homeScreen[home.index].text, toLCDLine(tempReplace), 16);
}
void homePressKey(byte _press)
{
if (KEY_UP == _press || KEY_DOWN == _press)
{
homeScreen[home.index].dataCurrent = KEY_UP == _press ? (homeScreen[home.index].dataCurrent == 255 ? 0 : homeScreen[home.index].dataCurrent + 1)
: (homeScreen[home.index].dataCurrent == 0 ? 255 : homeScreen[home.index].dataCurrent - 1);
(*homeScreen[home.index].process)(0);
home.timeDelay = millis() - 1;
}
else if (KEY_LEFT == _press || KEY_RIGHT == _press)
{
lcd.clear();
home.index = KEY_LEFT == _press ? (home.index == 0 ? HOME_COUNT - 1 : home.index - 1)
: (home.index >= HOME_COUNT - 1 ? 0 : home.index + 1);
(*homeScreen[home.index].process)(0);
home.timeDelay = millis() - 1;
}
else if (KEY_OK == _press && ((keyboard.isButton && keyboard.pressCount > 5) || (!keyboard.isButton && keyboard.pressCount > 25)))
{
keyboard.isStop = true;
viewMode = VIEW_MENU;
menu.index = 0;
menu.parentId = MENU_BEGIN;
menuRender();
}
else if (KEY_SHARP == _press)
{
}
else
{
(*homeScreen[home.index].process)(_press);
}
}
void homeProcess()
{
if (viewMode != VIEW_HOME || millis() < home.timeDelay)
return;
home.timeDelay = millis() + 150;
lcd.setCursor(0, 0);
//timeRead();
tempReplace = F("{0}:{1}:{2} {3} {4}");
tempReplace.replace("{0}", convertNumToStr(time.hour, 2));
tempReplace.replace("{1}", convertNumToStr(time.minutes, 2));
tempReplace.replace("{2}", convertNumToStr(time.seconds, 2));
tempReplace.replace("{3}", convertNumToStr(time.day, 2));
tempReplace.replace("{4}", time.month <= 11 && time.month >= 0 ? String(TIME_MONTH[time.month - 1]) : "NIL");
lcd.print(tempReplace);
if (String(homeScreen[home.index].text).length() <= 0)
{
(*homeScreen[home.index].process)(0);
}
//
lcd.setCursor(0, 1);
lcd.print(String(char(126)) + homeScreen[home.index].text);
}
#pragma endregion
#pragma region REMOTE
byte lastRemote;
void keyProcess()
{
if (millis() > lcdCon.timeDelayLight && lcdCon.timeDelayLight != 0)
{
lcdCon.timeDelayLight = 0;
//lcd.noBacklight();
}
byte KEY = 255;//buttonMapValue(analogRead(BUTTON_PIN));
if (KEY != 255)
keyboard.isButton = true;
// else if (IRLremote.available())
else if (receiver.decode())
{
keyboard.isButton = true;
// long remoteValue = (IRLremote.read()).command;
long remoteValue = receiver.decodedIRData.command;
//Serial.println(remoteValue);
receiver.resume();
KEY = remoteValue == REMOTE_UP ? KEY_UP
: remoteValue == REMOTE_LEFT ? KEY_LEFT
: remoteValue == REMOTE_OK ? KEY_OK
: remoteValue == REMOTE_RIGHT ? KEY_RIGHT
: remoteValue == REMOTE_DOWN ? KEY_DOWN
: remoteValue == REMOTE_0 ? KEY_0
: remoteValue == REMOTE_1 ? KEY_1
: remoteValue == REMOTE_2 ? KEY_2
: remoteValue == REMOTE_3 ? KEY_3
: remoteValue == REMOTE_4 ? KEY_4
: remoteValue == REMOTE_5 ? KEY_5
: remoteValue == REMOTE_6 ? KEY_6
: remoteValue == REMOTE_7 ? KEY_7
: remoteValue == REMOTE_8 ? KEY_8
: remoteValue == REMOTE_9 ? KEY_9
: remoteValue == REMOTE_STAR ? KEY_STAR
: remoteValue == REMOTE_SHARP ? KEY_SHARP
: remoteValue == REMOTE_EMPTY ? KEY_EMPTY
: 255;
if (KEY != 255)
if (KEY != KEY_EMPTY)
lastRemote = KEY;
else
KEY = lastRemote;
}
// else if (IRLremote.receiving())
// {
// KEY = lastRemote;
// }
keyboardProcess(KEY);
if (keyboard.isAvailable)
{
// Serial.println("isButton:" + String(keyboard.isButton) + " button:" + String(keyboard.press) + " hold:" + String(millis() - keyboard.timeRead) + " count:" + keyboard.pressCount);
keyPress(keyboard.press);
keyboard.isButton = false;
}
};
void keyPress(byte _press)
{
//lcd.backlight();
lcdCon.timeDelayLight = millis() + lcdCon.lightTime * 1000L;
if (viewMode == VIEW_HOME)
{
homePressKey(_press);
}
else if (viewMode == VIEW_MENU)
{
menuPressKey(_press);
}
else if (viewMode == VIEW_INPUT)
{
inputPressKey(_press);
}
};
#pragma endregion
#pragma region FM
#define FM_ADDRESS 0x60
byte fmChannelCount = 10;
struct fmChannelStruct
{
char Name[11];
char Value[6];
};
fmChannelStruct fmChannelWithName[FM_MAX_CHANNEL] = {
{
"VOV 89",
"089.0",
},
{
"Ha Noi",
"090.0",
},
{
"VOV GT",
"091.0",
},
{
"Xone",
"096.0",
},
{
"VOV 2",
"096.5",
},
{
"Joy FM",
"098.9",
},
{
"VOV 1",
"100.0",
},
{
"VOV 3",
"102.7",
},
{
"VOV 24/7",
"104.0",
},
{
"VOV 5",
"105.5",
},
};
float fmCustomFrequency = 87.5f;
byte *fmReadStatus()
{
byte reception_data[5];
Wire.requestFrom(FM_ADDRESS, 5);
if (Wire.available())
{
for (byte i = 0; i < 5; i++)
{
reception_data[i] = Wire.read();
}
}
return reception_data;
}
void fmSetFrequency(float frequency)
{
unsigned int frequencyB = 4 * (frequency * 1000000 + 225000) / 32768;
byte frequencyH = frequencyB >> 8;
byte frequencyL = frequencyB & 0XFF;
Wire.beginTransmission(FM_ADDRESS);
Wire.write(frequencyH);
Wire.write(frequencyL);
Wire.write(0xB0);
Wire.write(0x10);
Wire.write(0x00);
Wire.endTransmission();
delay(100);
}
byte fmGetSignalLevel()
{
// Necessary before read status
// transmitData();
// Read updated status
return fmReadStatus()[3] >> 4;
}
byte fmIsStereo()
{
return fmReadStatus()[2] >> 7;
}
byte fmIsReady()
{
return fmReadStatus()[0] >> 7;
}
void fmSetChannel(String text)
{
if (input.arrayState == MENU_ITEM_EDIT_ARRAY_ADD || input.arrayState == MENU_ITEM_EDIT_ARRAY_EDIT)
{
if (input.arrayState == MENU_ITEM_EDIT_ARRAY_ADD && fmChannelCount >= FM_MAX_CHANNEL)
return;
byte indexObj = MENU_ITEM_EDIT_ARRAY_ADD == input.arrayState ? fmChannelCount : input.arrayIndex;
String name = text.substring(0, 10);
String value = text.substring(11, 16);
name.toCharArray(fmChannelWithName[indexObj].Name, 11);
value.toCharArray(fmChannelWithName[indexObj].Value, 6);
if (input.arrayState == MENU_ITEM_EDIT_ARRAY_ADD)
fmChannelCount++;
}
else
{
if (fmChannelCount <= 0)
return;
fmChannelCount = fmChannelCount - 1;
for (byte i = 0; i < FM_MAX_CHANNEL - 1; i++)
{
if (i < input.arrayIndex)
continue;
fmChannelWithName[i] = fmChannelWithName[i + 1];
}
}
storeSave(SAVE_CHANEL);
homeFmProcess(0);
}
boolean fmAdjustPositive = true;
void homeFmProcess(byte _press)
{
String text = F(" FM C{0} ");
char str_temp[6];
if (_press == 0 && fmChannelCount > 0)
{
homeScreen[home.index].dataCurrent = homeScreen[home.index].dataCurrent == 255 ? fmChannelCount - 1 //
: homeScreen[home.index].dataCurrent > fmChannelCount - 1 ? 0
: homeScreen[home.index].dataCurrent;
String name = String(fmChannelWithName[homeScreen[home.index].dataCurrent].Name);
String frequency = String(fmChannelWithName[homeScreen[home.index].dataCurrent].Value);
fmCustomFrequency = frequency.toFloat();
dtostrf(fmCustomFrequency, 5, 1, str_temp);
text = name;
for (byte i = 0; i < 15 - 5 - name.length(); i++)
{
text += " ";
}
text += str_temp;
}
else
{
float adjust = _press == KEY_1 ? 0.1 //
: _press == KEY_4 ? -0.1
: _press == KEY_2 ? 0.5
: _press == KEY_5 ? -0.5
: _press == KEY_3 ? 1
: _press == KEY_6 ? -1
: _press == KEY_7 ? 10
: _press == KEY_8 ? -10
: 0;
if (keyboard.isButton && _press == KEY_OK)
{
fmAdjustPositive = keyboard.pressCount == 4 ? !fmAdjustPositive : fmAdjustPositive;
adjust = keyboard.pressCount < 4 && millis() - keyboard.timeRead > 1000 && millis() < home.timeDelay ? keyboard.pressCount == 1 ? 0.1 //
: keyboard.pressCount == 2 ? 1
: 5
: 0;
adjust *= fmAdjustPositive ? 1 : -1;
}
// if (adjust == 0)
// return;
fmCustomFrequency += adjust;
fmCustomFrequency = fmCustomFrequency > 108.0f ? 87.5f : fmCustomFrequency < 87.5f ? 108.0f
: fmCustomFrequency;
dtostrf(fmCustomFrequency, 5, 1, str_temp);
text = F("FM Hand ");
text = (keyboard.isButton ? fmAdjustPositive ? "+" : "-" : " ") + text;
text += str_temp;
}
// swap(homeScreen[home.index].text, sprintfTemp);
text.toCharArray(homeScreen[home.index].text, 16);
fmSetFrequency(fmCustomFrequency);
if (_press == 0)
storeSave(SAVE_CUSTOM);
}
#pragma endregion
#pragma region Menu open other
void menuOpenExtended(byte menuId)
{
if (MENU_ITEM_TIME == menuId)
{
tempReplace = F("{0}:{1}:{2}");
tempReplace.replace(F("{0}"), convertNumToStr(time.hour, 2));
tempReplace.replace(F("{1}"), convertNumToStr(time.minutes, 2));
tempReplace.replace(F("{2}"), convertNumToStr(time.seconds, 2));
input.text = tempReplace;
input.temp = F("**:**:**");
input.isOnlyNumber = true;
input.inputType = INPUT_TYPE_TEXT;
input.callback = &timeSetTimeMenu;
}
else if (MENU_ITEM_DAY == menuId)
{
tempReplace = F("{0}-{1}/{2}/{3}");
tempReplace.replace(F("{0}"), convertNumToStr(time.wday));
tempReplace.replace(F("{1}"), convertNumToStr(time.day, 2));
tempReplace.replace(F("{2}"), convertNumToStr(time.month, 2));
tempReplace.replace(F("{3}"), convertNumToStr(time.year + 2000, 4));
input.text = tempReplace;
input.temp = F("*-**/**/****");
input.isOnlyNumber = true;
input.inputType = INPUT_TYPE_TEXT;
input.callback = &timeSetDateMenu;
}
else if (MENU_ITEM_RADIO_CHANNEL == menuId)
{
input.temp = F("********** ***.*");
input.inputType = INPUT_TYPE_ARRAY;
input.arrayLength = fmChannelCount;
String name;
for (byte i = 0; i < input.arrayLength; i++)
{
String text;
name = (fmChannelWithName[i].Name);
text = name;
for (byte i = 0; i < 15 - 5 - name.length(); i++)
{
text += " ";
}
text += " ";
text += fmChannelWithName[i].Value;
input.arrayItems[i] = text;
}
input.callback = &fmSetChannel;
}
else
{
}
inputPrintLCD();
}
#pragma endregion
#pragma region STORE
byte EEPROM_read(byte index)
{
if (index >= 255)
return 0;
byte a = EEPROM.read(index);
// Serial.println(a);
return a;
}
byte EEPROM_write(byte index, byte value, boolean flag)
{
if (flag == true)
EEPROM_write(index, value);
}
byte EEPROM_write(byte index, byte value)
{
if (index < 255)
EEPROM.write(index, value);
}
void storeLoad()
{
byte cIndex = 0;
if (EEPROM.read(cIndex) != STORE_CODE)
{
storeSave();
}
else
{
cIndex++;
lcdCon.lightTime = EEPROM_read(cIndex);
cIndex++;
fmChannelCount = EEPROM_read(cIndex);
cIndex++;
homeScreen[0].dataCurrent = EEPROM_read(cIndex);
char str_temp[6];
dtostrf(fmCustomFrequency, 5, 1, str_temp);
for (byte i = 0; i < strlen(str_temp); i++)
{
cIndex++;
str_temp[i] = (EEPROM_read(cIndex));
}
String frequency = String(str_temp);
fmCustomFrequency = frequency.toFloat();
for (byte i = 0; i < fmChannelCount; i++)
{
cIndex++;
byte _length = EEPROM_read(cIndex);
for (byte j = 0; j < _length; j++)
{
cIndex++;
fmChannelWithName[i].Name[j] = (EEPROM_read(cIndex));
}
cIndex++;
_length = EEPROM_read(cIndex);
for (byte j = 0; j < _length; j++)
{
cIndex++;
fmChannelWithName[i].Value[j] = (EEPROM_read(cIndex));
}
}
}
}
void storeSave()
{
storeSave(SAVE_ALL);
}
void storeSave(byte type)
{
byte cIndex = 0;
boolean isSave = type == SAVE_ALL || type == SAVE_CUSTOM;
EEPROM_write(cIndex, STORE_CODE, isSave);
cIndex++;
EEPROM_write(cIndex, lcdCon.lightTime, isSave);
cIndex++;
EEPROM_write(cIndex, fmChannelCount, type == SAVE_CHANEL);
cIndex++;
EEPROM_write(cIndex, homeScreen[0].dataCurrent, isSave);
char str_temp[6];
dtostrf(fmCustomFrequency, 5, 1, str_temp);
for (byte i = 0; i < strlen(str_temp); i++)
{
cIndex++;
EEPROM_write(cIndex, (str_temp[i]), isSave);
}
isSave = type == SAVE_ALL || type == SAVE_CHANEL;
for (byte i = 0; i < fmChannelCount; i++)
{
cIndex++;
EEPROM_write(cIndex, strlen(fmChannelWithName[i].Name), isSave);
for (byte j = 0; j < strlen(fmChannelWithName[i].Name); j++)
{
cIndex++;
EEPROM_write(cIndex, fmChannelWithName[i].Name[j], isSave);
}
cIndex++;
EEPROM_write(cIndex, strlen(fmChannelWithName[i].Value), isSave);
for (byte j = 0; j < strlen(fmChannelWithName[i].Value); j++)
{
cIndex++;
EEPROM_write(cIndex, fmChannelWithName[i].Value[j], isSave);
}
}
}
#pragma endregion
void setup()
{
Serial.begin(9600);
// storeSave();
//storeLoad();
// IRLremote.begin(REMOTE_PIN);
receiver.enableIRIn();
//timeRead();
//lcd.init();
//lcd.backlight();
lcd.begin(16, 2);
lcdCon.timeDelayLight = millis() + lcdCon.lightTime * 1000;
viewMode = VIEW_MENU;
menu.index = 0;
menu.parentId = MENU_BEGIN;
menuRender();
// String frequency = String(fmChannelWithName[homeScreen[0].dataCurrent].Value);
// float temp = frequency.toFloat();
// homeFmProcess(fmCustomFrequency != temp ? 255 : 0);
}
String readText = "";
void prcessSerialInput(String cmd){
Serial.println("aaa: " + cmd);
}
void loop()
{
if (Serial.available()) {
char c = char(Serial.read());
Serial.println("ccc: " + c);
readText += c;
if(c == ';'){
prcessSerialInput(readText);
readText = "";
}
}
keyProcess();
inputProcess();
homeProcess();
}