Internet alarm clock

Dependencies:   EthernetNetIf NTPClient_NetServices mbed

main.cpp

Committer:
TyPatrick
Date:
2010-10-07
Revision:
0:df4b49a4be1a

File content as of revision 0:df4b49a4be1a:

#include "main.h"

/*******************************************************************
 * Print_lcd
 *
 * This function clears the LCD, then either prints 1. the alarm time
 * or 2. the current time and alarm clock menu state.
 ******************************************************************/
void print_lcd()
{
    lcd.cls();
    /* Menu options 2 and above deal with the alarm */
    if (menu > 1)
        print_time(ahour, amin);
    else
        print_time(cTime->tm_hour, cTime->tm_min);
    print_menu();
}

/******************************************************************
 * Print_time
 *
 * This function takes an hour(in 24hr time) and a minute and
 * prints the correct format to the lcd.
 *****************************************************************/
void print_time(int hour, int minute)
{
    /* Variable tmphr is 24 hour time adjusted for timezone */
    int tmphr = hour + timezone;
    while (tmphr < 0)
        tmphr += 24;
    tmphr %= 24;
    
    /* Variable printhr is 12 hour time for printing */
    int printhr = tmphr % 12;
    if (printhr == 0)
        printhr += 12;
    lcd.printf("%2d:%02d ", printhr, minute);
    
    /* tmphr allows for checking of AM/PM */
    if ((tmphr > 11) && (tmphr < 24))
        lcd.printf("PM\n");
    else
        lcd.printf("AM\n");
}    

/*******************************************************************
 * Print_menu
 *
 * This function prints the menu state of the alarm clock to the LCD. 
 * The menu options are 1. Viewing current time 2.  Setting Timezone
 * 3. Setting alarm hour 4. Setting alarm minute 5. Toggling alarm
 ******************************************************************/
void print_menu()
{
    switch (menu){
        case 0:
            break;
        case 1: 
            lcd.printf("TZ is (UTC) %+d\n", timezone);  
            break;
        case 2: 
            lcd.printf("Set Alarm Hour\n");
            break;
        case 3: 
            lcd.printf("Set Alarm Min\n");
            break;
        case 4: 
            lcd.printf("Alarm is ");
            if (alarmstate == false)
                lcd.printf("Off\n");
            else
                lcd.printf("On\n");
            break;
        default:
            lcd.printf("Invalid menu %d\n", menu);
            break;
    }
}

/******************************************************************
 * Change_menu
 *
 * This function uses a dedicated pushbutton that changes the menu. 
 * The state variable, menu, gives the user the ability to cycle 
 * through the 5 alarm clock menus.
 *****************************************************************/
void change_menu()
{
    alarm_snooze();
    menu = (menu + 1) % 5;
    print_lcd();
}

/******************************************************************
 * Push_plus
 *
 * This function  uses a dedicated pushbutton to only increment or
 * "Add" the value of variables of an alarm clock i.e. minute, hour,
 * time zone
 *****************************************************************/
void push_plus()
{
    alarm_snooze();
    button_press(1);
}

/******************************************************************
 * Push_minus
 *
 * This function  uses a dedicated pushbutton to only decrement 
 * or "Subtract" the value of variables of an alarm clock
 * i.e. minute, hour, time zone
 *****************************************************************/
void push_minus()
{
    alarm_snooze();
    button_press(-1);
}

/******************************************************************
 * Button_press
 *
 * This function performs an action based on which menu item is 
 * currently selected. It is called whenever the "Add" or 
 * "Subtract" button is pressed.
 *****************************************************************/
void button_press(int input)
{
    switch (menu)
    {
        case 0: 
            break;
        case 1:
            timezone += 12;      
            timezone += input;
            while (timezone < 0)
                timezone += 24;
            timezone %= 24;
            timezone -= 12;
            break;
        case 2:
            ahour += input;
            while (ahour < 0)
                ahour += 24;
            ahour %= 24;
            break;
        case 3: 
            amin += input;                  
            while (amin < 0)
                amin += 60;
            amin %= 60;
            break;
        case 4: 
            alarmstate = !alarmstate;       // Turn alarm on/off
            break;
        default:
            lcd.printf("Invalid state %d\n", menu);
            break;
    }
    print_lcd();
}

/******************************************************************
 * Alarm_ring
 *
 * This function rings the alarm by flashing the leds
 *****************************************************************/
 void alarm_ring()
 {
    if (led == 0x0F)
        led = 0;
    else
        led = (led << 1) | 1;
 }
 
/******************************************************************
 * Alarm_snooze
 *
 * This function turns off the alarm
 *****************************************************************/
void alarm_snooze()
{
    if (ringflag == true) {
        ringflag = false;
        snooze = true;
        ring.detach();
        led = 0;
    }
}

/******************************************************************
 * Alarm_check
 *
 * This function compares the alarm time vs the current time. Once 
 * alarm time and real time match it begins ringing the alarm. 
 * Once the times differ then it turns off the alarm.
 *****************************************************************/
void alarm_check()
{
    if ((cTime->tm_min == amin) && (cTime->tm_hour == ahour)) {
        if ((alarmstate == true) && (ringflag == false) && (snooze == false)) { 
            ringflag = true;
            ring.attach(&alarm_ring, .5); // Set up a Ticker for the alarm,
                             // calls alarm_ring every .5 seconds until stopped
        }
    }
    else {
        alarm_snooze();
        snooze = false;
    }
}

int main() {

    /* Set up Ethernet */
    lcd.cls();
    lcd.printf("Setting up Eth\n");
    EthernetErr ethErr = eth.setup();
    if (ethErr) {
        lcd.cls();
        lcd.printf("Error with Eth\nNum: %d", ethErr);
        return -1;
    }
    
    
    /* Set up NTP */
    lcd.printf("Setting up NTP\n");
    Host server(IpAddr(), 123, "0.uk.pool.ntp.org");
    ntp.setTime(server);
    
    /* Initialize all the interrupts for each of the pushbuttons */
    statechange.rise(&change_menu);
    plus.rise(&push_plus);
    minus.rise(&push_minus);
    
    /* Temporary variables for control loop */
    time_t rtc_time = time(NULL);
    int minute = -1;
    
    /* Initialize alarm time */
    ahour = 0;
    amin = 0;

    /* Main control loop */
    while(1)
    {
        /* Update current time */
        rtc_time = time(NULL);
        cTime = localtime(&rtc_time);
        
        /* Only redraw the lcd display if anything changes */
        if (cTime->tm_min != minute) {
            minute = cTime->tm_min;
            print_lcd();
            
            /* Update time from NTP server if it's midnight UTC */
            if ((cTime->tm_min == 0) && (cTime->tm_hour == 0)) {
                Host server(IpAddr(), 123, "0.north-america.pool.ntp.org");
                ntp.setTime(server);
            }
        }
        
        /* Check to see if the alarm should be started/stopped */
        alarm_check();
    }
    return 0;
}