Abe-Z
Published

The Talking Alarm Clock

Customized Time Announcement and Wake-Up Alarming using MP3 audio files.

AdvancedFull instructions provided16 hours99
The Talking Alarm Clock

Things used in this project

Hardware components

WIZ750SR
WIZnet WIZ750SR
WIZ750SR-232 module.
×1
Arduino Mega 2560 & Genuino Mega 2560
Arduino Mega 2560 & Genuino Mega 2560
×1
gen4-uLCD-32PT
4D Systems gen4-uLCD-32PT
SK-gen4-32PT (Starter Kit) This specific gen4 module features a 3.2” color TFT LCD display, with resistive touch.
×1
SparkFun DeadOn RTC Breakout - DS3234
×1
SparkFun PRT-00337
Coin Cell Battery - 12mm (CR1225) for RTC above.
×1
SparkFun MP3 Player Shield
SparkFun MP3 Player Shield
DEV-12660
×1
SparkFun microSD Card with Adapter - 16GB (Class 10) COM-13833
for MP3 Player
×1
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
COM-09151 for MP3 player
×2
SparkFun LED Tactile Button- White COM-10439
LED Tactile Button- White
×1
SparkFun LED Tactile Button Breakout BOB-10467
LED Tactile Button Breakout
×1
Resistor 10k ohm
Resistor 10k ohm
for pushbutton input
×1
Resistor 100 ohm
Resistor 100 ohm
for pushbutton light output
×1
Mouser max233cpp
RS-232 Interface IC 5V Multi-Channel RS-232 Driver/Receiver
×1
Mouser 20 pin dip socket
20 pin dip socket for max233cpp
×1
Mouser 12vdc Power Supply
Output connector: 2.1mm x 5.5mm female center positive
×1
Mouser Enclosure
Mouser #: 563-CU-3283 Mfr. #: CU-3283 Enclosures, Boxes, & Cases 6.1X4.6X2.2
×1
Amazon Web Services 6ft ethernet patch cable
Connects the WIZ750SR board to the LAN)
×1
USB-A to B Cable
USB-A to B Cable
USB 2.0 A-Male to B-Male Cable (for programming Arduino Mega)
×1

Software apps and online services

TAC - PC software application download
ABEtronics - TAC Web Site!! (Check IT Out)

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
solder iron and solder
SparkFun PRT-14284
Jumper Wires Premium 4" M/M - 26 AWG (30 Pack)
SparkFun PRT-12794
Jumper Wires - Connected 6" (M/F, 20 pack)
4D Systems 1/8" LCD mounting screws
4 ea. 1/8" LCD mounting screws

Story

Read more

Custom parts and enclosures

The Talking Alarm Clock User Manual

User Manual

WIZ750SR - TAC Hardware Instructions

Hardware assembly Instructions

4D Gen uLCD 32PT Program File

Use to program your LCD Display

MP3 - Bit Rate 32kbps

All Audio Files

Schematics

Electrical Schematic

Code

aClock

C/C++
Arduino Mega 2560 R3 software
// ================================================================================================
// Project: Talking Alarm Clock by ABEtronics 2018.
// Date:    5-6-18 v1.00
// Author:  Jim Abraham
//-------------------------------------------------------------------------------------------------
// WIZ750SR-232            (ETHERNET TO SERIAL INTERFACE)
// Arduino MEGA 2560 Rev3  (CONTROL BOARD)
// GEN4-uLCD-32PT          (LCD DISPLAY)
// MP3 Shield              (MP3 player)
// RTC Deadon              (Real Time Clock)
// ================================================================================================
// ------------------------------------------------------------------------------
// Set-Up Libraries
// ------------------------------------------------------------------------------
#include <SPI.h>            // SPI library
#include <SdFat.h>          // SDFat Library
#include <SdFatUtil.h>      // SDFat Util Library
#include <SFEMP3Shield.h>   // Mp3 Shield Library
#include <genieArduino.h>   // LCD Library
// ------------------------------------------------------------------------------
Genie genie;
SdFat sd;                   // Create object to handle SD functions
SFEMP3Shield MP3player;     // Create MP3 library object
// ------------------------------------------------------------------------------
// Initialize Variables
// ------------------------------------------------------------------------------
// REAL TIME CLOCK (RTC)
// ------------------------------------------------------------------------------
int RTC_SEC = 0;
int RTC_MIN = 0;
int RTC_HR = 0;
int RTC_AMPM = 0;
int RTC_MON = 0;
int RTC_DAY = 0;
int RTC_YR = 0;
int rtc_cs = 53; //RTC chip select.
int S_day = 0;
int S_month = 0;
int S_year = 18;
int SEC = 0;
int MIN = 0;
int HR = 0;
int AMPM = 0;
int ap = 0;
int tti = 0;
int hris = 0;
int minis = 0;
int ampmis = 0;
// ------------------------------------------------------------------------------
// LCD
// ------------------------------------------------------------------------------
int background;
int background_prev = 8;
int wakeupscreen;
int LCD_CLR = 0;
// ------------------------------------------------------------------------------
// ALARMING
// ------------------------------------------------------------------------------
int Set_WU_Alarm = 0;
int WAKE_UP_JACK = 0;
int TEST_Wakeup_Alarm = 0;
int Snooze_MIN = 0;
int Snooze_HR = 0;
int Snooze_PB = 0;
int Snooze_PB_PRESSED = 0;
int setAlarmPB_release = 0;
int SnoozePB_release = 0;
int SnoozePB_alarm_release = 0;
int MIN_ALARM = 0;
int HR_ALARM = 0;
int HR_ALARM1 = 0;
int AMPM_ALARM = 0;
int x = 0;
int PB_PRESSED_release = 0;
// ------------------------------------------------------------------------------
// MP3
// ------------------------------------------------------------------------------
int vol = 0;
int vol_alarm = 0;
int alarm_flag = 0;
int alarm_track;
int good_day = 0;
int hand = 0;
int pmp3f = 0;
int song = 150;
int BL = 150;
int announce_hourly;
int announce_TOH = 0;
int announce_TOH1=0;
// ------------------------------------------------------------------------------
// Set-Up I/O Pin Mapping and Function.
// ------------------------------------------------------------------------------
//Digital I/O Pins:
// D48 - IN   alarm/snooze pb
// D49 - OUT  alarm/snooze pb light
// D10 - OUT  Reset the LCD
//------------------------------------------------------------------
int SnoozePB = 48;
int snoozepbled = 49;
int LCD_Reset = 10;
int Test_LED13 = 13;
int WIZ750SR_nReset=46;

// ================================================================================================
// SETUP ROUTINE
// ================================================================================================
void setup()
{
  // ------------------------------------------------------------------------------
  // Set-Up I/O Pins:
  // ------------------------------------------------------------------------------
  // Set-Up Input Pins
  //-------------------------------------------------------------------------------
  // Use Snooze/Alarm PB:
  // - To set alarm on/off press for 2 seconds.
  // - When alarming press to snooze. (7 min alarm trigger)
  // - When not in alarm mode press to announce time.
  // ------------------------------------------------------------------------------
  pinMode(SnoozePB, INPUT_PULLUP);
  // ------------------------------------------------------------------------------
  // Set-Up Output Pins
  // ------------------------------------------------------------------------------
  pinMode(snoozepbled, OUTPUT);     // PB LIGHT
  pinMode(rtc_cs, OUTPUT);          // RTC chip select
  pinMode(LCD_Reset, OUTPUT);       // Set D10 on Arduino to Output (Display Reset)
  pinMode(Test_LED13, OUTPUT);      // Test LED
  pinMode(WIZ750SR_nReset, OUTPUT); // Reset WIZ750SR Module

  // ------------------------------------------------------------------------------
  // Set-Up Serial Ports
  // ------------------------------------------------------------------------------
  // #0 serial communication for PC 9600,8N1
  // ------------------------------------------------------------------------------
  Serial.begin(9600);       // PC

  // ------------------------------------------------------------------------------
  // #1 serial communication for WIZNET board (serial to ethernet) 9600,8N1
  // ------------------------------------------------------------------------------
  Serial1.begin(9600);      // WIZ750SR-232

  // ------------------------------------------------------------------------------
  // #2 serial communication for LCD DISPLAY 115200,8N1
  // ------------------------------------------------------------------------------
  Serial2.begin(115200);    // GEN4-uLCD-32PT.
  genie.Begin(Serial2);     // Use Serial1 for talking to the Genie Library, and to the 4D Systems display
  genie.AttachEventHandler(myGenieEventHandler); // Attach the user function Event Handler for processing events

  // ------------------------------------------------------------------------------
  // Reset the Display.
  // THIS IS IMPORTANT AND CAN PREVENT OUT OF SYNC ISSUES, SLOW SPEED RESPONSE ETC
  // If NOT using a 4D Arduino Adaptor, digitalWrites must be reversed as Display Reset is Active Low,
  // and the 4D Arduino Adaptors invert this signal so must be Active High.
  // ------------------------------------------------------------------------------
  digitalWrite(LCD_Reset, 0);         // Reset the Display via D10
  digitalWrite(WIZ750SR_nReset, 0);   // Reset WIZ750SR (ative low)
  delay(100);
  digitalWrite(LCD_Reset, 1);         // unReset the Display via D10
  delay(1000);
  digitalWrite(WIZ750SR_nReset, 1);   // Remove reset signal from WIZ750SR
  delay (2500);                       // Let the display start up after the reset
  digitalWrite(Test_LED13, 0);

  // ------------------------------------------------------------------------------
  // Initialize the RTC.
  // ------------------------------------------------------------------------------
  RTC_init();
  
  // ------------------------------------------------------------------------------
  // Initialize the SD card and checks for errors.
  // ------------------------------------------------------------------------------
  Sd_init();
  
  // ------------------------------------------------------------------------------
  // Initialize Functions
  // ------------------------------------------------------------------------------
  Snooze_PB = 0;
  Snooze_MIN = 0;
  pmp3f = 4;               // Stop Playing mp3 alarm track.
  SilenceAlarm();
  Read_RTC_Alarm_Time();   // Get stored alarm time, vol, track
  Read_RTC_SRAM();         // Get background, wakeup screen, announce hourly values.
  Read_Display_Time();     // Read Date and time and display on LCD.
  delay(1000);
  
  // ------------------------------------------------------------------------------
  //Initialize the MP3 Player Shield.
  // ------------------------------------------------------------------------------
  MP3_init();
  // ------------------------------------------------------------------------------
}//SETUP ROUTINE END

// ================================================================================================
// MAIN LOOP
// ================================================================================================
void loop()
{
  Read_Display_Time();    // Read Date and time and display on LCD.
  Announce_Hourly();      // Announce the top of the hour.
  Check_Serial_Com();     // Check for serial commands.
  Check_PB_Status();      // Check Pushbutton Status.
  WakeUpJackie();         // Check if alarm set to wake up Jackie.
  Check_MP3_Player();     // Check if track needs to be played.
}
//MAIN LOOP END
// ================================================================================================

// ================================================================================================
// INITIALIZING ROUTINES
// ================================================================================================
// ------------------------------------------------------------------------------
//Initialize the LCD.
// ------------------------------------------------------------------------------
void LCD_init()
{
  // Change background and text that was selected.
  if (background == 1) {genie.WriteObject(GENIE_OBJ_FORM, 0, 1);}
  if (background == 2) {genie.WriteObject(GENIE_OBJ_FORM, 1, 1);}
  if (background == 3) {genie.WriteObject(GENIE_OBJ_FORM, 2, 1);}
  if (background == 4) {genie.WriteObject(GENIE_OBJ_FORM, 3, 1);}
}

// ------------------------------------------------------------------------------
// Set-Up RTC
// ------------------------------------------------------------------------------
//day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
//SetTimeDate(28,10,14,11,59,50);
// ------------------------------------------------------------------------------
int RTC_init()
{
  // start the SPI library:
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3); //mode 3 works
  //set control register
  digitalWrite(rtc_cs, 0);
  SPI.transfer(0x8E); //control reg
  SPI.transfer(0x37); //37=00100101, 60= disable Osciallator and Battery SQ wave @1hz, temp compensation, Alarms disabled
  digitalWrite(rtc_cs, 1);
  delay(10);
}

// ------------------------------------------------------------------------------
// initSD() initializes the SD card and checks for an error.
// ------------------------------------------------------------------------------
void Sd_init()
{
  if (!sd.begin(SD_SEL, SPI_FULL_SPEED)) sd.initErrorHalt();
  // depending upon your SdCard environment, SPI_HALF_SPEED may work better.
  if (!sd.chdir("/")) sd.errorHalt("sd.chdir");
}

// ------------------------------------------------------------------------------
//Initialize the MP3 Player Shield
// ------------------------------------------------------------------------------
void MP3_init()
{
  uint8_t result = MP3player.begin();
  // set speaker volume and play start-up mp3 file.
  MP3player.setVolume(0, 0);        //set new volume. 0=max, 255=lowest (off)
  MP3player.setMonoMode(0);         //set Stereo Output.
  MP3player.playTrack(225);         //Play "Hello"
  delay(1500);                      //wait
  MP3player.playTrack(224);         //Play "system Ready"
  delay(1000);                      //wait
}
// ================================================================================================
// ROUTINES
// ================================================================================================
// ------------------------------------------------------------------------------
// Check Pushbutton Status
// ------------------------------------------------------------------------------
void Check_PB_Status()
{
// PB pressed = low
// alarm not enabled - when pressed and held for 3 seconds turn-on alarm.
// alarm not enabled - when pressed announce time.
// alarm enabled - when pressed snooze alarm enabled.
// alarm enabled - when pressed and held for 3 seconds turn-off alarm.
// ------------------------------------------------------------------------------

// ------------------------------------------------------------------------------
// alarm not enabled - when pressed and held for 3 seconds turn-on alarm.
// alarm not enabled - when pressed announce time.
// Set_WU_Alarm == 0 Wake up alarm disabled.
// ------------------------------------------------------------------------------
 if ((digitalRead(SnoozePB) == LOW) && (PB_PRESSED_release == 0))
 {
      if (Set_WU_Alarm == 0)
        {
           PB_PRESSED_release = 1;
           x = 0;
          do
          {
            delay(50);
            x = x + 1;
            if (x >= 20) {break;} // pb held down for 2 seconds.
          } while (digitalRead(SnoozePB) == LOW);
      
          if (digitalRead(SnoozePB) == HIGH)    // Announe Time
          {
            Snooze_PB_PRESSED = 3;
            Announce_Time();
            return;
        }
        if (digitalRead(SnoozePB) == LOW)      // Turn On Alarm
        {
          Enable_Wakeup_Alarm();
          return;
        } 
      }

// ------------------------------------------------------------------------------
// alarm enabled - when pressed snooze alarm enabled.
// alarm enabled - when pressed and held for 3 seconds turn-off alarm. 
// ------------------------------------------------------------------------------
    if (Set_WU_Alarm == 1)
        {
          PB_PRESSED_release = 1;
          x = 0;
          do
          {
            delay(50);
            x = x + 1;
            if (x >= 20) {break;} // pb held down for 2 seconds.
          } while (digitalRead(SnoozePB) == LOW);
      
          if (digitalRead(SnoozePB) == HIGH)    // Announce or Snooze
          {
            Snooze_PB_PRESSED = 3;
            if(!MP3player.isPlaying())  // Announce
            {
              Announce_Time();
              return;
            }  
            if(MP3player.isPlaying())   // Snooze
            { 
              Snooze_Alarm();
              return;
            }   
          }
          if (digitalRead(SnoozePB) == LOW)   // Turn Off Alarm
          {
            Disable_Wakeup_Alarm();
            return;
          } 
        }     
  }
// ------------------------------------------------------------------------------
 if (digitalRead(SnoozePB) == HIGH) {PB_PRESSED_release = 0;}
}

// ------------------------------------------------------------------------------
// Read RTC and Display Time on LCD
// ------------------------------------------------------------------------------
void Read_Display_Time()
{
  if (!MP3player.isPlaying())
  {
    ReadTimeDate();
  }
}

// ------------------------------------------------------------------------------
// Announce the current time when Snooze PB pressed or Top of the Hour.
// ------------------------------------------------------------------------------
void Announce_Time()
{
  if (announce_TOH == 1 || Snooze_PB_PRESSED == 3)
    {  
    Snooze_PB_PRESSED = 0;
    announce_TOH = 0;
    Read_Display_Time();
    HR = RTC_HR;
    MIN = RTC_MIN;
    AMPM = ap;
    tti = 0;
    hris = 0;
    minis = 0;
    ampmis = 0;
    hand = 0;
    MP3player.setVolume(0, 0);
    good_day = 0;
    // good morning =    220
    // good afternoon =  221
    // good evening =    222
    // good night =      223
    // AM = Good Morning.
    // PM & 12-5 Good Afternoon.
    // PM & 6-9 Good Evening.
    // PM & 10-11 Good Night.
    if (AMPM == 1)
    {
      MP3player.playTrack(220);            //Good Morning.
      good_day = 1;
    }
    if ((AMPM == 2) && ((HR == 12) || (HR == 1) || (HR == 2) || (HR == 3) || (HR == 4) || (HR == 5)))
    {
      MP3player.playTrack(221);           //Good Afternoon
      good_day = 1;
    }
    if ((AMPM == 2) && ((HR == 6) || (HR == 7) || (HR == 8) || (HR == 9)))
    {
      MP3player.playTrack(222);           //Good Evening
      good_day = 1;
    }
    pmp3f = 1;                            //play mp3 files flag
    playmp3();
    }
}

// ------------------------------------------------------------------------------
//Announce Top of the Hour Time. (Change display and announce)
// ------------------------------------------------------------------------------
void Announce_Hourly()
{
  if (announce_hourly == 1 && RTC_MIN == 0)
  {
    if (RTC_SEC == 0 && announce_TOH1==0)
    {
      announce_TOH1=1;
      genie.WriteObject(GENIE_OBJ_FORM, 7, 1);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x12, RTC_HR);
      //RTC 1=AM, 2=PM
      if (ap == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x09, 1);} // LCD PM=0, AM=1
      if (ap == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x09, 0);} // LCD PM=0, AM=1
      announce_TOH = 1;
      Announce_Time();
    }
    if (!MP3player.isPlaying() && pmp3f==0 && announce_TOH1==1)
      {
        announce_TOH1=0;
        LCD_init();
      }
  }
}

// ------------------------------------------------------------------------------
// Check if ready to wake up Jackie.
// ------------------------------------------------------------------------------
void WakeUpJackie()
{
  if (Set_WU_Alarm == 1)
  {
    if (alarm_flag == 0)
    {
      CheckAlarmTime();                                // check if RTC alarm bit set.

      if (WAKE_UP_JACK == 1 || TEST_Wakeup_Alarm == 1) // If alarm bit set, play alarm.
      {
        if (!MP3player.isPlaying())
        {
          MP3player.setVolume(0, 0); // set new volume. 0=max, 255=lowest (off)
          MP3player.playTrack(alarm_track);    // Play Alarm Track 1st time.
          Snooze_PB = 1;
          digitalWrite(snoozepbled, 1);        // Turn on Snooze pb LED.
          alarm_flag = 1;                      // Alarm played.
          TEST_Wakeup_Alarm = 0;
          if (wakeupscreen == 1) {genie.WriteObject(GENIE_OBJ_FORM, 5, 1);}
          if (wakeupscreen == 2) {genie.WriteObject(GENIE_OBJ_FORM, 4, 1);}
          if (wakeupscreen == 3) {genie.WriteObject(GENIE_OBJ_FORM, 6, 1);}
        }
      }
    }
    else
    {
      if ((Snooze_PB == 3) && (Snooze_MIN == RTC_MIN))
      {
        if (!MP3player.isPlaying())
        {
          MP3player.setVolume(0, 0); // set new volume. 0=max, 255=lowest (off)
          MP3player.playTrack(alarm_track);         //Play Alarm Track AGAIN.
          Snooze_PB = 2;
          digitalWrite(snoozepbled, 1);             //Turn on Snooze pb LED.
          if (wakeupscreen == 1) {genie.WriteObject(GENIE_OBJ_FORM, 5, 1);}
          if (wakeupscreen == 2) {genie.WriteObject(GENIE_OBJ_FORM, 4, 1);}
          if (wakeupscreen == 3) {genie.WriteObject(GENIE_OBJ_FORM, 6, 1);}
        }
      }
    }
  }
}

// ------------------------------------------------------------------------------
// Snooze Alarm?
// Snooze_PB
// = 1 play alarm track 1st time.
// = 2 play alarm track after snooze pb pressed and 7 in later.
// = 3 snooze pb pressed.
// ------------------------------------------------------------------------------
void Snooze_Alarm()
{
    LCD_init();
    MP3player.stopTrack();     // Stop Track
    pmp3f = 0;
    Read_Display_Time();
    Snooze_MIN = RTC_MIN + 7;  // + 7 minutes more to snooze!!
    if (HR_ALARM1 == 0) {
      Snooze_HR = HR_ALARM;
    }
    if (Snooze_MIN > 60)
    {
      Snooze_MIN = Snooze_MIN - 60;
      Snooze_HR = HR_ALARM + 1;
      HR_ALARM1 = 1;
    }
    if (Snooze_MIN == 60) {
      Snooze_MIN = 0;
    }
    if (Snooze_HR > 12) {
      Snooze_HR = Snooze_HR - 12;
    }
    Snooze_PB_PRESSED = 1;
    Snooze_PB = 3;
    pmp3f = 4;                //Stop Playing mp3 alarm track.
    //day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
    SetAlarmTime(Snooze_HR, Snooze_MIN, AMPM_ALARM, alarm_track, 0);
}

// ------------------------------------------------------------------------------
// Play MP3 file if commanded.
// ------------------------------------------------------------------------------
void Check_MP3_Player() {
  if (pmp3f > 0) playmp3();
}

// ------------------------------------------------------------------------------
// Write data to RTC SRAM.
// ------------------------------------------------------------------------------
int WriteBackgroundtoRTC(int bg)
{
  // ------------------------------------------
  // Write background # to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                // write 5 address to address reg 98H
  SPI.transfer(5);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                // write data to address 5 via 99h data addres
  SPI.transfer(bg);                  // 1-4
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}
int WriteWakeupScreentoRTC(int wus)
{
  // ------------------------------------------
  // Write Wake Up Screen # to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                // write 6 address to address reg 98H
  SPI.transfer(6);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                // write data to address 6 via 99h data addres
  SPI.transfer(wus);                  // 1-3
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}
int WriteAnnounceHourlytoRTC(int nh)
{
  // ------------------------------------------
  // Write Announce Hourly # to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                // write 7 address to address reg 98H
  SPI.transfer(7);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                // write data to address 7 via 99h data addres
  SPI.transfer(nh);                  // 0-1
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}

// ------------------------------------------------------------------------------
// check Serial communication: if chracter received
// ------------------------------------------------------------------------------
void Check_Serial_Com()
{
  if (Serial1.available() > 0)
  {
    getsercom(Serial1.read());    // get command from serial input
  }
}

// ------------------------------------------------------------------------------
// Check Serial Port for Incoming Characters
// ------------------------------------------------------------------------------
void getsercom(byte key_command)
{
  // MP3 file descriptions (track###.mp3 where ## = 000-255)
  // 1-59              1-59
  // 01-09             101 - 109
  // Alarm Tracks =    150 - 170
  // The Time Is =     200
  // AM =              201
  // PM =              202
  // have a nice day = 210
  // o-clock =         211
  // no =              219
  // good morning =    220
  // good afternoon =  221
  // good evening =    222
  // good night =      223
  // Sys Ready =       224
  // Hello =           225
  //-------------------------------------------------------------
  // Commands:
  // T = Announce Current Time  format: T,hr(1-12),min(1-59),ampm(1-2)
  //                                               min(0) say o-clock
  // H = Announce Current Time Hourly
  // h = Don't Announce Current Time Hourly
  // A = Enter Wake Up Alarm Time format: A,hr(1-12),min(1-59),ampm(1-2),track#,vol
  // P = Play Alarm MP3 Tracks    format: P,track#,vol
  // S = Stop Track               format: S
  // B = Backlight brightness     format: B,128-157 (not used)
  // E = Enable alarm mode.       format: E
  // D = Disable alarm mode.      format: D
  // ! = Test Alarm.              format: T (Play Alarm and disbale again)
  // 1 = background #1
  // 2 = background #2
  // 3 = background #3
  // 4 = background #4
  // 5 = wake up screen #1
  // 6 = wake up screen #2
  // 7 = wake up screen #3

  //--------------------------------------------------------------------------------------
  // Backgrounds
  //--------------------------------------------------------------------------------------
  if (key_command == '1')
  {
    Read_Display_Time();
    genie.WriteObject(GENIE_OBJ_FORM, 0, 1); // change startup screen (#,1 #=form#)
    background = 1;
    WriteBackgroundtoRTC(background);
    return;
  }
  if (key_command == '2')
  {
    Read_Display_Time();
    genie.WriteObject(GENIE_OBJ_FORM, 1, 1); // change startup screen (#,1 #=form#)
    background = 2;
    WriteBackgroundtoRTC(background);
    return;
  }
  if (key_command == '3')
  {
    Read_Display_Time();
    genie.WriteObject(GENIE_OBJ_FORM, 2, 1); // change startup screen (#,1 #=form#)
    background = 3;
    WriteBackgroundtoRTC(background);
    return;
  }
  if (key_command == '4')
  {
    Read_Display_Time();
    genie.WriteObject(GENIE_OBJ_FORM, 3, 1); // change startup screen (#,1 #=form#)
    background = 4;
    WriteBackgroundtoRTC(background);
    return;
  }

  //--------------------------------------------------------------------------------------
  // Wake Up Screens
  //--------------------------------------------------------------------------------------
  if (key_command == '5')
  {
    genie.WriteObject(GENIE_OBJ_FORM, 5, 1); // change startup screen (#,1 #=form#)
    wakeupscreen = 1;
    WriteWakeupScreentoRTC(wakeupscreen);
    return;
  }
  if (key_command == '6')
  {
    genie.WriteObject(GENIE_OBJ_FORM, 4, 1); // change startup screen (#,1 #=form#)
    wakeupscreen = 2;
    WriteWakeupScreentoRTC(wakeupscreen);
    return;
  }
  if (key_command == '7')
  {
    genie.WriteObject(GENIE_OBJ_FORM, 6, 1); // change startup screen (#,1 #=form#)
    wakeupscreen = 3;
    WriteWakeupScreentoRTC(wakeupscreen);
    return;
  }
  //--------------------------------------------------------------------------------------
  //  Enable/Disable Wake Up Alarm
  //--------------------------------------------------------------------------------------
  if (key_command == 'E'){Enable_Wakeup_Alarm();}
  if (key_command == 'D'){Disable_Wakeup_Alarm();}
  
  //--------------------------------------------------------------------------------------
  // Announce Hourly
  //--------------------------------------------------------------------------------------
  if (key_command == 'H')
  {
    announce_hourly = 1;
    WriteAnnounceHourlytoRTC(announce_hourly);
  }
  if (key_command == 'h')
  {
    announce_hourly = 0;
    WriteAnnounceHourlytoRTC(announce_hourly);
  }
  //--------------------------------------------------------------------------------------
  //  TEST Wake Up Alarm
  //--------------------------------------------------------------------------------------
  if (key_command == '!')
  {
    Enable_Wakeup_Alarm();
    TEST_Wakeup_Alarm = 1;
  }

  // ------------------------------------------------------------
  // Set Current Time
  // T, month, day, year, hr, min, sec, AmPm
  // ------------------------------------------------------------
  if (key_command == 'T')
  {
    tti = 0;
    hris = 0;
    minis = 0;
    ampmis = 0;
    hand = 0;
    pmp3f = 0;

    S_month = Serial1.parseInt();      // 1-12
    S_day = Serial1.parseInt();        // 1-31
    S_year = Serial1.parseInt();       // 20xx
    HR = Serial1.parseInt();           // 1-12
    MIN = Serial1.parseInt();          // 1-59, 60=OCLOCK
    SEC = Serial1.parseInt();          // 1-59, 60=OCLOCK
    AMPM = Serial1.parseInt();         // 1=AM, 2=PM
    vol_alarm = Serial1.parseInt();    // Alarm volume
    vol_alarm = 0;
    if (MIN >= 100)
    {
      MIN = MIN - 100;
      // ------------------------------------------------------------
      //day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
      // ------------------------------------------------------------
      SetTimeDate(S_day, S_month, S_year, HR, MIN, SEC);
      MIN = MIN + 100;
    } else
      // ------------------------------------------------------------
      //day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
      // ------------------------------------------------------------
    SetTimeDate(S_day, S_month, S_year, HR, MIN, SEC);
    Read_Display_Time();              //Read Date and time and display on LCD.
    UPDATE_LCD();

    pmp3f = 1;                        //Play mp3 files flag
    good_day = 1;
    MP3player.setVolume(0, 0);
    return;
  }
  // ------------------------------------------------------------
  // Set Wake Up Alarm Time
  // A = Set Wake Up Alarm Time format: A,hr(1-12),min(1-59),ampm(1-2)
  // ------------------------------------------------------------
  if (key_command == 'A')
  {
    tti = 0;
    hris = 0;
    minis = 0;
    ampmis = 0;
    hand = 0;
    pmp3f = 0;
    alarm_flag = 0;
    WAKE_UP_JACK = 0;
    HR = Serial1.parseInt();           // 1-12
    MIN = Serial1.parseInt();          // 1-59, 60=OCLOCK
    AMPM = Serial1.parseInt();         // 1=AM, 2=PM
    alarm_track = Serial1.parseInt();  // Alarm Track#
    vol_alarm = Serial1.parseInt();    // Alarm volume
    vol_alarm = 0;    // Alarm volume
    if (MIN==0 || MIN==59) {announce_hourly=0;}   // Turn off announce hourly is alarm min=0
    // ------------------------------------------------------------
    //Set Wake Up Alarm Time.
    // ------------------------------------------------------------
    HR_ALARM = HR;
    MIN_ALARM = MIN;
    AMPM_ALARM = AMPM;
    // ------------------------------------------------------------
    //day(1-31), month(1-12), year(0-99), hour(0-23), minute(0-59), second(0-59)
    // ------------------------------------------------------------
    SetAlarmTime(HR, MIN, AMPM, alarm_track, 0);
    WriteAlarmDatatoRTC(HR, MIN, AMPM, alarm_track, 0);
    UPDATE_LCD();
    pmp3f = 2;                                 //play mp3 files flag
    MP3player.setVolume(0, 0);
    playmp3();
    return;
  }

  // ------------------------------------------------------------
  // Sample Alarm MP3 Track
  // ------------------------------------------------------------
  if (key_command == 'P')
  {
    song = Serial1.parseInt();         //track #
    vol_alarm = Serial1.parseInt();    //Alarm volume
    vol_alarm = 0;
    if (song > 100)
    {
      pmp3f = 3;                      //play mp3 files flag
      MP3player.setVolume(0, 0);
      return;
    }
  }

  // ------------------------------------------------------------
  // Stop Track
  // ------------------------------------------------------------
  if (key_command == 'S')
  {
    pmp3f = 4;                  //play mp3 track flag
    return;
  }
}//end routine

// ------------------------------------------------------------------------------
// Play MP3 Files
// ------------------------------------------------------------------------------
void playmp3()
{
  // ------------------------------------------------------------
  // Play MP3 Files (Announce Current Time)
  // ------------------------------------------------------------
  if (pmp3f == 1 || pmp3f == 2)
  {
    if (!MP3player.isPlaying() && tti == 0)
    {
      tti = 1;
      MP3player.playTrack(200);                   // The Time is..
      delay(2000);
   }
   
    if (!MP3player.isPlaying() && tti == 1 && hris == 0)
    {
      hris = 1;
      MP3player.playTrack(HR);                   // Hour
    }
    if (!MP3player.isPlaying() && hris == 1 && minis == 0)
    {
      if (MIN == 0)
      {
        MP3player.playTrack(211);                  // O-Clock
        ampmis = 1;
        minis = 1;
      }
      if (MIN < 10)
      {
        MP3player.playTrack(100 + MIN);
        minis = 1;
      }
      if (MIN > 9)
      {
        MP3player.playTrack(MIN);                  // Minute
        minis = 1;
      }
    }
    if (!MP3player.isPlaying() && minis == 1 && ampmis == 0)
    {
      ampmis = 1;
      MP3player.playTrack(200 + AMPM);            // AM or PM (200+1 or 2)
    }

    if (!MP3player.isPlaying() && ampmis == 1 && hand == 0 && pmp3f == 1)
    {
      hand = 1;
      if (good_day == 1) {
        MP3player.playTrack(210); // Have a Good Day!
      }
      else {
        MP3player.playTrack(223); // Good Night.
      }
      pmp3f = 0;
    }
  }

  // ------------------------------------------------------------
  // Play MP3 Files (Play Alarm Track)
  // ------------------------------------------------------------
  if (pmp3f == 3)
  {
    if (!MP3player.isPlaying())
    {
      MP3player.playTrack(song);        //Play Alarm Track
      pmp3f = 0;
      return;
    }
  }
  // ------------------------------------------------------------
  // STOP MP3 Files (STOP Track)
  // ------------------------------------------------------------
  if (pmp3f == 4)
  {
    MP3player.stopTrack();             //Stop Track
    pmp3f = 0;
    return;
  }
}

// ------------------------------------------------------------------------------
// Check Alarm Time on RTC
// ------------------------------------------------------------------------------
int CheckAlarmTime()
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);   //mode 3 works
  digitalWrite(rtc_cs, LOW);    //read RTC.
  SPI.transfer(0x0F);
  unsigned int n = SPI.transfer(0x0F);
  digitalWrite(rtc_cs, HIGH);
  WAKE_UP_JACK = SPI.transfer(0x0F) & B00000001; //A1F=1?
  delay(10);
  return (WAKE_UP_JACK);
}

// ------------------------------------------------------------------------------
// Clear Alarm Bit on RTC
// ------------------------------------------------------------------------------
void SilenceAlarm()
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);  //mode 3 works
  //clear previous alarm
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x0F);          //read reg 0F (control/status RTC reg)
  unsigned int n = SPI.transfer(0x0F);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x8F);          //clear only A1F bit. (Alarm Flag bit)
  SPI.transfer(n & B11111100);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}

// ------------------------------------------------------------------------------
// Read data from RTC SRAM.
// ------------------------------------------------------------------------------
void Read_RTC_SRAM()         // Get stored values.
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  // ------------------------------------------
  // Read Background
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                    // write 5 address to address reg 98H
  SPI.transfer(5);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  background = SPI.transfer(0x05);          // Get Background
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  if (background < 1 || background > 4) {background = 1;}
  
  // ------------------------------------------
  // Read Wake Up Screen
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                    // write 5 address to address reg 98H
  SPI.transfer(6);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  wakeupscreen = SPI.transfer(0x06);          // Get Wake Up Screen
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  if (wakeupscreen < 1 || wakeupscreen > 3) {wakeupscreen = 1;}
  
  // ------------------------------------------
  // Read Announce Hourly
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                    // write 5 address to address reg 98H
  SPI.transfer(7);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  announce_hourly = SPI.transfer(0x07);   // Get Announce Hourly
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  if (announce_hourly > 1) {announce_hourly = 0;}
  
  UPDATE_LCD();
  LCD_init(); //diaplay start up form
}

// ------------------------------------------------------------------------------
void Read_RTC_Alarm_Time()         // Get Alarm time stored in RTC + track# and volume.
// ------------------------------------------------------------------------------
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);                //mode 3 works
  // 0h = alarm track #. (150-170)
  // 1h = alarm volume.  (0-50)
  // 2h = alarm hour.    (1-12)
  // 3h = alarm minute.  (0-59)
  // 4h = alarm ampm.    (1-2)
  // ------------------------------------------
  // Read Alarm Track from SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                       // write 0 address to address reg 98H
  SPI.transfer(0);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  alarm_track = SPI.transfer(0x00);     // Get Alarm Track #
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  if (alarm_track < 150 || alarm_track > 170) {alarm_track = 150;}
  
  // ------------------------------------------
  // Read Alarm Volume from SRAM
  // ------------------------------------------
  //    digitalWrite(rtc_cs, LOW);
  //    SPI.transfer(0x098);                  // write 1 address to address reg 98H
  //    SPI.transfer(1);
  //    digitalWrite(rtc_cs, HIGH);
  //    delay(10);

  //    digitalWrite(rtc_cs, LOW);
  //    SPI.transfer(0x19);
  //    vol_alarm = SPI.transfer(0x01);        // Get Volume
  //    digitalWrite(rtc_cs, HIGH);
  //    delay(10);
  vol_alarm = 0;
  
  // ------------------------------------------
  // Read Alarm Hour from SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                    // write 2 address to address reg 98H
  SPI.transfer(2);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  HR_ALARM = SPI.transfer(0x02);          // Get Hour
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  // ------------------------------------------
  // Read Alarm Minute from SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                    // write 3 address to address reg 98H
  SPI.transfer(3);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  MIN_ALARM = SPI.transfer(0x03);         // Get Minute
  digitalWrite(rtc_cs, HIGH);
  delay(10);
 
  // ------------------------------------------
  // Read Alarm AMPM from SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                   // write 4 address to address reg 98H
  SPI.transfer(4);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x19);
  AMPM_ALARM = SPI.transfer(0x04);       // Get AMPM
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}

// ------------------------------------------------------------------------------
// Set Alarm Time on RTC
// ------------------------------------------------------------------------------
int SetAlarmTime(int h, int mi, int ap, int alm_track, int alm_vol)
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);                //mode 3 works

  int TimeDate [3] = {0, mi, h}; //0,1,2
  for (int i = 0; i <= 2; i++)
  {
    int b = TimeDate[i] / 10;
    int a = TimeDate[i] - b * 10;
    if (i == 2)                                  //hr
    {
      //ap 1=am, 2=pm
      if (TimeDate[2] < 10)
      {
        if (ap == 2)                             //PM
        {
          TimeDate[2] = TimeDate[2] + B01100000;//bit 7=0, 6=1 (12 hr), 5=1 (PM), 4=0 (10hr)
        }                                       //bit 7 6 5 4 3 2 1 0
        if (ap == 1)                             //AM
        {
          TimeDate[2] = TimeDate[2] + B01000000;//bit 7=0, 6=1 (12 hr), 5=0(AM), 4=0 (10hr)
        }                                       //bit 7 6 5 4 3 2 1 0
      }

      else if (TimeDate[2] > 9)
      {
        TimeDate[2] = TimeDate[2] - 10;
        if (ap == 2)                            //PM
        {
          TimeDate[2] = TimeDate[2] + B01110000;//bit 7=0, 6=1 (12 hr), 5=1 (PM), 4=1 (10hr)
        }
        if (ap == 1)                            //AM
        {
          TimeDate[2] = TimeDate[2] + B01010000;//bit 7=0, 6=1 (12 hr), 5=0 (AM), 4=0 (10hr)
        }
      }
    }

    if (i != 2)                                  //hr
    {
      TimeDate[i] = a + (b << 4);
    }
    // ------------------------------------------
    // Write alarm time to RTC. (sec=0, min, hour)
    // ------------------------------------------
    // SET ALARM ON RTC
    // 1. Set alarm time, 87,88,89h
    // ------------------------------------------
    digitalWrite(rtc_cs, LOW);
    SPI.transfer(i + 0x87);                    // i=0 seconds=0, i=1 set alarm min, i=2 set alarm hour.
    SPI.transfer(TimeDate[i]);
    digitalWrite(rtc_cs, HIGH);
    delay(10);
  }

  // ------------------------------------------
  // Clear previous alarm
  // ------------------------------------------
  // 2. 0Fh/8Fh  Bit 0: Alarm 1 Flag (A1F)=0
  // 3. 0AH/8AH  BIT 7: ALARM 1 REGISTER MASK BITS (A1M4) = 1 Alarm when hours, minutes, and seconds match
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x0F);                        // read reg 0F (control/status RTC reg)
  unsigned int n = SPI.transfer(0x0F);
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x8F);
  SPI.transfer(n & B11111100);              // clear only A1F bit. (Alarm Flag bit)
  digitalWrite(rtc_cs, HIGH);
  delay(10);

  // ------------------------------------------
  // Alarm when h,m,s ampm = alarm time
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x8A);                        // set A1M4 (Alarm 1)
  SPI.transfer(B10000000);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}

// ------------------------------------------------------------------------------
// Write data to RTC SRAM.
// ------------------------------------------------------------------------------
int WriteAlarmDatatoRTC(int h, int mi, int ap, int alm_track, int alm_vol)
{
  // ------------------------------------------
  // 0h = alarm track #. (150-170)
  // 1h = alarm volume.  (0-50)
  // 2h = alarm hour.    (1-12)
  // 3h = alarm minute.  (0-59)
  // 4h = alarm ampm.    (1-2)
  // ------------------------------------------
  // Write Alarm Track to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                       // write 0 address to address reg 98H
  SPI.transfer(0);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                        // write data to address 0 via 99h data address
  SPI.transfer(alm_track);                   // Alarm Track #
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  // ------------------------------------------
  // Write Alarm Volume to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                       // write 1 address to address reg 98H
  SPI.transfer(1);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                        // write data to address 1 via 99h data addres
  SPI.transfer(alm_vol);                     // Volume
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  // ------------------------------------------
  // Write Alarm Hour to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                       // write 2 address to address reg 98H
  SPI.transfer(2);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                        // write data to address 2 via 99h data addres
  SPI.transfer(h);                           // Hour
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  // ------------------------------------------
  // Write Alarm Minute Hour to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                       // write 3 address to address reg 98H
  SPI.transfer(3);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                        // write data to address 3 via 99h data addres
  SPI.transfer(mi);                          // Minute
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  // ------------------------------------------
  // Write Alarm AMPM Hour to SRAM
  // ------------------------------------------
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x098);                       // write 4 address to address reg 98H
  SPI.transfer(4);
  digitalWrite(rtc_cs, HIGH);
  delay(10);
  digitalWrite(rtc_cs, LOW);
  SPI.transfer(0x99);                        // write data to address 4 via 99h data addres
  SPI.transfer(ap);                          // AMPM
  digitalWrite(rtc_cs, HIGH);
  delay(10);
}

// ------------------------------------------------------------------------------
// Set Time and Date on RTC
// ------------------------------------------------------------------------------
// bit 7 6 5 4 3 2 1 0
// 3 2 1 0 = 0-9 BCD
// 7 = 0
// 6 = 0 for 24 or 1 12 hour
// 5 = 0 for AM or 1 PM
// 4 = 1 for 10 hour
// ------------------------------------------------------------------------------
int SetTimeDate(int d, int mo, int y, int h, int mi, int s)
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3); // mode 3 works

  int TimeDate [7] = {s, mi, h, 0, d, mo, y}; //0=second,1=minute,2=hour,3=null,4=day,5=month,6=year
  for (int i = 0; i <= 6; i++)
  {
    if (i == 3) {
      i++; //only when i=3, increment to 4.
    }

    int b = TimeDate[i] / 10;
    int a = TimeDate[i] - b * 10;

    if (i == 2)                                  //hr
    {
      ap = AMPM;                                 //1=am, 2=pm
      if (TimeDate[2] < 10)
      {
        if (ap == 2)                             //PM
        {
          TimeDate[2] = TimeDate[2] + B01100000;//bit 7=0, 6=1 (12 hr), 5=1 (PM), 4=0 (10hr)
        }                                       //bit 7 6 5 4 3 2 1 0
        if (ap == 1)                             //AM
        {
          TimeDate[2] = TimeDate[2] + B01000000;//bit 7=0, 6=1 (12 hr), 5=0(AM), 4=0 (10hr)
        }                                       //bit 7 6 5 4 3 2 1 0
      }

      else if (TimeDate[2] > 9)
      {
        TimeDate[2] = TimeDate[2] - 10;
        if (ap == 2)                            //PM
        {
          TimeDate[2] = TimeDate[2] + B01110000;//bit 7=0, 6=1 (12 hr), 5=1 (PM), 4=1 (10hr)
        }
        if (ap == 1)                            //AM
        {
          TimeDate[2] = TimeDate[2] + B01010000;//bit 7=0, 6=1 (12 hr), 5=0 (AM), 4=0 (10hr)
        }
      }
    }

    if (i != 2){TimeDate[i] = a + (b << 4);}    //hr

    digitalWrite(rtc_cs, LOW);
    SPI.transfer(i + 0x80);                    //write data to RTC.
    SPI.transfer(TimeDate[i]);
    digitalWrite(rtc_cs, HIGH);
    delay(10);
  }//for loop
}

// ------------------------------------------------------------------------------
// Read Time and Date on RTC
// ------------------------------------------------------------------------------
void ReadTimeDate()
{
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);                // mode 3 works
  int TimeDate [7]; //0=second,1=minute,2=hour,3=null,4=day,5=month,6=year
  for (int i = 0; i <= 6; i++)
  {
    if (i == 3) {
      i++;
    }
    digitalWrite(rtc_cs, LOW);             // read RTC.
    SPI.transfer(i + 0x00);
    unsigned int n = SPI.transfer(0x00);
    digitalWrite(rtc_cs, HIGH);
    int a = n & B00001111;                 // mask out bits 7-4.
    //----------------------------------------------------------------------------------
    // Get Hour.
    //----------------------------------------------------------------------------------
    if (i == 2)                     // hour
    {
      int b = (n & B00010000) >> 4; // 24 hour mode
      int b10 = 10 * b;             // = 0 or 10
      TimeDate[2] = a + b10;        // add 0 or 10
      b = (n & B00100000) >> 5;     // AM/PM?
      ap = 1 + b;                   // AM=1,PM=2?
    }
    //----------------------------------------------------------------------------------
    // Get Day.
    //----------------------------------------------------------------------------------
    else if (i == 4)                       // day
    {
      int b = (n & B00110000) >> 4;
      TimeDate[i] = a + b * 10;
    }
    //----------------------------------------------------------------------------------
    // Get Month.
    //----------------------------------------------------------------------------------
    else if (i == 5)                       // mo
    {
      int b = (n & B00010000) >> 4;
      TimeDate[i] = a + b * 10;
    }
    //----------------------------------------------------------------------------------
    // Get Year.
    //----------------------------------------------------------------------------------
    else if (i == 6)                      // yr
    {
      int b = (n & B11110000) >> 4;
      TimeDate[i] = a + b * 10;
    }
    else//sec and min
    {
      int b = (n & B01110000) >> 4;   //bits 6,5,4
      TimeDate[i] = a + b * 10;
    }
  }
  //----------------------------------------------------------------------------------
  // For alarming
  //----------------------------------------------------------------------------------
  RTC_MON = TimeDate[5];
  RTC_DAY = TimeDate[4];
  RTC_YR = TimeDate[6];
  RTC_SEC = TimeDate[0];
  RTC_HR = TimeDate[2];
  // Update ONLY Minutes every Minute
  if (RTC_MIN != TimeDate[1] || background != background_prev) // only update display at every minute change.
  {
    background_prev = background;
    RTC_MIN = TimeDate[1];
    UPDATE_LCD();
  }
}

//----------------------------------------------------------------------------------
// Update LCD
//----------------------------------------------------------------------------------
void UPDATE_LCD()
  {
    if (background == 1)
    {
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x01, RTC_MIN);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x00, RTC_HR);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x02, HR_ALARM);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x03, MIN_ALARM);
      //RTC 1=AM, 2=PM
      if (ap == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x00, 1);} // LCD PM=0, AM=1
      if (ap == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x00, 0);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x04, 1);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x04, 0);} // LCD PM=0, AM=1
      genie.WriteObject(GENIE_OBJ_FORM, 0, 1); // change startup screen (#,1 #=form#)
      return;
    }
    if (background == 2)
    {
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x05, RTC_MIN);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x04, RTC_HR);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x07, HR_ALARM);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x06, MIN_ALARM);
      //RTC 1=AM, 2=PM
      if (ap == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x01, 1);} // LCD PM=0, AM=1
      if (ap == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x01, 0);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x05, 1);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x05, 0);} // LCD PM=0, AM=1
      genie.WriteObject(GENIE_OBJ_FORM, 1, 1); // change startup screen (#,1 #=form#)
      return;
    }
    if (background == 3)
    {
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x09, RTC_MIN);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x08, RTC_HR);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x0B, HR_ALARM);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x0A, MIN_ALARM);
      //RTC 1=AM, 2=PM
      if (ap == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x02, 1);} // LCD PM=0, AM=1
      if (ap == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x02, 0);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x06, 1);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x06, 0);} // LCD PM=0, AM=1
      genie.WriteObject(GENIE_OBJ_FORM, 2, 1); // change startup screen (#,1 #=form#)
      return;
    }
    if (background == 4)
    {
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x0D, RTC_MIN);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x0C, RTC_HR);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x0F, HR_ALARM);
      genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0x0E, MIN_ALARM);
      //RTC 1=AM, 2=PM
      if (ap == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x03, 1);} // LCD PM=0, AM=1
      if (ap == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x03, 0);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 1) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x07, 1);} // LCD PM=0, AM=1
      if (AMPM_ALARM == 2) {genie.WriteObject(GENIE_OBJ_STRINGS, 0x07, 0);} // LCD PM=0, AM=1
      genie.WriteObject(GENIE_OBJ_FORM, 3, 1); // change startup screen (#,1 #=form#)
      return;
    }
  }

// ------------------------------------------------------------------------------
// Enable Wake-Up Alarm
// ------------------------------------------------------------------------------
void Enable_Wakeup_Alarm()
{
  Set_WU_Alarm = 1;               //Set wake-up alarm = ON
  setAlarmPB_release = 0;
  LCD_CLR = 0;
  Snooze_PB = 0;
  SilenceAlarm();                 //Clear alarm flag on RTC
  UPDATE_LCD();
  genie.WriteObject(GENIE_OBJ_LED, 0x00, 1);
  genie.WriteObject(GENIE_OBJ_LED, 0x01, 1);
  genie.WriteObject(GENIE_OBJ_LED, 0x02, 1);
  genie.WriteObject(GENIE_OBJ_LED, 0x03, 1);
 }
 
// ------------------------------------------------------------------------------
// Disable Wake-Up Alarm
// ------------------------------------------------------------------------------
void Disable_Wakeup_Alarm()
{
  genie.WriteObject(GENIE_OBJ_LED, 0x00, 0);
  genie.WriteObject(GENIE_OBJ_LED, 0x01, 0);
  genie.WriteObject(GENIE_OBJ_LED, 0x02, 0);
  genie.WriteObject(GENIE_OBJ_LED, 0x03, 0);
  UPDATE_LCD();
  digitalWrite(snoozepbled, 0);      //turn off pb led.
  WAKE_UP_JACK = 0;
  Set_WU_Alarm = 0;
  Snooze_PB = 0;
  alarm_flag = 0;
  Snooze_PB_PRESSED = 0;
  Snooze_HR = HR_ALARM;
  Snooze_MIN = MIN_ALARM;
  HR_ALARM1 = 0;
  setAlarmPB_release = 0;
  pmp3f = 4;                         //Stop Playing mp3 alarm track.
  SilenceAlarm();                    //Clear alarm flag on RTC.
  SetAlarmTime(HR_ALARM, MIN_ALARM, AMPM_ALARM, alarm_track, 0);
}

// ------------------------------------------------------------------------------
// myGenieEventHandler
// ------------------------------------------------------------------------------
void myGenieEventHandler(void)
  {
  genieFrame Event;
  genie.DequeueEvent(&Event);
  //If the cmd received is from a Reported Event (Events triggered from the Events tab of Workshop4 objects)
  if (Event.reportObject.cmd == GENIE_REPORT_EVENT)
    {

    }

  //If the cmd received is from a Reported Object, which occurs if a Read Object (genie.ReadOject) is requested in the main code, reply processed here.
  if (Event.reportObject.cmd == GENIE_REPORT_OBJ)
    {
    
    }
  }
  //This can be expanded as more objects are added that need to be captured
  //Event.reportObject.cmd is used to determine the command of that event, such as an reported event
  //Event.reportObject.object is used to determine the object type, such as a Slider
  //Event.reportObject.index is used to determine the index of the object, such as Slider0
  //genie.GetEventData(&Event) us used to save the data from the Event, into a variable.
// ------------------------------------------------------------------------------
// PROGRAM END
// ------------------------------------------------------------------------------

aClock PC App

VBScript
Install program. (VB6)
No preview (download only).

Credits

Abe-Z

Abe-Z

2 projects • 1 follower
Electrical Engineer.
Contact

Comments

Add projectSign up / Login