You seem to be determined not to post your code in the easiest way possible so here it is
/*
For laptop: Uno on com port 3. Left side USB front.
*/
#define version_ "100"
#include <LiquidCrystal.h>
#include <Wire.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <phi_interfaces.h>
#include <phi_prompt.h>
#include <DS1307.h>
#include <alarm_clock.h>
#include <Centipede.h>
#include <Arduino.h>
#define phi_2_shield
#define turn_light_on() CS.digitalWrite(1, HIGH)
#define turn_light_off() CS.digitalWrite(1, LOW)
#define turn_blanket_on() CS.digitalWrite(0, HIGH)
#define turn_blanket_off() CS.digitalWrite(0, LOW)
#define lcd_rows 4
#define lcd_columns 20
///////////////// Un-remark this line to set values in EEPROM for new build.
//#define setRTC
#define LED 13
//Phi-2 shield definitions
#define total_buttons 6
#define btn_U 5
#define btn_D 10
#define btn_L 11
#define btn_R 4
#define btn_B 14
#define btn_A 15
//Phi-2 shield LCD pin setting
#define LCD_RS 8
#define LCD_EN 9
#define LCD_D4 7
#define LCD_D5 6
#define LCD_D6 2
#define LCD_D7 3
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // Create the lcd object
int rtc[7];
DS1307 RTC = DS1307(); // Create RTC object
alarm_clock clock1(false); // Create an alarm clock
#define alarm_EEPROM_storage 100 // Where the alarm is saved. The first 100 bytes are for other things.
#define EEPROM_user 0 // Where I put my things/
#define Max_alarms 6
/*
Map of things stored so far:
0 - Alarm_run_time
1 - Blanket off HR
2 - Blanket off MN
3 - Alarm defered flag
4 - DLS start month // Needs work. Could only be month? October
5 - DLS end month // Needs work Could only be month? April
6 - RDO day // Work in progress
7 - week counter // Work in progress
8 - Audio alarm control
9 - Light run time
10 - Blanket run time
11 - DLS flag
*/
byte alarm_run_time;
int blanket_off_time_hr;
int blanket_off_time_mnt;
int defered_flag;
byte DLS_S_mth;
byte DLS_E_mth;
byte skip_day;
boolean week_num;
byte skip_day_flag; // Is this used?
boolean audio_flag;
byte light_run_time;
byte blanket_run_time;
boolean DLS_Flag;
Centipede CS; // create Centipede object
const PROGMEM char msg_00[] = "LCD ALARM CLOCK\nDeveloped by:\nDr.Liu 02/28/12\nhttp://liudr.wordpress.com";
const PROGMEM char msg_01[] = "Up - Defere alarm\nDown - Disable ALL alarms ON/OFF\nLeft - Blank' ON/OFFRight - Light ON/OFFEnter - SLEEP";
const PROGMEM char month_00[] = "JAN";
const PROGMEM char month_01[] = "FEB";
const PROGMEM char month_02[] = "MAR";
const PROGMEM char month_03[] = "APR";
const PROGMEM char month_04[] = "MAY";
const PROGMEM char month_05[] = "JUN";
const PROGMEM char month_06[] = "JUL";
const PROGMEM char month_07[] = "AUG";
const PROGMEM char month_08[] = "SEP";
const PROGMEM char month_09[] = "OCT";
const PROGMEM char month_10[] = "NOV";
const PROGMEM char month_11[] = "DEC";
//const PROGMEM signMessage[] *month_items[]= {month_00,month_01,month_02,month_03,month_04,month_05,month_06,month_07,month_08,month_09,month_10,month_11};
const char *const month_items[] PROGMEM = { month_00, month_01, month_02, month_03, month_04, month_05, month_06, month_07, month_08, month_09, month_10, month_11 };
const PROGMEM char dow_00[] = "SUN";
const PROGMEM char dow_01[] = "MON";
const PROGMEM char dow_02[] = "TUE";
const PROGMEM char dow_03[] = "WED";
const PROGMEM char dow_04[] = "THU";
const PROGMEM char dow_05[] = "FRI";
const PROGMEM char dow_06[] = "SAT";
//const PROGMEM char *dow_items[]= {dow_00,dow_01,dow_02,dow_03,dow_04,dow_05,dow_06};
const char *const dow_items[] PROGMEM = { dow_00, dow_01, dow_02, dow_03, dow_04, dow_05, dow_06 };
const PROGMEM char alarm_00[] = "Off";
const PROGMEM char alarm_01[] = "Daily";
const PROGMEM char alarm_02[] = "Weekday";
const PROGMEM char alarm_03[] = "Weekend";
const PROGMEM char alarm_04[] = "Once";
//PROGMEM const char *alarm_items[]= {alarm_00,alarm_01,alarm_02,alarm_03,alarm_04};
const char *const alarm_items[] PROGMEM = { alarm_00, alarm_01, alarm_02, alarm_03, alarm_04 };
// /*
char mapping[] = { 1, 2, 3, 4, 5, 6 }; // This is a list of names for each button.
// sterretje, changed to uppercase last character
//byte pins[] = {btn_U, btn_D, btn_L, btn_R, btn_D, btn_A}; // The digital pins connected to the 6 buttons.
byte pins[] = { btn_U, btn_D, btn_L, btn_R, btn_D, btn_A }; // The digital pins connected to the 6 buttons.
phi_button_groups my_btns(mapping, pins, total_buttons);
phi_serial_keypads debug_keypad(&Serial, 9600);
multiple_button_input *keypads[] = { &my_btns, &debug_keypad, 0 };
char up_keys[] = { 1, 0 }; ///< All keys that act as the up key are listed here.
char down_keys[] = { 2, 0 }; ///< All keys that act as the down key are listed here.
char left_keys[] = { 3, 0 }; ///< All keys that act as the left key are listed here.
char right_keys[] = { 4, 0 }; ///< All keys that act as the right key are listed here.
char enter_keys[] = { 5, 0 }; ///< All keys that act as the enter key are listed here.
char escape_keys[] = { 6, 0 }; ///< All keys that act as the escape key are listed here.
char *function_keys[] = { up_keys, down_keys, left_keys, right_keys, enter_keys, escape_keys }; ///< All function key names are gathered here fhr phi_prompt.
// */
// This is used to set if the blanket is also turned off when an alarm goes off.
// If 0 nothing happens.
// Set to 1 and when an alarm goes off, the blanket will be turned off also.
#define ABO 0
void setup()
{
// put your setup code here, to run once:
// My routines here.
Serial.begin(9600);
alarm_run_time = EEPROM.read(EEPROM_user + 0);
delay(100);
blanket_off_time_hr = EEPROM.read(EEPROM_user + 1);
delay(100);
blanket_off_time_mnt = EEPROM.read(EEPROM_user + 2);
delay(100);
defered_flag = EEPROM.read(EEPROM_user + 3);
delay(100);
DLS_S_mth = EEPROM.read(EEPROM_user + 4);
delay(100);
DLS_E_mth = EEPROM.read(EEPROM_user + 5);
delay(100);
skip_day = EEPROM.read(EEPROM_user + 6);
delay(100);
week_num = EEPROM.read(EEPROM_user + 7);
delay(100);
audio_flag = EEPROM.read(EEPROM_user + 8);
delay(100);
light_run_time = EEPROM.read(EEPROM_user + 9);
delay(100);
blanket_run_time = EEPROM.read(EEPROM_user + 10);
delay(100);
DLS_Flag = EEPROM.read(EEPROM_user + 11);
delay(100);
byte ch_buffer[10]; // This buffer is required for custom characters on the LCD.
lcd.begin(lcd_columns, lcd_rows);
Wire.begin(); // initialize wire
init_phi_prompt(&lcd, keypads, function_keys, lcd_columns, lcd_rows, '~'); // Supply the liquid crystal object, input keypads, and function key names. Also supply the column and row of the lcd, and indicator as '>'. You can also use '\x7e', which is a right arrow.
// =========== 2023 08 31
//init_big_font(&lcd);
////////////////////////////////////////////////
CS.initialize(); // set all registers to default
CS.portMode(0, 0b0000000000000000); // set all pins on chip 0 to output
// Set the two channels to output to drive the buzzer and LED.
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
//============================================
// I am not sure I need to keep this section of code.
// Ending with similar line of =====
#ifdef setRTC
// Set/init RTC
RTC.stop();
RTC.set(DS1307_SEC, 0);
RTC.set(DS1307_MIN, 50);
RTC.set(DS1307_HR, 0);
RTC.set(DS1307_DOW, 3); // value from 1 to 7. User define whether 1 is sun or mon.
RTC.set(DS1307_DATE, 10);
RTC.set(DS1307_MTH, 06);
RTC.set(DS1307_YR, 23);
RTC.start();
//Set alarms
EEPROM.write(alarm_EEPROM_storage, 6); // Alarm 0 hour
EEPROM.write(alarm_EEPROM_storage + 1, 50); // Alarm 0 minute
EEPROM.write(alarm_EEPROM_storage + 2, 0); // Alarm 0 frequency off
EEPROM.write(alarm_EEPROM_storage + 3, 7); // Alarm 1 hour
EEPROM.write(alarm_EEPROM_storage + 4, 00); // Alarm 1 minute
EEPROM.write(alarm_EEPROM_storage + 5, 0); // Alarm 1 frequency off
EEPROM.write(alarm_EEPROM_storage + 6, 7); // Alarm 2 hour
EEPROM.write(alarm_EEPROM_storage + 7, 00); // Alarm 2 minute
EEPROM.write(alarm_EEPROM_storage + 8, 3); // Alarm 2 frequency Week end
EEPROM.write(alarm_EEPROM_storage + 9, 4); // Alarm 3 hour
EEPROM.write(alarm_EEPROM_storage + 10, 48); // Alarm 3 minute
EEPROM.write(alarm_EEPROM_storage + 11, 0); // Alarm 3 frequency off
EEPROM.write(alarm_EEPROM_storage + 12, 5); // Alarm 4 hour
EEPROM.write(alarm_EEPROM_storage + 13, 48); // Alarm 4 minute
EEPROM.write(alarm_EEPROM_storage + 14, 2); // Alarm 4 frequency M-F
// Set when DLS starts and ends - months.
EEPROM.write(EEPROM_user + 4, 10);
delay(100);
EEPROM.write(EEPROM_user + 5, 4);
delay(100);
//============================================
#else
// Set alarm on the clock from EEPROM.
clock1.set_alarm(0, EEPROM.read(alarm_EEPROM_storage), EEPROM.read(alarm_EEPROM_storage + 1), EEPROM.read(alarm_EEPROM_storage + 2));
clock1.set_alarm(1, EEPROM.read(alarm_EEPROM_storage + 3), EEPROM.read(alarm_EEPROM_storage + 4), EEPROM.read(alarm_EEPROM_storage + 5));
clock1.set_alarm(2, EEPROM.read(alarm_EEPROM_storage + 6), EEPROM.read(alarm_EEPROM_storage + 7), EEPROM.read(alarm_EEPROM_storage + 8));
clock1.set_alarm(3, EEPROM.read(alarm_EEPROM_storage + 9), EEPROM.read(alarm_EEPROM_storage + 10), EEPROM.read(alarm_EEPROM_storage + 11));
clock1.set_alarm(4, EEPROM.read(alarm_EEPROM_storage + 12), EEPROM.read(alarm_EEPROM_storage + 13), EEPROM.read(alarm_EEPROM_storage + 14));
clock1.set_alarm(5, EEPROM.read(alarm_EEPROM_storage + 15), EEPROM.read(alarm_EEPROM_storage + 16), EEPROM.read(alarm_EEPROM_storage + 17));
#endif
}
void loop()
{
// put your main code here, to run repeatedly:
}
// (My routines)
/*============================================================================================================================*/
/*
Below are routines.
*/
/*============================================================================================================================*/
/*
This is a list of the routines in this section:
bootup
alarm_defer
light_toggle
lecky_blanky
sleep_time
alarm_timer
DLS
show_keys
week_counter
voice_reminder
audio_test
display_stuff
*/
void bootup()
{
//
Serial.print("Version ");
Serial.println(version_);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Boot up info.");
lcd.setCursor(0, 1);
lcd.print("Ver' ");
lcd.print(version_);
wait_on_escape(4000);
lcd.setCursor(0, 0);
lcd.print("HR MN ADF [DLS ] ART");
lcd.setCursor(1, 1);
lcd.print(blanket_off_time_hr);
lcd.print(" ");
lcd.print(blanket_off_time_mnt);
lcd.print(" ");
lcd.print(defered_flag);
lcd.print(" [");
lcd.print(DLS_S_mth);
lcd.print(" ");
lcd.print(DLS_E_mth);
lcd.print("] ");
lcd.print(alarm_run_time);
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print("SD WN LT BT DF AF");
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.print(skip_day);
lcd.print(" ");
lcd.print(week_num);
if (light_run_time > 9)
{
lcd.print(" ");
}
else
{
lcd.print(" ");
}
lcd.print(light_run_time);
lcd.print(" ");
lcd.print(blanket_run_time);
lcd.print(" ");
lcd.print(DLS_Flag);
lcd.print(" ");
lcd.print(audio_flag);
wait_on_escape(8000);
}
/*============================================================================================================================*/
// My routine to defere alarms for people who beat the alarm.
/*
Call it with 0 return the status of the defered alarms DISPLAY ONLY.
Call it with 1 to set the flag to skip the next alarm.
Call it with 2 to set the MASTER defere flag.
Call it with 3 to return the status and clear if needed. This is called when the alarm is active.
When called with 0:
Returns 0, 1 or 3.
0 - allow alarm to happen.
1 - do not allow this alarm to happen.
3 - ALL alarms defered.
*/
boolean alarm_defere(byte fctn)
{
Serial.print(F("alarm defer called with "));
Serial.println(fctn);
boolean rc;
if (fctn == 0)
return defered_flag;
if (fctn == 1)
{
//
if (defered_flag != 3)
{
defered_flag = defered_flag + 1;
defered_flag = defered_flag % 2;
}
rc = 0; // This is a "dummy" as it is not needed/used.
}
if (fctn == 2) // This is for future use as a quick turn off for all alarm - toggle.
{
defered_flag = defered_flag + 1;
defered_flag = defered_flag % 2;
if (defered_flag == 1)
{
defered_flag = 3;
}
rc = 0; // This is a "dummy" as it is not needed/used.
}
else if (fctn == 3)
{
if (defered_flag == 0)
{
rc = 0;
}
if (defered_flag == 3)
{
rc = 1;
}
if (defered_flag == 1)
{
defered_flag = 0;
rc = 1;
}
}
EEPROM.write(EEPROM_user + 3, defered_flag);
delay(100);
Serial.print(F("Alarm defer returning value "));
Serial.println(rc);
return rc;
}
/*============================================================================================================================*/
// My little routine to toggle light on/off
/*
This is a simple toggle function for the light.
So if you need it on, press the button.
Call with 0 - returns status.
Call with 1 - toggle light.
Call with 2 - turn off.
When called with 0:
Returns:
0 - light off
1 - light on
This is used for another routine to display the icon.
*/
boolean light_toggle(byte fctn)
{
static boolean Light_status;
if (fctn == 0)
{
return Light_status;
}
else if (fctn == 1)
{
sleep_time(light_run_time, 1);
Light_status = Light_status + 1;
Light_status = Light_status % 2;
switch (Light_status)
{
case 0:
turn_light_off();
break;
case 1:
turn_light_on();
break;
}
}
else if (fctn == 2) // used to force off.
{
Light_status = 0;
turn_light_off();
}
}
/*============================================================================================================================*/
// Electric blanket routine.
/*
This routine turns on the blanket relay.
and other functions with the blanket.
Call with 0 - return status
Call with 1 - toggle.
Call with 2 - turn off.
When called with 0:
Returns:
0 - blanket off
1 - blanket on
This is used for another routine to display the icon.
*/
boolean leky_blanky(byte fctn)
{
static int blanket_status;
if (fctn == 0)
{
return blanket_status;
}
else if (fctn == 1)
{
sleep_time(blanket_run_time, 2);
blanket_status = blanket_status + 1;
blanket_status = blanket_status % 2;
switch (blanket_status)
{
case 0:
turn_blanket_off();
break;
case 1:
turn_blanket_on();
break;
}
}
else if (fctn == 2)
{
blanket_status = 0;
turn_blanket_off();
}
}
/*============================================================================================================================*/
/*
This is a countdown function. There are TWO paramaters. Function and Caller.
Initial settings are set when it is called with a caller value of 0 or 1.
The function value sets the time.
To activate the timer, call with a caller value of 30.
To the cancel the timer, call again with caller value of 30.
Call twice with Caller of 0 or 1 then with 30 to turn on the
device after the specified time, rather than turn off after
the specified time.
Returns the countdown time remaining when active.
*/
byte sleep_time(byte fctn, byte caller)
{
static byte count_down_time_remaining;
static byte fctn_memory; // This is a copy of the original call value so if it is seen again, it cancels the timer.
static byte caller_memory; // This is the memory of who called and initiated the timer.
static byte min_flag; // This ia the memory of the last minute from the RTC.
static boolean condition; // This is a memory for the condition of this function.
static byte old_caller; // This is another memory which is needed for who called.
RTC.get(rtc, true);
if (caller == 0)
{
// count down
if (count_down_time_remaining > 0)
{
if (min_flag != rtc[1])
{
min_flag = rtc[1];
count_down_time_remaining = count_down_time_remaining - 1;
}
}
if (count_down_time_remaining == 0)
{
//condition = 0;
if (old_caller > 0)
{
switch (old_caller)
{
case 1:
old_caller = 0;
light_toggle(1);
break;
case 2:
old_caller = 0;
leky_blanky(1);
break;
default:
break;
}
}
}
return count_down_time_remaining;
}
if (caller == 1)
{
min_flag = rtc[1];
caller_memory = caller;
fctn_memory = fctn;
if (old_caller == caller)
{
count_down_time_remaining = 0;
return 0;
}
}
if (caller == 2)
{
min_flag = rtc[1];
caller_memory = caller;
fctn_memory = fctn;
if (old_caller == caller)
{
count_down_time_remaining = 0;
return 0;
}
}
if (caller == 30)
{
// toggle status of the "Sleep" function
condition = condition + 1;
condition = condition % 2;
switch (condition)
{
case 0:
count_down_time_remaining = 0;
return 0;
break;
case 1:
count_down_time_remaining = fctn_memory;
old_caller = caller_memory;
return count_down_time_remaining;
break;
default:
return (0);
}
}
}
/*============================================================================================================================*/
/*
This routine is a "countdown" timer for the alarms.
It counts down the value ART - Alarm Run Time.
*/
byte alarm_timer(byte boo)
{
static byte run_flag;
static byte ART;
static byte min_called;
char msg[18];
RTC.get(rtc, true);
run_flag = boo;
byte x = 2;
byte y = 0;
if (run_flag == 0)
{
ART = 0;
return (ART);
}
if (run_flag == 1)
{
if (ART == 0)
{
ART = alarm_run_time;
min_called = rtc[1];
}
if (ART > 0)
{
if (min_called != rtc[1])
{
min_called = rtc[1];
ART = ART - 1;
}
lcd.setCursor(x, y);
lcd.print(ART);
if (ART == 1)
lcd.print(F(" minute to go. "));
else if (ART > 9)
lcd.print(F(" minutes to go."));
else
lcd.print(F(" minutes to go. "));
}
return (ART);
}
}
/*============================================================================================================================*/
/*
Idea:
Set:
Check for DLS start month
Check for DOW = 1. Sunday
Check hour = 02.
Add 1 hour and set flag
Reset:
Check for DLS end month
Check for DOW = 1. Sunday
Check hour = 02.
Check flag is set
Remove 1 hour and reset flag
rtc[5] is the month.
rtc[4] is the date.
rtc[3] is DOW.
rtc[2] is hour.
*/
void DLS()
{
byte hour_now;
RTC.get(rtc, true);
if (DLS_S_mth == rtc[5])
{
// Check DOW
if (rtc[3] == 1)
{
//
if (rtc[2] == 2)
{
if (DLS_Flag == 0)
{
// Wind clock fwd 1 hour and set flag.
// and set DLS_Flag = 1
hour_now = rtc[2];
hour_now = hour_now + 1;
rtc[2] = hour_now;
RTC.stop();
RTC.set(DS1307_HR, rtc[2]);
RTC.start();
DLS_Flag = 1;
EEPROM.write(EEPROM_user + 11, DLS_Flag);
delay(100);
}
}
}
}
if (DLS_E_mth == rtc[5])
{
// Check DOW
if (rtc[3] == 1)
{
if (rtc[2] == 2)
{
if (DLS_Flag == 1)
{
// Wind clock back 1 hour and set flag.
// and set DLS_Flag = 0
hour_now = rtc[2];
hour_now = hour_now - 1;
rtc[2] = hour_now;
RTC.stop();
RTC.set(DS1307_HR, rtc[2]);
RTC.start();
DLS_Flag = 0;
EEPROM.write(EEPROM_user + 11, DLS_Flag);
delay(100);
}
}
}
}
}
/*============================================================================================================================*/
/*
This shows what all the keys do.
*/
void show_keys()
{
phi_prompt_struct myLongMsg;
lcd.clear();
lcd.noBlink();
myLongMsg.ptr.msg_P = msg_01; // Assign the address of the text string to the pointer.
myLongMsg.low.i = 0; // Default text starting position. 0 is highly recommended.
myLongMsg.high.i = strlen_P(msg_01); // Position of the last character in the text string, which is size of the string - 1.
myLongMsg.step.c_arr[0] = lcd_rows; // rows to auto fit entire screen
myLongMsg.step.c_arr[1] = lcd_columns; // one col list
myLongMsg.col = 0; // Display the text area starting at column 0
myLongMsg.row = 0; // Display the text area starting at row 0
myLongMsg.option = 0; // Option 0, display classic message, option 1, display message with scroll bar on right.
text_area_P(&myLongMsg);
}
/*============================================================================================================================*/
/*
This counts the week and alternates from 0 to 1.
This is used to allow for "flexy days" to be included
in the alarm sequence and actually stop the alarm going off
on that specific day.
*/
void week_counter()
{
static boolean flag;
RTC.get(rtc, true);
if (rtc[3] == 2) // Monday - or Sunday MIDNIGHT going into Monday.
{
if (flag == 0)
{
week_num = week_num + 1;
week_num = week_num % 2;
flag = 1;
//************ WORK NEEDED HERE TO STORE TO EEPROM
}
}
if (rtc[3] == 3)
{
flag = 0;
}
}
/*============================================================================================================================*/
/*
This creates a random number which is used to trigger a random
sound.
No sound optinon removed.
The initial value is:
0 - play sound 1
1 - play sound 2
Then given the 1 or 2, they are reduced by 1 to be 0 or 1.
This is to help identify which pin is used on the MCP.
There is a lot of flags - GO and FLAG - which are used to
stop multiple invocation of the routine.
FLAG is used when the alarm starts and stops the voice repeating.
GO is also needed to clear the FLAG once the alarm is stopped.
*/
void voice_reminder(boolean go)
{
// This bit of routine selects 1 of 2 values to select which sound is played.
static boolean flag;
if (go == 0)
{
//
if (flag == 0)
{
//
int random_num;
lcd.setCursor(18, 0);
random_num = random(0, audio_flag + 1);
lcd.print(random_num);
// if (random_num >0)
// {
// random_num = random_num -1;
CS.digitalWrite(4 + random_num, HIGH);
delay(500);
CS.digitalWrite(4 + random_num, LOW);
// }
flag = 1;
}
}
if (go == 1)
{
flag = 0;
lcd.setCursor(18, 0); // 2017 06 24 This was putting curor at 19,0 instead of 18,0.
lcd.print(" ");
}
}
/*============================================================================================================================*/
/*
This routine is used only to cycle the pins to stimulate the audion card so I cam be sure it is working.
*/
void audio_test()
{
// for (int i=0;i<5;i++)
for (int i = 0; i < (audio_flag + 1); i++)
{
//
lcd.clear();
lcd.print(i);
CS.digitalWrite(4 + i, HIGH);
delay(500);
lcd.clear();
lcd.print(i);
CS.digitalWrite(4 + i, LOW);
delay(500);
}
// return;
}
/*============================================================================================================================*/
/*============================================================================================================================*/
/*============================================================================================================================*/
/*
This piece of code is used for display stuff.
There is no particular order but each "routine" is seperated
by a line of -------
General stuff to note:
Variables x and y are used by each section to position the curosr
on the screen as much as possible to help if the position where
the information is displayed.
boo is a general purpose thing for getting return values from other
functions.
*/
void display_stuff()
{
// These two lines are for setting the position of things to print.
byte x; // Sets X position on screen
byte y; // Sets Y position on screen
byte boo; // This is used to get return values from other routines.
RTC.get(rtc, true);
// Now a list of other variables used.
// Comments tell which section they are used in.
static byte al_flag; // Used in defere alarm section.
static byte skip_day_flag; // RDO routine.
byte i; // Used for displaying alarm status symbol.
int foo[Max_alarms - 1]; // Used for displaying alarm status symbol.
//-------------------------------------------------------------------------------------
//display bell symbol for each "active" alarm
x = 20 - (Max_alarms / 2); //
// x = 15; //
y = 1;
lcd.setCursor(x, y);
for (byte i = 0; i < (Max_alarms / 2); i++)
// for (int i=0;i<5;i++)
{
foo[i] = clock1.alarms[i].dow; //2, 5, 8 and 11
if (foo[i] > 0)
{
lcd.print(char(0));
}
else
{
lcd.print("-");
}
}
if (Max_alarms > 5)
{
// Work needed here so use the line below (now) the given one as well for extra alarms.
x = 20 - (Max_alarms / 2); //
// x = 15; //
y = 2;
lcd.setCursor(x, y);
for (byte i = (Max_alarms / 2); i < Max_alarms; i++)
{
foo[i] = clock1.alarms[i].dow; //2, 5, 8 and 11
if (foo[i] > 0)
{
lcd.print(char(0));
}
else
{
lcd.print("-");
}
}
}
//-------------------------------------------------------------------------------------
// Display the "defered alarm" symbol on the screen if the next alarm is defered.
// byte boo_x;
x = 0;
y = 0;
boo = alarm_defere(0);
lcd.setCursor(x, y);
/*
Serial.println("------------------");
Serial.println(" alarm defer routine");
Serial.print("Al flag ");
Serial.print(al_flag);
*/
if (boo == 0)
{
if (al_flag == 0)
{
lcd.print(" ");
al_flag = 1;
}
}
if (boo == 1)
{
lcd.print("X");
al_flag = 0;
}
if (boo == 3)
{
al_flag = 0;
static int last_sec;
if (last_sec != rtc[0])
{
last_sec = rtc[0];
if (last_sec % 2 == 0)
{
//
lcd.print("ALL alarms DISABLED");
}
else
{
lcd.print(" WARNING! ");
}
}
}
//-------------------------------------------------------------------------------------
// Display the LIGHT icon indicating the light has been manually activated.
x = 1;
y = 2;
lcd.setCursor(x, y);
boo = light_toggle(0);
if (boo == 0)
{
lcd.print(" ");
}
if (boo == 1)
{
lcd.print(char(3));
}
//-------------------------------------------------------------------------------------
// Display the BOLT icon indicating the blanket has been turned on.
x = 0;
y = 2;
lcd.setCursor(x, y);
boo = leky_blanky(0);
if (boo == 0)
{
lcd.print(" ");
}
if (boo == 1)
{
lcd.print(char(2));
}
//-------------------------------------------------------------------------------------
// sleep time remaining routine.
x = 2;
y = 2;
lcd.setCursor(x, y);
boo = sleep_time(0, 0);
// text format: " @ nn" Where @ is the timer char and nn are numbers. Length = 5
if (boo == 0)
{
lcd.print(" ");
}
if (boo > 0)
{
lcd.print(char(1));
lcd.print(" ");
lcd.print(boo);
if (boo < 9)
{
lcd.print(" ");
}
}
//-------------------------------------------------------------------------------------
// RDO routine.
// These lines are semi-debuging stuff.
lcd.setCursor(18, 3);
lcd.print(week_num);
lcd.print(rtc[3]);
lcd.setCursor(0, 3);
lcd.print(skip_day);
// End debug lines.
x = 6;
y = 2;
lcd.setCursor(x, y);
if (week_num == 1)
{
//
if (rtc[3] == (skip_day - 1))
{
lcd.print("Tomorrow");
skip_day_flag = 0; // THis is only for testing reasons. Can be deleted later
}
else if (rtc[3] == skip_day)
{
lcd.print("R.D.O. ");
if (skip_day_flag != 1)
{
alarm_defere(1);
skip_day_flag = 1;
}
}
else
{
lcd.print(" ");
// skip_day_flag = 0;
}
}
//-------------------------------------------------------------------------------------
// Show when DLS is active. This may be temporary.
x = 0;
y = 1;
lcd.setCursor(x, y);
if (DLS_Flag == 1)
{
lcd.print("DLS");
}
else
{
lcd.print(" ");
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
// Other things happen below.
}
// The line above needs to stay "outside" the other functions to close the bigger "display_stuff()" function.
/*============================================================================================================================*/
// (Example menu)
// Menu texts
// If more items are addeed, you also have to edit in the menu settings below!
const PROGMEM char top_menu_item00[] = "Display clock";
const PROGMEM char top_menu_item01[] = "List alarms";
const PROGMEM char top_menu_item02[] = "Set alarms";
const PROGMEM char top_menu_item03[] = "Adjust time";
const PROGMEM char top_menu_item04[] = "Adj' alarm run time";
const PROGMEM char top_menu_item05[] = "Blanket off time";
const PROGMEM char top_menu_item06[] = "Set skip day";
const PROGMEM char top_menu_item07[] = "Audio flag";
const PROGMEM char top_menu_item08[] = "Show key functions";
const PROGMEM char top_menu_item09[] = "Light run time";
const PROGMEM char top_menu_item10[] = "Blanket run time";
const PROGMEM char top_menu_item11[] = "Test audio outputs";
const PROGMEM char top_menu_item12[] = "Display boot information";
const char *const top_menu_items[] = { top_menu_item00, top_menu_item01, top_menu_item02, top_menu_item03, top_menu_item04, top_menu_item05, top_menu_item06, top_menu_item07, top_menu_item08, top_menu_item09, top_menu_item10, top_menu_item11, top_menu_item12 };
//This program is the main menu. It handles inputs from the keys, updates the menu or executes a certain menu function accordingly.
byte clock_style = 0; // This is the style of the menu
void top_menu()
{
// Display the clock at boot up.
lcd.clear();
top_menu_function_1();
byte menu_pointer_1 = 0; // This stores the menu choice the user made.
phi_prompt_struct myMenu; // This structure stores the main menu.
// Initialize the top menu
myMenu.ptr.list = (char **)&top_menu_items; // Assign the list to the pointer
myMenu.low.i = 0; // Default item highlighted on the list
myMenu.high.i = 12; // Last item of the list is size of the list - 1.
myMenu.width = lcd_columns - 1; // Length in characters of the longest list item.
myMenu.step.c_arr[0] = lcd_rows - 1; // rows to auto fit entire screen
myMenu.step.c_arr[1] = 1; // one col list
myMenu.step.c_arr[2] = 0; // y for additional feature such as an index
myMenu.step.c_arr[3] = lcd_columns - 6; // x for additional feature such as an index
myMenu.col = 0; // Display prompt at column 0
myMenu.row = 1; // Display prompt at row 1
myMenu.option = 45;
while (1) // This loops every time a menu item is selected.
{
lcd.clear(); // Refresh menu if a button has been pushed
lcd.print("Main Menu");
select_list(&myMenu); // Use the select_list to ask the user to select an item of the list, that is a menu item from your menu.
menu_pointer_1 = myMenu.low.i; // Get the selected item number and store it in the menu pointer.
switch (menu_pointer_1) // See which menu item is selected and execute that correspond function
{
case 0:
lcd.clear();
top_menu_function_1();
break;
case 1:
lcd.clear();
top_menu_function_4();
break;
case 2:
lcd.clear();
top_menu_function_3();
break;
case 3:
lcd.clear();
top_menu_function_2();
break;
case 4:
lcd.clear();
top_menu_function_5();
break;
case 5:
lcd.clear();
top_menu_function_6();
break;
case 6:
lcd.clear();
top_menu_function_7();
break;
case 7:
lcd.clear();
top_menu_function_8();
break;
case 8:
lcd.clear();
top_menu_function_9();
break;
case 9:
lcd.clear();
top_menu_function_10();
break;
case 10:
lcd.clear();
top_menu_function_11();
break;
case 11:
lcd.clear();
top_menu_function_12();
break;
case 12:
lcd.clear();
bootup();
break;
/*
// This is a dummy if more menu options are added.
case :
lcd.clear();
top_menu_function_();
break;
*/
default:
break;
}
}
}
/*============================================================================================================================*/
// Menu functions go here. The functions are called when their menu items are selected. They are called only once so if you want to do something repeatedly, make sure you have a while loop.
void top_menu_function_1() //This runs the clock
{
lcd.clear();
lcd.print("Escape key for menu");
wait_on_escape(600);
lcd.clear();
byte temp1;
while (1)
{
clock1.run();
// Can I put the "If (ABO==0)" routine here?
// Taken from alarm_clock
if (!clock1.alarm_is_on)
{
temp1 = wait_on_escape(800);
switch (temp1)
{
case 0:
break;
case 1: // UP key
alarm_defere(1);
break;
// ALL Alarms ON/OFF quick toggle.
case 2: // DOWN key
alarm_defere(2);
break;
// Electric blanket ON/OFF function. Needs work for time specific on period.
case 3: // LEFT key
leky_blanky(1);
break;
// call my routine (in alarm_clock) to toggle light.
case 4: // RIGHT key
light_toggle(1);
break;
// call my routine for sleep time (in alarm_clock).
case 5: // ENTER key
sleep_time(30, 30);
//digitalWrite(LED,HIGH);
break;
// This is the ESCAPE key and exits back to the menu
case 6: // ESCAPE key
return;
default:
break;
}
}
}
}
/*============================================================================================================================*/
void top_menu_function_2() //Set the clock
{
int user_input;
phi_prompt_struct myIntegerInput, myListInput; // This structure stores the main menu.
render_RTC(0);
RTC.get(rtc, true);
user_input = rtc[6]; // Current value
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 2000; // Lower limit
myIntegerInput.high.i = 2099; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 6; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 4; // The number occupies 2 characters space
myIntegerInput.option = 0; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Year"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) rtc[6] = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
myListInput.ptr.list = (char **)&month_items; // Assign the list to the pointer
myListInput.low.i = rtc[5] - 1; // Default item highlighted on the list
myListInput.high.i = 11; // Last item of the list is size of the list - 1.
myListInput.width = 3; // Length in characters of the longest list item.
myListInput.col = 0; // Display prompt at column 0
myListInput.row = 1; // Display prompt at row 1
myListInput.option = 1;
myListInput.step.c_arr[0] = lcd_rows - 1; // rows to auto fit entire screen
myListInput.step.c_arr[1] = lcd_columns / 4; // multi col list
lcd.clear();
center_text("Month"); // Prompt user for input
if (select_list(&myListInput) != -1) rtc[5] = myListInput.low.i + 1; // select_list stores user choice in myListInput.low. If the user didn't press escape (return -1) then update the user choice with the value in myListInput.low.
else
return;
user_input = rtc[4]; // Current value
myIntegerInput.low.i = 1; // Lower limit
myIntegerInput.high.i = 31; // Upper limit
lcd.clear();
center_text("Date"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) rtc[4] = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
myListInput.ptr.list = (char **)&dow_items; // Assign the list to the pointer
myListInput.low.i = rtc[3] - 1; // Default item highlighted on the list
myListInput.high.i = 6; // Last item of the list is size of the list - 1.
myListInput.width = 3; // Length in characters of the longest list item.
myListInput.col = 0; // Display prompt at column 0
myListInput.row = 1; // Display prompt at row 1
myListInput.option = 1;
myListInput.step.c_arr[0] = lcd_rows - 1; // rows to auto fit entire screen
myListInput.step.c_arr[1] = lcd_columns / 4; // multi col list
lcd.clear();
center_text("Day of the week"); // Prompt user for input
if (select_list(&myListInput) != -1) rtc[3] = myListInput.low.i + 1; // select_list stores user choice in myListInput.low. If the user didn't press escape (return -1) then update the user choice with the value in myListInput.low.
else
return;
user_input = rtc[2]; // Current value
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = 23; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 7; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Hour"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) rtc[2] = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
user_input = rtc[1]; // Current value
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = 59; // Upper limit
lcd.clear();
center_text("Minute"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) rtc[1] = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
user_input = rtc[0]; // Current value
lcd.clear();
center_text("Second"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) rtc[0] = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
RTC.stop();
RTC.set(DS1307_SEC, rtc[0]); //rtc[0]
RTC.set(DS1307_MIN, rtc[1]); //rtc[1]
RTC.set(DS1307_HR, rtc[2]); //rtc[2]
RTC.set(DS1307_DOW, rtc[3]); //rtc[3] value from 1 to 7. User define whether 1 is sun or mon.
RTC.set(DS1307_DATE, rtc[4]); //rtc[4] dat
RTC.set(DS1307_MTH, rtc[5]); //rtc[5] Month
RTC.set(DS1307_YR, rtc[6] - 2000); //rtc[6] Year only has years since 2000 so 10 represents 20100.
RTC.start();
}
/*============================================================================================================================*/
void top_menu_function_3() //Set alarms
{
byte temp1;
byte ala = 0;
char msg[17];
int user_input;
phi_prompt_struct myIntegerInput, myListInput; // This structure stores the main menu.
lcd.clear();
sprintf(msg, "Alarm %02d:", 0);
lcd.print(msg);
user_input = 0; // Current value
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = Max_alarms - 1; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 7; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Which alarm?"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) ala = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
user_input = clock1.alarms[ala].hr; // Current value
myIntegerInput.high.i = 23; // Upper limit
lcd.clear();
center_text("Hour"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) clock1.alarms[ala].hr = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
user_input = clock1.alarms[ala].mnt; // Current value
myIntegerInput.high.i = 59; // Upper limit
lcd.clear();
center_text("Minute"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1) clock1.alarms[ala].mnt = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
else
return;
myListInput.ptr.list = (char **)&alarm_items; // Assign the list to the pointer
myListInput.low.i = clock1.alarms[ala].dow; // Default item highlighted on the list
myListInput.high.i = 4; // Last item of the list is size of the list - 1.
myListInput.width = 7; // Length in characters of the longest list item.
myListInput.col = 0; // Display prompt at column 0
myListInput.row = 1; // Display prompt at row 1
myListInput.option = 1; // Option 0, display classic list, option 1, display 2X2 list, option 2, display list with index, option 3, display list with index2.
myListInput.step.c_arr[0] = lcd_rows - 1; // rows to auto fit entire screen
myListInput.step.c_arr[1] = lcd_columns / 8; // multi col list
lcd.clear();
center_text("Type"); // Prompt user for input
if (select_list(&myListInput) != -1) clock1.alarms[ala].dow = myListInput.low.i; // select_list stores user choice in myListInput.low. If the user didn't press escape (return -1) then update the user choice with the value in myListInput.low.
else
return;
// If the alarm is set for ONCE, don't store it in EEPROM memory.
if (myListInput.low.i != 4)
{
EEPROM.write(alarm_EEPROM_storage + 3 * ala, clock1.alarms[ala].hr); // Alarm hour
delay(100);
EEPROM.write(alarm_EEPROM_storage + 3 * ala + 1, clock1.alarms[ala].mnt); // Alarm minute
delay(100);
EEPROM.write(alarm_EEPROM_storage + 3 * ala + 2, clock1.alarms[ala].dow); // Alarm frequency M-F
delay(100);
}
}
/*============================================================================================================================*/
void top_menu_function_4() //Display a list of the alarms and times.
/*
What I have learnt:
alarm_EEPROM_storage+n (where n is the alarm number) yields 0,1,2,3
0 = off
1 = Daily
2 = M-F
3 = Weekend
4 = Once
bit of information about the RTC alarms.
clock1.alarms[ala].hr;
clock1.alarms[ala].mnt;
clock1.alarms[ala].dow;
*/
{
byte boo;
char msg[14];
byte button_pressed;
byte j = 0;
byte i;
lcd.clear();
lcd.print(" Alarm list (u/d/e)");
while (1)
{
button_pressed = wait_on_escape(500);
switch (button_pressed)
{
case 0:
break;
case 1: // up key
if (j > 1)
{
j = (j - 3) % (Max_alarms - 1);
}
break;
case 2: // down key
if (j < Max_alarms - 2)
{
j = (j + 3) % (Max_alarms - 1);
}
break;
case 6: // escape key
return;
default:
break;
}
for (i = j; i < (j + 3); i++)
{
lcd.setCursor(0, (i % 3) + 1);
if (i > Max_alarms - 1)
{
// Clear text on line for alarms which don't exist.
lcd.print(" ");
}
else
{
sprintf(msg, "Alm %1d %2d:%02d ", i, clock1.alarms[i].hr, clock1.alarms[i].mnt);
boo = clock1.alarms[i].dow;
lcd.print(msg);
if (boo == 0)
{
lcd.print("OFF ");
}
if (boo == 1)
{
lcd.print("Daily ");
}
if (boo == 2)
{
lcd.print("Week Day");
}
if (boo == 3)
{
lcd.print("Week End");
}
if (boo == 4)
{
lcd.print("Once ");
}
}
}
}
}
/*============================================================================================================================*/
int top_menu_function_5() //Adjust alarm run time
{
int user_input;
phi_prompt_struct myIntegerInput;
user_input = EEPROM.read(EEPROM_user + 0);
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = 240; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 7; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Alarm run time"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1)
{
alarm_run_time = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
EEPROM.write(EEPROM_user + 0, alarm_run_time);
delay(100);
}
else
return (0);
}
/*============================================================================================================================*/
/*
This is my attempt to add the menu at what time to turn off the blanket - EVERY DAY!
*/
void top_menu_function_6() //Blanket off time
{
int user_input;
phi_prompt_struct myIntegerInput;
user_input = blanket_off_time_hr;
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = 23; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 8; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
lcd.print("Blanket off time:"); // Prompt user for input
lcd.setCursor(0, 1);
lcd.print("Hour:");
lcd.setCursor(0, 2);
lcd.print("Minute:"); // Prompt user for input
lcd.setCursor(8, 2);
lcd.print(blanket_off_time_mnt);
if (input_integer(&myIntegerInput) != -1)
{
blanket_off_time_hr = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
}
user_input = blanket_off_time_mnt;
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = 59; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 8; // Display prompt at column 7
myIntegerInput.row = 2; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
if (input_integer(&myIntegerInput) != -1)
{
blanket_off_time_mnt = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
//
EEPROM.write(EEPROM_user + 1, blanket_off_time_hr);
delay(100);
EEPROM.write(EEPROM_user + 2, blanket_off_time_mnt);
delay(100);
}
else
return;
}
/*============================================================================================================================*/
void top_menu_function_7() //Skip day settings
{
//
boolean week;
lcd.clear();
lcd.print(F("Which day to skip? ")); // Don't know if I need this line. See next line.
skip_day = simple_select_list("Which day to skip\nOff\nMonday\nTuesday\nWednesday\nThursday\nFriday\n");
skip_day = skip_day + 1;
Serial.print("Skip day ");
Serial.println(skip_day);
// Need to now set which week to skip.
//
week = simple_select_list("Which week?\nThis\nNext\n");
Serial.print("Week ");
Serial.println(week);
Serial.print("Week num ");
Serial.println(week_num);
week_num = week ^ (week_num & 1); // 2017 06 24 added ( ) around the week_num & 1 part
Serial.print("Week XOR week_num ");
Serial.println(week_num);
Serial.println("-------------");
lcd.clear();
lcd.print("day / week_num");
lcd.setCursor(0, 1);
lcd.print(skip_day);
lcd.print(" ");
lcd.print(week_num);
EEPROM.write(EEPROM_user + 6, skip_day);
delay(100);
EEPROM.write(EEPROM_user + 7, week_num);
delay(1500);
return;
}
/*============================================================================================================================*/
boolean top_menu_function_8() //Audio flag alterer.
{
int user_input;
int audio_flag;
phi_prompt_struct myIntegerInput;
user_input = EEPROM.read(EEPROM_user + 8);
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 0; // Lower limit
myIntegerInput.high.i = 2; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 7; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 1; // The number occupies 2 characters space
myIntegerInput.option = 0; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Audio control"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1)
{
audio_flag = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
if (input_integer(&myIntegerInput) != -1)
{
EEPROM.write(EEPROM_user + 8, audio_flag);
delay(100);
}
}
else
return (0);
}
/*============================================================================================================================*/
void top_menu_function_9()
{
show_keys();
}
/*============================================================================================================================*/
int top_menu_function_10() //Adjust Light on time
{
int user_input;
phi_prompt_struct myIntegerInput;
user_input = EEPROM.read(EEPROM_user + 9);
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 1; // Lower limit
myIntegerInput.high.i = 99; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 7; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Light on time"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1)
{
light_run_time = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
EEPROM.write(EEPROM_user + 9, light_run_time);
delay(100);
}
else
return (0);
}
/*============================================================================================================================*/
int top_menu_function_11() //Adjust blanket time
{
int user_input;
phi_prompt_struct myIntegerInput;
user_input = EEPROM.read(EEPROM_user + 10);
myIntegerInput.ptr.i_buffer = &user_input; // Pass the address of the buffer
myIntegerInput.low.i = 1; // Lower limit
myIntegerInput.high.i = 99; // Upper limit
myIntegerInput.step.i = 1; // Step size
myIntegerInput.col = 7; // Display prompt at column 7
myIntegerInput.row = 1; // Display prompt at row 1
myIntegerInput.width = 2; // The number occupies 2 characters space
myIntegerInput.option = 1; // Option 0, space pad right, option 1, zero pad left, option 2, space pad left.
lcd.clear();
center_text("Blanket run time"); // Prompt user for input
if (input_integer(&myIntegerInput) != -1)
{
blanket_run_time = user_input; // If the user didn't press escape (return -1) then update the ultimate storage with the value in the buffer.
EEPROM.write(EEPROM_user + 10, blanket_run_time);
delay(100);
}
else
return (0);
}
/*============================================================================================================================*/
int top_menu_function_12() //Test audio outputs of audio card
{
audio_test();
}
/*============================================================================================================================*/
The error seems quite obvious. You are calling the render_RTC() function and it is not in the sketch. Where did you get the code that tries to call it ?