alarmclock with 2 alarm times, 128x64 LCD with KS0108, displays time / time&date / a menu to change time & alarms, rotary encoder with push button, relay which switsches on a hi-fi system or something else, a 1F- Cap as a backup supply

Dependencies:   KS0108 QEI mbed

Alarmclock

features:

  • alarmclock with 2 alarm times
  • 128x64 LCD with KS0108
  • displays time / time&date / a menu to change time & alarms
  • sleeptimer, relay is switched of when timer runs out
  • rotary encoder with push button
  • relay which switsches on a hi-fi system or something else
  • a 1F- Cap as a backup supply

todo/ desired improvements/ known issues:

  • a more precise real time clock would be nice
  • a speaker or beeper directly connected to the mbed
  • there is a bug where the big font is not displayed correctly

Schematic:

/media/uploads/gaebu/alarmclock_mbed_128x64.pdf

main.cpp

Committer:
gaebu
Date:
2016-01-05
Revision:
2:fbf734bc04de
Parent:
1:8a7f4f79f84d

File content as of revision 2:fbf734bc04de:

 /*
 * @author gaebu
 *
 * @section LICENSE
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @section DESCRIPTION
 
//----------------------------------------------------------------
// Alarmclock
// -----------
// features:
//  - alarmclock with 2 alarm times
//  - 128x64 LCD with KS0108
//  - displays time / time&date / a menu to change time & alarms
//  - sleeptimer, relay is switched of when timer runs out
//  - rottary encoder with push button
//  - relay which switsches on a hi-fi system or something else
//  - a 1F- Cap as a backup supply
//  - the relay is manualy switched on/off by pressing the button
//    longer than 2s
//----------------------------------------------------------------
// todo/ desired improvements:
//  - a more precise real time clock would be nice
//  - a speaker or beeper directly connected to the mbed
//  - there is a bug in displaying fonts
//----------------------------------------------------------------
*/

#include "mbed.h"
#include "KS0108.h"
#include "QEI.h"
//#include "math.h"
//#include "Arial12.h"
//#include "Arial14.h"
//#include "arial_bold_14.h"
//#include "Comic24.h"
//#include "SystemFont5x7.h"
//#include "vivaldi16.h"
//#include "MyPhone_40.h"
//#include "Buxton32.h"
#include "Pointy48.h"
//#include "Buxton48B.h"
//#include "GoodDog48B.h"
//#include "SnapITC32.h"
#include "alarmclock.h"
//#include <string>

//             _RST,_DI, _RW, _E, _CS2, _CS1,DB0, DB1, DB2, DB3, DB4, DB5, DB6, DB7)
KS0108 display(p13, p12, p14, p11, p30, p29, p21, p22, p23, p24, p25, p26, p27, p28);

QEI wheel (p17, p16, NC, 18, QEI::X2_ENCODING);
DigitalIn wheelpush(p18);
DigitalOut led1(LED1), led2(LED2), relay(p15), enbackligth(p19), beeper(p20);

int main()
{
    //general init
    beeper=0;
    menu=1;
    menuDisp=1;
    alarmon=0;
    alarmset2=0;
    sleeptimer=0;
    wheelpushchanged=1;

    alarm.tm_sec = 00;    // 0-59
    alarm.tm_min = 00;    // 0-59
    alarm.tm_hour = 6;   // 0-23
    alarm2.tm_sec = 00;    // 0-59
    alarm2.tm_min = 00;    // 0-59
    alarm2.tm_hour = 5;   // 0-23

    //display title & frame
    display.ClearScreen();
    display.PutString(0,30,"alarmclock");
    display.EmptyRectangle(0,0,127,63,BLACK);
    display.HLine(0,127,7,BLACK);


    //display.GotoXY(10,16);
    //display.SelectFont(Comic24,BLACK,ReadData);
    //display.PrintString("by_gaebu!");
    display.PutString(10,16,"by_gaebu!");
    display.PutString(30,26,"V1.2");
    wait(2);
    clearmenu();
    wheel.reset();    

//mainloop
//---------------------------------------------------------------
    while (1) {
        //read time
        seconds = time(NULL);

        led1=relay;

        //ckeck if button pressed or wheel turned
        checkbutton();
        pulses=wheel.getPulses();
        //display.PrintInteger(pulses,0,0);
        if (pulses!=0){
            blTimeout.attach(&blTimeout_tick, 5.0);

            //blstate=1;
            //backlight(blstate);
            backlight(1);
        
            if (pulses>0){              
                menu++;
                if (menu>7)
                    menu=0;
            }
            if (pulses<0){
                if (menu==0)
                    menu=7;
                else
                    menu--;
            }     
            wheel.reset();
            display.PrintInteger(menu,0,100);
        }
        
        
        //ring the alarm?
        if(alarmon | alarmon2) {
            relay=1;
            //blstate=!blstate;
            backlight(1);//blstate);
            if(menuold!=menu) {        //ring until any button pressed
                alarmon=0;
                alarmon2=0;
                relay=0;
                backlight(blstate);//old);
            }
        }

        //check alarm
        if(alarmset & !alarmon) {
            newtime = localtime(&seconds);
            if(alarm.tm_min==newtime->tm_min & alarm.tm_hour==newtime->tm_hour & alarm.tm_sec==newtime->tm_sec) {
                alarmon=1;
            }
        }
        if(alarmset2 & !alarmon2) {
            newtime = localtime(&seconds);
            if(alarm2.tm_min==newtime->tm_min & alarm2.tm_hour==newtime->tm_hour & alarm2.tm_sec==newtime->tm_sec) {
                alarmon2=1;
            }
        }

        //display menu
        //---------------------------------------------------------------                     
        if (menu!=menuold) {
            menuDisp=menu;
            if (menu<2 | (menu==2&menuold==1) | (menu==7&menuold==0)){
                clearmenu();               
            }
            menuold=menu;
        }
        else if (menu>1 & !(wheelpushed|wheelpushedlong))    //don't redraw menu if no time is diplayed or no input made
            menuDisp=99;
        else
            menuDisp=menu;
            
        switch (menuDisp) {
                //--- Menu 1 --- date&time
            case 0:
                strftime(x_day, 20, "%a, %d %b %Y\n", localtime(&seconds));
                display.PutString(3,20,x_day);

                strftime(x_time, 16, "%X\n", localtime(&seconds));
                display.PutString(4,30,x_time);

                if (wheelpushed) {    //switch backlight if button pressed
                    blstate=!blstate;
                    backlight(blstate);
                }
                if (wheelpushedlong) {    //switch relay if button pressed long
                    relay=!relay;
                }
                break;

                //--- Menu 2 --- time big
            case 1:
                strftime(x_time, 16, "%H:%M  .", localtime(&seconds));
//                display.GotoXY(32,24);
                display.GotoXY(8,16);       //hint: position must be a product of 8
                display.SelectFont(Pointy48,BLACK,ReadData);
                //display.SelectFont(Comic24,BLACK,ReadData);
                display.PrintString(x_time);

                if (wheelpushed) {    //switch backlight if button pressed
                    blstate=!blstate;
                    backlight(blstate);
                }
                if (wheelpushedlong) {    //switch relay if button pressed long
                    relay=!relay;
                }
                break;

                //--- Menu 3 --- display menu, alarm1 on/off
            case 2:
                if (wheelpushed) {
                    alarmset=!alarmset;
                }
                printmenu(2);
                break;
                //--- Menu 4 --- display menu, alarm2 on/off
            case 3:
                if (wheelpushed) {
                    alarmset2=!alarmset2;
                }
                printmenu(3);
                break;
                //--- Menu 5 --- set alarm 1
            case 4:
                if (wheelpushed) {
                    setalarm(1);
                }
                printmenu(4);
                break;
                //--- Menu 6 --- set alarm 2
            case 5:
                if (wheelpushed) {
                    setalarm(2);
                }
                printmenu(5);
                break;
                //--- Menu 7 --- set time&date
            case 6:
                if (wheelpushed) {
                    settimedate();
                }
                printmenu(6);
                break;
                
                //--- Menu 8 --- sleep timer
            case 7:
                if (wheelpushed) {
                    if (sleeptimer>0)   //if sleeptimer already set then reset
                        sleeptimer=0;
                    else
                        setsleeptimer();
                }
                printmenu(7);
                break;        
            case 99:
                //do nothing
                break;
            default:
                display.PutString(0,100,"error");
                //exit(1);
        }
    }
}
//functions
//------------------------------------------
void clearmenu()
{
    //display.FullRectangle(1,9,126,62,WHITE);

    //display title & frame
    display.ClearScreen();
    display.PutString(0,30,"alarmclock");
    display.EmptyRectangle(0,0,127,63,BLACK);
    display.HLine(0,127,7,BLACK);
}
//------------------------------------------
void printmenu(int selectedline)
{

    //zeile1

    //zeile2
    display.PutString(2,20,"Alarm 1: ");
    if (alarmset)
        display.PutString(2,80,"on    ");
    else
        display.PutString(2,80,"off   ");
    //zeile3
    display.PutString(3,20,"Alarm 2: ");
    if (alarmset2)
        display.PutString(3,80,"on   ");
    else
        display.PutString(3,80,"off   ");
    //zeile4
    display.PutString(4,20,"set Alarm 1");
    strftime(alarmtime, 6, "%H:%M\n", &alarm);
    display.PutString(4,85,alarmtime);
    //zeile5
    display.PutString(5,20,"set Alarm 2");
    strftime(alarmtime, 6, "%H:%M\n", &alarm2);
    display.PutString(5,85,alarmtime);
    //zeile6
    display.PutString(6,20,"set Time/ Date");
    //zeile7
    display.PutString(7,20,"sleep timer");
//    if (sleeptimerstart) {
    if (sleeptimer>0) {
        display.PrintInteger(sleeptimer,7,85);
//        display.PutString(7,40,sleeptime_set);
    }        
    //select line
    for (i=2;i<8;i++)
        display.PutString(i,2,"  ");
    display.PutString(selectedline,2,"~~");
    //frame
    display.EmptyRectangle(0,0,127,63,BLACK);
}
//------------------------------------------
void setsleeptimer(){
    sleeptimer=30;
    clearmenu();
    wheel.reset();
    change_sleeptimer=true;
    display.PutString(3,30,"set sleeptimer");
    display.PutString(5,30,"min:");
    while(change_sleeptimer){
        if (sleeptimer<10)
            display.PutString(5,65," ");
        if (sleeptimer<100)
            display.PutString(5,70," ");
        if (sleeptimer<1000)
            display.PutString(5,75," ");
        if (sleeptimer<10000)
            display.PutString(5,80," ");
        display.PrintInteger(sleeptimer,5,60);

        checkbutton();       
        if (wheel.getPulses()>0){
            if (sleeptimer<1080)
                sleeptimer+=5;
        }
        else if (wheel.getPulses()<0){
            if (sleeptimer>5)
                sleeptimer-=5;
        }
        if (wheel.getPulses()!=0)
            wheel.reset();
                    
        if (wheelpushed) {
            change_sleeptimer=false;
            wheelpushed=false;
            wheel.reset();
            ticker.attach(&ticker_tick, 60.0);
            relay=1;
            display.ClearScreen();
        }
    }
} 
//------------------------------------------
void setalarm(char alnb)
{
    clearmenu();
    wheel.reset();
    change_alarm_hour=1;
    display.PutString(4,30,"--   ");
    if (alnb == 1)
        al_to_change=alarm;
    else
        al_to_change=alarm2;
    while (change_alarm_hour) {
        strftime(alarmtime, 6, "%H:%M\n", &al_to_change);
        display.PutString(3,30,alarmtime);
        checkbutton();
        if (wheel.getPulses()>0)
            wheelturned='r';
        else if (wheel.getPulses()<0)
            wheelturned='l';
        if (wheel.getPulses()==0)
            wheelturned=0;
        else
            wheel.reset();

        if (wheelturned=='r') {
            al_to_change.tm_hour++;
            if (al_to_change.tm_hour>23)
                al_to_change.tm_hour=0;
        }
        if (wheelturned=='l') {
            al_to_change.tm_hour--;
            if (al_to_change.tm_hour<0)
                al_to_change.tm_hour=23;
        }
        if (wheelpushed) {
            change_alarm_hour=0;
            change_alarm_min=1;
            display.PutString(4,30,"   --");
        }
    }
    while (change_alarm_min) {
        strftime(alarmtime, 6, "%H:%M\n", &al_to_change);
        display.PutString(3,30,alarmtime);

        checkbutton();
        if (wheel.getPulses()>0)
            wheelturned='r';
        else if (wheel.getPulses()<0)
            wheelturned='l';
        if (wheel.getPulses()==0)
            wheelturned=0;
        else
            wheel.reset();
        if (wheelturned=='r') {
            al_to_change.tm_min++;
            if (al_to_change.tm_min>59)
                al_to_change.tm_min=0;
        }
        if (wheelturned=='l') {
            al_to_change.tm_min--;
            if (al_to_change.tm_min<0)
                al_to_change.tm_min=59;
        }
        if (wheelpushed) {
            change_alarm_min=0;
            if (alnb == 1)
                alarm=al_to_change;
            else
                alarm2=al_to_change;
            wheelturned=0;
            wheelpushed=false;
            wheel.reset();
        }
    }
}
//------------------------------------------
void settimedate()
{
    clearmenu();
    wheel.reset();
    seconds = time(NULL);
    newtime = localtime(&seconds);
    set_td_menu=1;
    wheelturned=1;
    //menuold=0;
    display.PutString(4,30,"--   ");
    if (newtime->tm_year==70)
        newtime->tm_year=113;

    while(set_td_menu>0) {
        if(wheelturned>0) {        //update display if changed
            strftime(x_day, 20, "%d.%m.%Y\n", newtime);
            display.PutString(5,30,x_day);

            char x_time[16];
            strftime(x_time, 16, "%H:%M\n", newtime);
            display.PutString(3,30,x_time);
        }
        checkbutton();
        //menu=wheel.getPulses();
        //display.PrintInteger(menu,0,100);
        //if (menu>menuold)
        if (wheel.getPulses()>0)
            wheelturned='r';
        else if (wheel.getPulses()<0)
            wheelturned='l';
        if (wheel.getPulses()==0)
            wheelturned=0;
        else
            wheel.reset();
        //menuold=menu;

        switch(set_td_menu) {
            case 0:
                break;      // Invalid entry
            case 1:             //set hour
                if (wheelturned=='r') {
                    newtime->tm_hour++;
                    if (newtime->tm_hour>23)
                        newtime->tm_hour=0;
                }
                if (wheelturned=='l') {
                    newtime->tm_hour--;
                    if (newtime->tm_hour<0)
                        newtime->tm_hour=23;
                }
                if (wheelpushed) {
                    set_td_menu++;
                    display.PutString(4,30,"   --");
                }
                break;
            case 2:             //set min
                if (wheelturned=='r') {
                    newtime->tm_min++;
                    if (newtime->tm_min>59)
                        newtime->tm_min=0;
                }
                if (wheelturned=='l') {
                    newtime->tm_min--;
                    if (newtime->tm_min<0)
                        newtime->tm_min=59;
                }
                if (wheelpushed) {
                    set_td_menu++;
                    display.PutString(4,30,"     ");
                    display.PutString(6,30,"--        ");
                }
                break;
            case 3:             //set day
                if (wheelturned=='r') {
                    newtime->tm_mday++;
                    if (newtime->tm_mday>31)
                        newtime->tm_mday=1;
                }
                if (wheelturned=='l') {
                    newtime->tm_mday--;
                    if (newtime->tm_mday<1)
                        newtime->tm_mday=31;
                }
                if (wheelpushed) {
                    set_td_menu++;
                    display.PutString(6,30,"   --     ");
                }
                break;
            case 4:             //set month
                if (wheelturned=='r') {
                    newtime->tm_mon++;
                    if (newtime->tm_mon>11)
                        newtime->tm_mon=0;
                }
                if (wheelturned=='l') {
                    newtime->tm_mon--;
                    if (newtime->tm_mon<0)
                        newtime->tm_mon=11;
                }
                if (wheelpushed) {
                    set_td_menu++;
                    display.PutString(6,30,"      ----");
                }
                break;
            case 5:             //set month
                if (wheelturned=='r') {
                    newtime->tm_year++;
                    if (newtime->tm_year>200)
                        newtime->tm_year=100;
                }
                if (wheelturned=='l') {
                    newtime->tm_year--;
                    if (newtime->tm_year<100)
                        newtime->tm_year=200;
                }
                if (wheelpushed) {
                    set_td_menu=0;
                    display.PutString(6,30,"          ");
                    // convert to timestamp and set
                    set_time(mktime(newtime));
                    wheelturned=0;
                    wheelpushed=false;
                    //menuDisp=0;
                    //menuold=0;
                    wheel.reset();
                }
                break;
            default:
                display.PutString(0,100,"error");
                exit(1);
        }
    }
}
//------------------------------------------
void ticker_tick() //called every 60s when sleeptimer set
{
    if (sleeptimer==0){
        relay=0;
        led1=0;
        blstate=0;
        ticker.detach();
    }
    else
        sleeptimer--;
}   
//------------------------------------------
void backlight (bool onoff)
{
    led2=onoff;
    enbackligth=onoff;
}
//------------------------------------------
void blTimeout_tick() //called after 5s when wheel is turned
{
    //cklight(blstate);
    //blticker.detach();
    led2=0;
    enbackligth=0;
}  
//------------------------------------------
void checkbutton()
{
    wheelpushed=false;
    wheelpushedlong=false;
        
    if (!wheelpush) {
        if (wheelpushchanged) {
            temp=0;
            while(!wheelpush & temp<=200) { //if pressed longer than 2s..
                wait(0.01);
                temp++;
            }
            if (temp>200)
                wheelpushedlong=true;
            else
                wheelpushed=true;
            wheelpushchanged=0;
        }    
    }
    else
        wheelpushchanged=1;
}