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

Revision:
0:62a6f55722d9
Child:
1:8a7f4f79f84d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jan 21 12:35:29 2014 +0000
@@ -0,0 +1,575 @@
+ /*
+ * @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
+//  - rottary 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:
+//  - the sleeptimer isn't integrated already
+//  - a real time clock would be nice
+//  - a speaker or beeper directly connected to the mbed
+//----------------------------------------------------------------
+*/
+
+#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_20.h"
+#include "MyPhone_40.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);
+DigitalIn wheelpush(p18);
+DigitalOut led1(LED1), led2(LED2), relay(p15), enbackligth(p19);
+
+int main()
+{
+    //general init
+    menu=1;
+    menuDisp=1;
+    alarmon=0;
+    alarmset2=0;
+    sleeptimer=30;
+
+    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!");
+    wait(2);
+    clearmenu();
+
+    /*
+    //print all chars
+    display.ClearScreen();
+    int x=0,y=0;
+    for (int i=0x20;i<0xff;i++){
+        display.Putchar(y,x,i);
+        x=x+8;
+        if (x>120){
+            x=0;
+            y++;
+        }
+    }
+    while(1){}
+    */                    
+//mainloop
+//---------------------------------------------------------------
+    while (1) {
+        //read time
+        seconds = time(NULL);
+
+        led1=relay;
+
+        //ckeck if button pressed or wheel turned
+        checkbutton();
+        //menu=wheel.getPulses();
+        if (wheel.getPulses()>1){
+            wheel.reset();
+            menu++;
+            if (menu>7)
+                menu=0;
+        }
+        if (wheel.getPulses()<1){
+            wheel.reset();
+            if (menu==0)
+                menu=7;
+            else
+                menu--;
+        }        
+        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;
+                //menuold=menu;
+                //blstateold=blstate;
+            }
+        }
+        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;
+                //menuold=menu;
+                //blstateold=blstate;
+            }
+        }
+
+        //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.SelectFont(MyPhone_40,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;
+                    //    readchar=0;
+                }
+                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) {
+                    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");
+    //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(){
+    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()>1){
+            if (sleeptimer<10080)
+                sleeptimer+=5;
+        }
+        else if (wheel.getPulses()<1){
+            if (sleeptimer>5)
+                sleeptimer-=5;
+        }
+        if (wheel.getPulses()!=1)
+            wheel.reset();
+                    
+        if (wheelpushed) {
+            change_sleeptimer=false;
+            wheelpushed=false;
+            wheel.reset();
+        }
+    }
+}
+//------------------------------------------
+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()>1)
+            wheelturned='r';
+        else if (wheel.getPulses()<1)
+            wheelturned='l';
+        if (wheel.getPulses()==1)
+            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()>1)
+            wheelturned='r';
+        else if (wheel.getPulses()<1)
+            wheelturned='l';
+        if (wheel.getPulses()==1)
+            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()>1)
+            wheelturned='r';
+        else if (wheel.getPulses()<1)
+            wheelturned='l';
+        if (wheel.getPulses()==1)
+            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 backlight (bool onoff)
+{
+    led2=onoff;
+    enbackligth=onoff;
+}
+//------------------------------------------
+void checkbutton()
+{
+    wheelpushed=false;
+    wheelpushedlong=false;
+    if (!wheelpush) {
+        temp=0;
+        while(!wheelpush) {
+            wait(0.01);
+            temp++;
+        }
+        if (temp>150)
+            wheelpushedlong=true;
+        else
+            wheelpushed=true;
+    }
+}
\ No newline at end of file