/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2003 Zakk Roberts * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ /***************************** * RELEASE NOTES ***** VERSION 4.00 ** New almost entirely bitmap based display. Scales to all resolutions. Combined Digital and LCD modes into one. Use Rockbox menu code for the menu. Removed count-down option. A couple new options. Source code reworked, improved, cleaned up. ***** VERSION 3.10 ** Drawing now scales for the display - still needs updated bitmaps for the binary and plain mode. The Time's Up logo could also be updated. ***** VERSION 3.00 ** New, simpler UI - every screen can be accessed from the new Main Menu. Huge code cleanup - many major functions rewritten and optimized, targeting scalability. Number of variables reduced majorly. New clock mode: Plain (simple, large text). ON now controls counter (press toggle/hold reset). Fancier credits roll. New logo. iRiver and iPod ports are working but not yet scaled to fit their LCDs. ***** VERSION 2.60 ** Fixed general settings typo, split up settings function, added cursor animations, and updated cursor look (rounded edges). ***** VERSION 2.51 ** "Show Counter" option is now saved to disk ***** VERSION 2.50 ** New general settings mode added, reworked options screen, cleaned up a few things and removed redundant code, faster load_settings(), fixed a help-screen bug (thanks to zeekoe) ***** VERSION 2.40 ** Cleaned and optimized code, removed unused code/bitmaps, credits screen updated, centered text all over, general settings added at ON+F3, new arrow bitmap for general settings and mode selector, bugfix: 12:00AM is no longer 00:00AM ***** VERSION 2.31 ** Fixed credits roll - now displays all names. Features improved animations. Also revised release notes. ***** VERSION 2.30 ** Tab indentation removed, and Counter screen added at ON+F2, with countdown options ***** VERSION 2.22 ** Fixed two bugs: Digital settings are now independent of LCD settings 12/24h "Analog" settings are now displayed correctly. ***** VERSION 2.21 ** -Changed the behaviour of F2 ***** VERSION 2.20 ** Few small bugs taken care of. New features: New binary mode, new mode selector, "counter", and redesigned help screen. ***** VERSION 2.10 ** New bug fixes, and some new features: an LCD imitation mode, and American and European date modes. ***** VERSION 2.00 ** Major update, lots of bugfixes and new features. Fullscreen mode introduced, modes have independent settings, credit roll added, options screen reworked, logo selector, and -much- cleaner code. ***** VERSION 1.0 ** Original release, featuring analog/digital modes and a few options. *****************************/ #include "plugin.h" #include "time.h" #include "checkbox.h" #include "xlcd.h" PLUGIN_HEADER /* External bitmap references */ extern const fb_data clock_digits[]; extern const fb_data clock_smalldigits[]; extern const fb_data clock_segments[]; extern const fb_data clock_smallsegments[]; extern const fb_data clock_logo[]; extern const fb_data clock_messages[]; extern const fb_data clock_timesup[]; /* Bitmap sizes/positions/deltas, per LCD size */ #if (LCD_WIDTH >= 320) && (LCD_HEIGHT >=240) && (LCD_DEPTH >= 16) /* iPod 5G */ #define DIGIT_WIDTH 50 #define DIGIT_HEIGHT 70 #define SMALLDIGIT_WIDTH 15 #define SMALLDIGIT_HEIGHT 21 #define SMALLSEG_WIDTH 15 #define SMALLSEG_HEIGHT 21 #define MESSAGE_HEIGHT 40 #define MESSAGE_WIDTH 320 #define LOGO_WIDTH 320 #define LOGO_HEIGHT 160 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) && (LCD_DEPTH >= 16) /* H300 */ #define DIGIT_WIDTH 35 #define DIGIT_HEIGHT 49 #define SMALLDIGIT_WIDTH 10 #define SMALLDIGIT_HEIGHT 14 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 14 #define MESSAGE_HEIGHT 27 #define MESSAGE_WIDTH 220 #define LOGO_WIDTH 220 #define LOGO_HEIGHT 110 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132) && (LCD_DEPTH >=16) /* Nano */ #define DIGIT_WIDTH 25 #define DIGIT_HEIGHT 35 #define SMALLDIGIT_WIDTH 10 #define SMALLDIGIT_HEIGHT 14 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 14 #define MESSAGE_HEIGHT 22 #define MESSAGE_WIDTH 176 #define LOGO_WIDTH 176 #define LOGO_HEIGHT 88 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >=16) /* iAudio, H10 */ #define DIGIT_WIDTH 25 #define DIGIT_HEIGHT 35 #define SMALLDIGIT_WIDTH 10 #define SMALLDIGIT_HEIGHT 14 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 14 #define MESSAGE_HEIGHT 20 #define MESSAGE_WIDTH 160 #define LOGO_WIDTH 160 #define LOGO_HEIGHT 80 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >=16) /* H10 5/6GB */ #define DIGIT_WIDTH 20 #define DIGIT_HEIGHT 28 #define SMALLDIGIT_WIDTH 10 #define SMALLDIGIT_HEIGHT 14 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 14 #define MESSAGE_HEIGHT 16 #define MESSAGE_WIDTH 128 #define LOGO_WIDTH 128 #define LOGO_HEIGHT 64 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >=2) /* iPod 3G, 4G */ #define DIGIT_WIDTH 25 #define DIGIT_HEIGHT 35 #define SMALLDIGIT_WIDTH 10 #define SMALLDIGIT_HEIGHT 14 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 14 #define MESSAGE_HEIGHT 20 #define MESSAGE_WIDTH 160 #define LOGO_WIDTH 160 #define LOGO_HEIGHT 80 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) && (LCD_DEPTH >=2) /* iPod mini */ #define DIGIT_WIDTH 23 #define DIGIT_HEIGHT 32 #define SMALLDIGIT_WIDTH 10 #define SMALLDIGIT_HEIGHT 14 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 14 #define MESSAGE_HEIGHT 17 #define MESSAGE_WIDTH 138 #define LOGO_WIDTH 138 #define LOGO_HEIGHT 69 #define LCD_OFFSET 1.5 #define HAND_W 3 #elif (LCD_WIDTH >= 112) && (LCD_HEIGHT >= 64) && (LCD_DEPTH >= 1) /* Archos */ #define DIGIT_WIDTH 16 #define DIGIT_HEIGHT 20 #define SMALLDIGIT_WIDTH 8 #define SMALLDIGIT_HEIGHT 10 #define SMALLSEG_WIDTH 10 #define SMALLSEG_HEIGHT 12 #define MESSAGE_HEIGHT 14 #define MESSAGE_WIDTH 112 #define LOGO_WIDTH 112 #define LOGO_HEIGHT 50 #define LCD_OFFSET 1 #define HAND_W 2 #endif /* Parts of larger bitmaps */ #define COLON 10 #define DOT_FILLED 11 #define DOT_EMPTY 12 #define ICON_PM 13 #define ICON_AM 14 #define SEGMENT_AM 11 #define SEGMENT_PM 12 #define SLASH 11 #define PERIOD 12 /* Message names/values */ #define MESSAGE_LOADING 0 #define MESSAGE_LOADED 1 #define MESSAGE_ERRLOAD 2 #define MESSAGE_SAVING 3 #define MESSAGE_SAVED 4 #define MESSAGE_ERRSAVE 5 /* Some macros to simplify drawing et al */ #define draw_digit( num, x, y )\ rb->lcd_bitmap_part( clock_digits, 0, num * DIGIT_HEIGHT, \ DIGIT_WIDTH, x, y, DIGIT_WIDTH, DIGIT_HEIGHT ) #define draw_smalldigit( num, x, y )\ rb->lcd_bitmap_part( clock_smalldigits, 0, num * SMALLDIGIT_HEIGHT, \ SMALLDIGIT_WIDTH, x, y, SMALLDIGIT_WIDTH, SMALLDIGIT_HEIGHT ) #define draw_segment( num, x, y )\ rb->lcd_bitmap_part( clock_segments, 0, num * DIGIT_HEIGHT, \ DIGIT_WIDTH, x, y, DIGIT_WIDTH, DIGIT_HEIGHT ) #define draw_smallsegment( num, x, y )\ rb->lcd_bitmap_part( clock_smallsegments, 0, num * SMALLSEG_HEIGHT, \ SMALLSEG_WIDTH, x, y, SMALLSEG_WIDTH, SMALLSEG_HEIGHT ) #define draw_message( msg, ypos )\ rb->lcd_bitmap_part( clock_messages, 0, msg*MESSAGE_HEIGHT, MESSAGE_WIDTH, \ 0, LCD_HEIGHT-(MESSAGE_HEIGHT*ypos), MESSAGE_WIDTH, MESSAGE_HEIGHT ) #define DIGIT_XOFS(x) (LCD_WIDTH-x*DIGIT_WIDTH)/2 #define DIGIT_YOFS(x) (LCD_HEIGHT-x*DIGIT_HEIGHT)/2 #define SMALLDIGIT_XOFS(x) (LCD_WIDTH-x*SMALLDIGIT_WIDTH)/2 #define SMALLDIGIT_YOFS(x) (LCD_HEIGHT-x*SMALLDIGIT_HEIGHT)/2 #define SMALLSEG_XOFS(x) (LCD_WIDTH-x*SMALLSEG_WIDTH)/2 #define SMALLSEG_YOFS(x) (LCD_HEIGHT-x*SMALLSEG_HEIGHT)/2 /* Keymaps */ #if (CONFIG_KEYPAD == RECORDER_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_PLAY #define ALT_MENU_BUTTON BUTTON_F1 #define EXIT_BUTTON BUTTON_OFF #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #elif (CONFIG_KEYPAD == ARCHOS_AV300_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_SELECT #define ALT_MENU_BUTTON BUTTON_F1 #define EXIT_BUTTON BUTTON_OFF #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_PLAY|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_PLAY|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_SELECT #define EXIT_BUTTON BUTTON_MENU #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #elif (CONFIG_KEYPAD == IRIVER_H300_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_SELECT #define EXIT_BUTTON BUTTON_OFF #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #define EXIT_RC_BUTTON BUTTON_RC_STOP #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_PLAY|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_PLAY|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_SELECT #define EXIT_BUTTON BUTTON_POWER #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #elif (CONFIG_KEYPAD == SANSA_E200_PAD) #define COUNTER_TOGGLE_BUTTON BUTTON_UP #define COUNTER_RESET_BUTTON BUTTON_DOWN #define MENU_BUTTON BUTTON_SELECT #define EXIT_BUTTON BUTTON_POWER #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #elif (CONFIG_KEYPAD == IRIVER_H10_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_PLAY|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_PLAY|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_REW #define EXIT_BUTTON BUTTON_POWER #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #elif (CONFIG_KEYPAD == GIGABEAT_PAD) #define COUNTER_TOGGLE_BUTTON (BUTTON_SELECT|BUTTON_REL) #define COUNTER_RESET_BUTTON (BUTTON_SELECT|BUTTON_REPEAT) #define MENU_BUTTON BUTTON_MENU #define EXIT_BUTTON BUTTON_A #define MODE_NEXT_BUTTON BUTTON_RIGHT #define MODE_PREV_BUTTON BUTTON_LEFT #endif /************ * Prototypes ***********/ void save_settings(bool interface); /******************** * Misc counter stuff *******************/ int start_tick = 0; int passed_time = 0; int counter = 0; int displayed_value = 0; int count_h, count_m, count_s; bool counting = false; /******************** * Everything else... *******************/ bool idle_poweroff = true; /* poweroff activated or not? */ bool done = false; /* used for most of the while loops */ bool exit_clock = false; /* when true, the main plugin loop will exit */ static struct plugin_api* rb; /*********************************************************************** * Used for hands to define lengths at a given time, analog + fullscreen **********************************************************************/ unsigned int xminute[61]; unsigned int yminute[61]; unsigned int yhour[61]; unsigned int xhour[61]; unsigned int xminute_full[61]; unsigned int yminute_full[61]; unsigned int xhour_full[61]; unsigned int yhour_full[61]; /* settings are saved to this location */ static const char default_filename[] = "/.rockbox/rocks/.clock_settings"; /********************************************************* * Some arrays/definitions for drawing settings/menu text. ********************************************************/ #define ANALOG 1 #define DIGITAL 2 #define FULLSCREEN 3 #define BINARY 4 #define PLAIN 5 #define CLOCK_MODES 5 #define analog_date 0 #define analog_secondhand 1 #define analog_time 2 #define digital_seconds 0 #define digital_date 1 #define digital_blinkcolon 2 #define digital_format 3 #define fullscreen_border 0 #define fullscreen_secondhand 1 #define binary_mode 0 #define plain_format 0 #define plain_seconds 1 #define plain_date 2 #define plain_blinkcolon 3 #define general_counter 0 #define general_savesetting 1 #define general_backlight 2 /* Menu structs (lists of menu items) */ static const struct menu_item main_menu_items[] = { { "View Clock", NULL }, { "Mode Selector", NULL }, { "Mode Settings", NULL }, { "General Settings", NULL }, { "Exit Plugin", NULL } }; static const struct menu_item mode_selector_items[] = { { "Analog", NULL }, { "Digital/LCD", NULL }, { "Full-screen", NULL }, { "Binary", NULL }, { "Plain", NULL } }; static const struct menu_item general_settings_items[] = { { "Reset Settings", NULL }, { "Save Settings Now", NULL }, { "Save On Exit", NULL }, { "Show Counter", NULL }, { "Backlight Settings", NULL }, { "Idle Poweroff (temporary)", NULL } }; static const struct menu_item analog_items[] = { { "Show Date", NULL }, { "Show Second Hand", NULL }, { "Show Time Readout", NULL } }; static const struct menu_item digital_items[] = { { "Show Seconds", NULL }, { "Show Date", NULL }, { "Blinking Colon", NULL }, { "Time Format", NULL } }; static const struct menu_item fullscreen_items[] = { { "Show Border", NULL }, { "Show Second Hand", NULL } }; static const struct menu_item binary_items[] = { { "Display Mode", NULL } }; static const struct menu_item plain_items[] = { { "Show Date", NULL }, { "Show Seconds", NULL }, { "Blinking Colon", NULL }, { "Time Format", NULL } }; /* Option structs (possible selections per each option) */ static const struct opt_items noyes_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items saving_options_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items show_counter_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items backlight_settings_text[3] = { { "Always Off", -1 }, { "Rockbox setting", -1 }, { "Always On", -1 } }; static const struct opt_items idle_poweroff_text[2] = { { "Disabled", -1 }, { "Enabled", -1 } }; static const struct opt_items counting_direction_text[2] = { {"Down", -1}, {"Up", -1} }; static const struct opt_items analog_date_text[3] = { { "No", -1 }, { "American format", -1 }, { "European format", -1 } }; static const struct opt_items analog_secondhand_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items analog_time_text[3] = { { "No", -1 }, { "24-hour Format", -1 }, { "12-hour Format", -1 } }; static const struct opt_items digital_seconds_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items digital_date_text[3] = { { "No", -1 }, { "American format", -1 }, { "European format", -1 } }; static const struct opt_items digital_blinkcolon_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items digital_format_text[2] = { { "24-hour Format", -1 }, { "12-hour Format", -1 } }; static const struct opt_items fullscreen_border_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items fullscreen_secondhand_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items binary_mode_text[2] = { { "Numbers", -1 }, { "Dots", -1 } }; static const struct opt_items plain_date_text[3] = { { "No", -1 }, { "American format", -1 }, { "European format", -1 } }; static const struct opt_items plain_seconds_text[3] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items plain_blinkcolon_text[2] = { { "No", -1 }, { "Yes", -1 } }; static const struct opt_items plain_format_text[3] = { { "24-hour Format", -1 }, { "12-hour Format", -1 } }; /***************************************** * All settings, saved to default_filename ****************************************/ struct saved_settings { int clock; /* clock mode */ int general[4]; /* general settings*/ int analog[3]; int digital[4]; int fullscreen[2]; int binary[1]; int plain[4]; } settings; /************************ * Setting default values ***********************/ void reset_settings(void) { settings.clock = 1; settings.general[general_counter] = 1; settings.general[general_savesetting] = 1; settings.general[general_backlight] = 2; settings.analog[analog_date] = 0; settings.analog[analog_secondhand] = true; settings.analog[analog_time] = false; settings.digital[digital_seconds] = 1; settings.digital[digital_date] = 1; settings.digital[digital_blinkcolon] = false; settings.digital[digital_format] = true; settings.fullscreen[fullscreen_border] = true; settings.fullscreen[fullscreen_secondhand] = true; settings.plain[plain_format] = true; settings.plain[plain_seconds] = true; settings.plain[plain_date] = 1; settings.plain[plain_blinkcolon] = false; } /************************************************ * Precalculated sine * 16384 (fixed point 18.14) ***********************************************/ static const short sin_table[91] = { 0, 285, 571, 857, 1142, 1427, 1712, 1996, 2280, 2563, 2845, 3126, 3406, 3685, 3963, 4240, 4516, 4790, 5062, 5334, 5603, 5871, 6137, 6401, 6663, 6924, 7182, 7438, 7691, 7943, 8191, 8438, 8682, 8923, 9161, 9397, 9630, 9860, 10086, 10310, 10531, 10748, 10963, 11173, 11381, 11585, 11785, 11982, 12175, 12365, 12550, 12732, 12910, 13084, 13254, 13420, 13582, 13740, 13894, 14043, 14188, 14329, 14466, 14598, 14725, 14848, 14967, 15081, 15190, 15295, 15395, 15491, 15582, 15668, 15749, 15825, 15897, 15964, 16025, 16082, 16135, 16182, 16224, 16261, 16294, 16321, 16344, 16361, 16374, 16381, 16384 }; /******************************* * Sine function (from plasma.c) ******************************/ static short sin(int val) { /* value should be between 0 and 360 degree for correct lookup*/ val%=360; if(val<0) val+=360; /* Speed improvement through successive lookup */ if (val < 181) { if (val < 91) return (short)sin_table[val]; /* phase 0-90 degree */ else return (short)sin_table[180-val]; /* phase 91-180 degree */ } else { if (val < 271) return -(short)sin_table[val-180]; /* phase 181-270 degree */ else return -(short)sin_table[360-val]; /* phase 270-359 degree */ } return 0; } /************************************************************** * Simple function to check if we're switching to digital mode, * and if so, set bg/fg colors appropriately. *************************************************************/ void set_digital_colors(void) { #ifdef HAVE_LCD_COLOR /* color LCDs.. */ if(settings.clock == DIGITAL) { rb->lcd_set_foreground(LCD_WHITE); rb->lcd_set_background(LCD_BLACK); } else { rb->lcd_set_foreground(LCD_BLACK); rb->lcd_set_background(LCD_RGBPACK(180,200,230)); } #elif LCD_DEPTH >= 2 if(settings.clock == DIGITAL) { rb->lcd_set_foreground(LCD_WHITE); rb->lcd_set_background(LCD_BLACK); } else { rb->lcd_set_foreground(LCD_BLACK); rb->lcd_set_background(LCD_WHITE); } #endif } /************************************************************* * Simple function to set standard black-on-light blue colors. ************************************************************/ void set_standard_colors(void) { #ifdef HAVE_LCD_COLOR /* color LCDs only.. */ rb->lcd_set_foreground(LCD_BLACK); rb->lcd_set_background(LCD_RGBPACK(180,200,230)); #elif LCD_DEPTH >= 2 rb->lcd_set_foreground(LCD_BLACK); rb->lcd_set_background(LCD_WHITE); #endif } /************************** * Cleanup on plugin return *************************/ void cleanup(void *parameter) { (void)parameter; if(settings.general[general_savesetting] == 1) save_settings(true); /* restore set backlight timeout */ rb->backlight_set_timeout(rb->global_settings->backlight_timeout); } /**************** * Shows the logo ***************/ void show_clock_logo(void) { #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_BLACK); rb->lcd_set_background(LCD_RGBPACK(180,200,230)); #endif rb->lcd_clear_display();; rb->lcd_bitmap(clock_logo, 0, 0, LOGO_WIDTH, LOGO_HEIGHT); rb->lcd_update(); } /******************************** * Saves "saved_settings" to disk *******************************/ void save_settings(bool interface) { int fd; if(interface) { rb->lcd_clear_display(); show_clock_logo(); draw_message(MESSAGE_SAVING, 1); rb->lcd_update(); } fd = rb->creat(default_filename); /* create the settings file */ if(fd >= 0) /* file exists, save successful */ { rb->write (fd, &settings, sizeof(struct saved_settings)); rb->close(fd); if(interface) { rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); rb->lcd_fillrect(0, LCD_HEIGHT-MESSAGE_HEIGHT, LCD_WIDTH, MESSAGE_HEIGHT); rb->lcd_set_drawmode(DRMODE_SOLID); draw_message(MESSAGE_SAVED, 1); } } else /* couldn't save for some reason */ { if(interface) { rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); rb->lcd_fillrect(0, LCD_HEIGHT-MESSAGE_HEIGHT, LCD_WIDTH, MESSAGE_HEIGHT); rb->lcd_set_drawmode(DRMODE_SOLID); draw_message(MESSAGE_ERRSAVE, 1); } } if(interface) { rb->lcd_update(); rb->sleep(HZ); /* pause a second */ } } /********************************** * Loads "saved_settings" from disk *********************************/ void load_settings(void) { /* open the settings file */ int fd; fd = rb->open(default_filename, O_RDONLY); rb->lcd_clear_display(); show_clock_logo(); draw_message(MESSAGE_LOADING, 1); rb->lcd_update(); if(fd >= 0) /* does file exist? */ { if(rb->filesize(fd) == sizeof(struct saved_settings)) /* if so, is it the right size? */ { rb->read(fd, &settings, sizeof(struct saved_settings)); rb->close(fd); rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); rb->lcd_fillrect(0, LCD_HEIGHT-MESSAGE_HEIGHT, LCD_WIDTH, MESSAGE_HEIGHT); rb->lcd_set_drawmode(DRMODE_SOLID); draw_message(MESSAGE_LOADED, 1); } else /* must be invalid, bail out */ { rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); rb->lcd_fillrect(0, LCD_HEIGHT-MESSAGE_HEIGHT, LCD_WIDTH, MESSAGE_HEIGHT); rb->lcd_set_drawmode(DRMODE_SOLID); draw_message(MESSAGE_ERRLOAD, 1); reset_settings(); } } else /* must be missing, bail out */ { rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); rb->lcd_fillrect(0, LCD_HEIGHT-MESSAGE_HEIGHT, LCD_WIDTH, MESSAGE_HEIGHT); rb->lcd_set_drawmode(DRMODE_SOLID); draw_message(MESSAGE_ERRLOAD, 1); reset_settings(); } rb->lcd_update(); #ifndef SIMULATOR rb->ata_sleep(); #endif rb->sleep(HZ); } /******************************* * Init clock, set up x/y tables ******************************/ void init_clock(void) { #define ANALOG_VALUES 60 #define ANALOG_YCENTER (LCD_HEIGHT/2) #define ANALOG_XCENTER (LCD_WIDTH/2) #define ANALOG_MIN_RADIUS MIN(LCD_HEIGHT/2 -10, LCD_WIDTH/2 -10) #define ANALOG_HR_RADIUS ((2 * ANALOG_MIN_RADIUS)/3) #define PI 3.141592 int i; rb->lcd_setfont(FONT_SYSFIXED); /* universal font */ load_settings(); /* set backlight timeout */ if(settings.general[general_backlight] == 0) rb->backlight_set_timeout(0); else if(settings.general[general_backlight] == 1) rb->backlight_set_timeout(rb->global_settings->backlight_timeout); else if(settings.general[general_backlight] == 2) rb->backlight_set_timeout(1); for(i=0; i> 14) + ANALOG_XCENTER; yminute[i] = ((sin(360*i/ ANALOG_VALUES-90) * ANALOG_MIN_RADIUS) >> 14) + ANALOG_YCENTER; xhour[i] = ((sin(360 * i / ANALOG_VALUES) * ANALOG_HR_RADIUS) >> 14) + ANALOG_XCENTER; yhour[i] = ((sin(360 * i / ANALOG_VALUES-90) * ANALOG_HR_RADIUS) >> 14) + ANALOG_YCENTER; /* Fullscreen initialization */ if(i==0) { xminute_full[i] = LCD_WIDTH/2; xhour_full[i] = LCD_WIDTH/2; yminute_full[i] = 1; yhour_full[i] = LCD_HEIGHT/6; } else if(i<10 || (i>50 && i <60) ) { xminute_full[i] = xminute_full[i-1]+LCD_WIDTH/20; xhour_full[i] = xhour_full[i-1]+(LCD_WIDTH/30); yminute_full[i] = 1; yhour_full[i] = LCD_HEIGHT/6; } else if (i>=10 && i < 20) { xminute_full[i] = LCD_WIDTH-2; xhour_full[i] = (5*LCD_WIDTH)/6; yminute_full[i] = ((i-10)*LCD_HEIGHT)/10; yhour_full[i] = (LCD_HEIGHT/6)+((i-10)*(LCD_HEIGHT))/15; } else if(i>=20&&i<40) { xminute_full[i] = ((40-i)*LCD_WIDTH)/20; xhour_full[i] = (LCD_WIDTH/6)+((40-i)*(LCD_WIDTH))/30; yminute_full[i] = LCD_HEIGHT-2; yhour_full[i] = (5*LCD_HEIGHT)/6; } else { xminute_full[i] = 1; xhour_full[i] = LCD_WIDTH/6; yminute_full[i] = ((50-i)*LCD_HEIGHT)/10; yhour_full[i] = LCD_HEIGHT/6 + ((50-i)*LCD_HEIGHT)/15; } } } /******************* * Analog clock mode ******************/ void analog_clock(int hour, int minute, int second) { if(hour >= 12) hour -= 12; int i; int hourpos = (hour*5) + (minute/12); /* Crappy fake antialiasing (color LCDs only)! * how this works is we draw a large mid-gray hr/min/sec hand, * then the actual (slightly smaller) hand on top of those. * End result: mid-gray edges to the black hands, smooths them out. */ #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_RGBPACK(100,110,125)); /* second hand */ if(settings.analog[analog_secondhand]) { xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-2, LCD_WIDTH/2, LCD_HEIGHT/2+2, xminute[second], yminute[second]); xlcd_filltriangle(LCD_WIDTH/2-2, LCD_HEIGHT/2, LCD_WIDTH/2+2, LCD_HEIGHT/2, xminute[second], yminute[second]); } /* minute hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-4, LCD_WIDTH/2, LCD_HEIGHT/2+4, xminute[minute], yminute[minute]); xlcd_filltriangle(LCD_WIDTH/2-4, LCD_HEIGHT/2, LCD_WIDTH/2+4, LCD_HEIGHT/2, xminute[minute], yminute[minute]); /* hour hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-4, LCD_WIDTH/2, LCD_HEIGHT/2+4, xhour[hourpos], yhour[hourpos]); xlcd_filltriangle(LCD_WIDTH/2-4, LCD_HEIGHT/2, LCD_WIDTH/2+4, LCD_HEIGHT/2, xhour[hourpos], yhour[hourpos]); rb->lcd_set_foreground(LCD_BLACK); #endif /* second hand, if needed */ if(settings.analog[analog_secondhand]) { xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-1, LCD_WIDTH/2, LCD_HEIGHT/2+1, xminute[second], yminute[second]); xlcd_filltriangle(LCD_WIDTH/2-1, LCD_HEIGHT/2, LCD_WIDTH/2+1, LCD_HEIGHT/2, xminute[second], yminute[second]); } /* minute hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-HAND_W, LCD_WIDTH/2, LCD_HEIGHT/2+HAND_W, xminute[minute], yminute[minute]); xlcd_filltriangle(LCD_WIDTH/2-HAND_W, LCD_HEIGHT/2, LCD_WIDTH/2 +HAND_W, LCD_HEIGHT/2, xminute[minute], yminute[minute]); /* hour hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-HAND_W, LCD_WIDTH/2, LCD_HEIGHT/2+HAND_W, xhour[hourpos], yhour[hourpos]); xlcd_filltriangle(LCD_WIDTH/2-HAND_W, LCD_HEIGHT/2, LCD_WIDTH/2 +HAND_W, LCD_HEIGHT/2, xhour[hourpos], yhour[hourpos]); /* Draw the circle */ for(i=0; i < 60; i+=5) rb->lcd_fillrect(xminute[i]-1, yminute[i]-1, 3, 3); /* Draw the cover over the center */ rb->lcd_drawline((LCD_WIDTH/2)-1, (LCD_HEIGHT/2)+3, (LCD_WIDTH/2)+1, (LCD_HEIGHT/2)+3); rb->lcd_drawline((LCD_WIDTH/2)-3, (LCD_HEIGHT/2)+2, (LCD_WIDTH/2)+3, (LCD_HEIGHT/2)+2); rb->lcd_drawline((LCD_WIDTH/2)-4, (LCD_HEIGHT/2)+1, (LCD_WIDTH/2)+4, (LCD_HEIGHT/2)+1); rb->lcd_drawline((LCD_WIDTH/2)-4, LCD_HEIGHT/2, (LCD_WIDTH/2)+4, LCD_HEIGHT/2); rb->lcd_drawline((LCD_WIDTH/2)-4, (LCD_HEIGHT/2)-1, (LCD_WIDTH/2)+4, (LCD_HEIGHT/2)-1); rb->lcd_drawline((LCD_WIDTH/2)-3, (LCD_HEIGHT/2)-2, (LCD_WIDTH/2)+3, (LCD_HEIGHT/2)-2); rb->lcd_drawline((LCD_WIDTH/2)-1, (LCD_HEIGHT/2)-3, (LCD_WIDTH/2)+1, (LCD_HEIGHT/2)-3); } /******************** * Digital clock mode *******************/ void digital_clock(int hour, int minute, int second, bool colon) { int x_ofs=0; /* this basically detects if we draw an AM or PM bitmap. * if we don't, we center the hh:mm display. */ if(!settings.digital[digital_format]) x_ofs=DIGIT_WIDTH/2; #if LCD_DEPTH == 1 rb->lcd_fillrect(0,0,112,64); #endif if(settings.digital[digital_format]) { /* draw the AM or PM bitmap */ if(hour<12) draw_segment(SEGMENT_AM,DIGIT_XOFS(6)+DIGIT_WIDTH*5, 0); else draw_segment(SEGMENT_PM,DIGIT_XOFS(6)+DIGIT_WIDTH*5, 0); /* and then readjust the hour to 12-hour format * ( 13:00+ -> 1:00+ ) */ if(hour>12) hour -= 12; } /* hour */ draw_segment(hour/10, DIGIT_XOFS(6)+x_ofs, 0); draw_segment(hour%10, DIGIT_XOFS(6)+DIGIT_WIDTH+x_ofs, 0); /* colon */ if(colon) draw_segment(COLON, DIGIT_XOFS(6)+2*DIGIT_WIDTH+x_ofs, 0); /* minutes */ draw_segment(minute/10, DIGIT_XOFS(6)+3*DIGIT_WIDTH+x_ofs, 0); draw_segment(minute%10, DIGIT_XOFS(6)+4*DIGIT_WIDTH+x_ofs, 0); if(settings.digital[digital_seconds]) { draw_segment(second/10, DIGIT_XOFS(2), DIGIT_HEIGHT); draw_segment(second%10, DIGIT_XOFS(2)+DIGIT_WIDTH, DIGIT_HEIGHT); } } /*********************** * Fullscreen clock mode **********************/ void fullscreen_clock(int hour, int minute, int second) { if(hour >= 12) hour -= 12; int i; int hourpos = (hour*5) + (minute/12); /* Crappy fake antialiasing (color LCDs only)! * how this works is we draw a large mid-gray hr/min/sec hand, * then the actual (slightly smaller) hand on top of those. * End result: mid-gray edges to the black hands, smooths them out. */ #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_RGBPACK(100,110,125)); /* second hand */ if(settings.analog[analog_secondhand]) { xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-2, LCD_WIDTH/2, LCD_HEIGHT/2+2, xminute_full[second], yminute_full[second]); xlcd_filltriangle(LCD_WIDTH/2-2, LCD_HEIGHT/2, LCD_WIDTH/2+2, LCD_HEIGHT/2, xminute_full[second], yminute_full[second]); } /* minute hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-4, LCD_WIDTH/2, LCD_HEIGHT/2+4, xminute_full[minute], yminute_full[minute]); xlcd_filltriangle(LCD_WIDTH/2-4, LCD_HEIGHT/2, LCD_WIDTH/2+4, LCD_HEIGHT/2, xminute_full[minute], yminute_full[minute]); /* hour hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-4, LCD_WIDTH/2, LCD_HEIGHT/2+4, xhour_full[hourpos], yhour_full[hourpos]); xlcd_filltriangle(LCD_WIDTH/2-4, LCD_HEIGHT/2, LCD_WIDTH/2+4, LCD_HEIGHT/2, xhour_full[hourpos], yhour_full[hourpos]); rb->lcd_set_foreground(LCD_BLACK); #endif /* second hand, if needed */ if(settings.analog[analog_secondhand]) { xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-1, LCD_WIDTH/2, LCD_HEIGHT/2+1, xminute_full[second], yminute_full[second]); xlcd_filltriangle(LCD_WIDTH/2-1, LCD_HEIGHT/2, LCD_WIDTH/2+1, LCD_HEIGHT/2, xminute_full[second], yminute_full[second]); } /* minute hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-3, LCD_WIDTH/2, LCD_HEIGHT/2+3, xminute_full[minute], yminute_full[minute]); xlcd_filltriangle(LCD_WIDTH/2-3, LCD_HEIGHT/2, LCD_WIDTH/2+3, LCD_HEIGHT/2, xminute_full[minute], yminute_full[minute]); /* hour hand */ xlcd_filltriangle(LCD_WIDTH/2, LCD_HEIGHT/2-3, LCD_WIDTH/2, LCD_HEIGHT/2+3, xhour_full[hourpos], yhour_full[hourpos]); xlcd_filltriangle(LCD_WIDTH/2-3, LCD_HEIGHT/2, LCD_WIDTH/2+3, LCD_HEIGHT/2, xhour_full[hourpos], yhour_full[hourpos]); /* Draw the circle */ for(i=0; i < 60; i+=5) rb->lcd_fillrect(xminute_full[i]-1, yminute_full[i]-1, 3, 3); /* Draw the cover over the center */ rb->lcd_drawline((LCD_WIDTH/2)-1, (LCD_HEIGHT/2)+3, (LCD_WIDTH/2)+1, (LCD_HEIGHT/2)+3); rb->lcd_drawline((LCD_WIDTH/2)-3, (LCD_HEIGHT/2)+2, (LCD_WIDTH/2)+3, (LCD_HEIGHT/2)+2); rb->lcd_drawline((LCD_WIDTH/2)-4, (LCD_HEIGHT/2)+1, (LCD_WIDTH/2)+4, (LCD_HEIGHT/2)+1); rb->lcd_drawline((LCD_WIDTH/2)-4, LCD_HEIGHT/2, (LCD_WIDTH/2)+4, LCD_HEIGHT/2); rb->lcd_drawline((LCD_WIDTH/2)-4, (LCD_HEIGHT/2)-1, (LCD_WIDTH/2)+4, (LCD_HEIGHT/2)-1); rb->lcd_drawline((LCD_WIDTH/2)-3, (LCD_HEIGHT/2)-2, (LCD_WIDTH/2)+3, (LCD_HEIGHT/2)-2); rb->lcd_drawline((LCD_WIDTH/2)-1, (LCD_HEIGHT/2)-3, (LCD_WIDTH/2)+1, (LCD_HEIGHT/2)-3); } /******************* * Binary clock mode ******************/ void binary_clock(int hour, int minute, int second) { int i, xpos=0; int mode_var[3]; /* pointers to h, m, s arguments */ int mode; /* 0 = hour, 1 = minute, 2 = second */ mode_var[0] = hour; mode_var[1] = minute; mode_var[2] = second; for(mode = 0; mode < 3; mode++) { for(i = 32; i > 0; i /= 2) { if(mode_var[mode] >= i) { if(settings.binary[binary_mode]) draw_digit(DOT_FILLED, xpos*DIGIT_WIDTH+DIGIT_XOFS(6), DIGIT_HEIGHT*mode+DIGIT_YOFS(3)); else draw_digit(1, xpos*DIGIT_WIDTH+DIGIT_XOFS(6), DIGIT_HEIGHT*mode+DIGIT_YOFS(3)); mode_var[mode] -= i; } else { if(settings.binary[binary_mode]) draw_digit(DOT_EMPTY, xpos*DIGIT_WIDTH+DIGIT_XOFS(6), DIGIT_HEIGHT*mode+DIGIT_YOFS(3)); else draw_digit(0, xpos*DIGIT_WIDTH+DIGIT_XOFS(6), DIGIT_HEIGHT*mode+DIGIT_YOFS(3)); } xpos++; } xpos=0; /* reset the x-pos for next mode */ } } /****************** * Plain clock mode *****************/ void plain_clock(int hour, int minute, int second, bool colon) { int x_ofs=0; /* this basically detects if we draw an AM or PM bitmap. * if we don't, we center the hh:mm display. */ if(!settings.plain[plain_format]) x_ofs=DIGIT_WIDTH/2; if(settings.plain[plain_format]) { /* draw the AM or PM bitmap */ if(hour<12) draw_digit(ICON_AM, DIGIT_XOFS(6)+(DIGIT_WIDTH*5)+x_ofs, 0); else draw_digit(ICON_PM, DIGIT_XOFS(6)+(DIGIT_WIDTH*5)+x_ofs, 0); /* and then readjust the hour to 12-hour format * ( 13:00+ -> 1:00+ ) */ if(hour>12) hour -= 12; } draw_digit(hour/10, DIGIT_XOFS(6)+(DIGIT_WIDTH*0)+x_ofs, 0); draw_digit(hour%10, DIGIT_XOFS(6)+(DIGIT_WIDTH*1)+x_ofs, 0); if(colon) draw_digit(COLON, DIGIT_XOFS(6)+(DIGIT_WIDTH*2)+x_ofs, 0); draw_digit(minute/10, DIGIT_XOFS(6)+(DIGIT_WIDTH*3)+x_ofs, 0); draw_digit(minute%10, DIGIT_XOFS(6)+(DIGIT_WIDTH*4)+x_ofs, 0); if(settings.plain[plain_seconds]) { draw_digit(second/10, DIGIT_XOFS(2), DIGIT_HEIGHT); draw_digit(second%10, DIGIT_XOFS(2)+(DIGIT_WIDTH), DIGIT_HEIGHT); } } /********************** * Analog settings menu *********************/ void analog_settings_menu(void) { int m=0, result; done = false; #ifdef HAVE_LCD_COLOR rb->lcd_set_background(LCD_RGBPACK(180,200,230)); rb->lcd_set_foreground(LCD_BLACK); #endif m = rb->menu_init(analog_items, sizeof(analog_items) / sizeof(*analog_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: rb->set_option("Show Date", &settings.analog[analog_date], INT, analog_date_text, 3, NULL); break; case 1: rb->set_option("Show Second Hand", &settings.analog[analog_secondhand], INT, analog_secondhand_text, 2, NULL); break; case 2: rb->set_option("Show Time", &settings.analog[analog_time], INT, analog_time_text, 3, NULL); break; default: done = true; break; } rb->menu_exit(m); } } /*********************** * Digital settings menu **********************/ void digital_settings_menu(void) { int m=0, result; done = false; #ifdef HAVE_LCD_COLOR rb->lcd_set_background(LCD_RGBPACK(180,200,230)); rb->lcd_set_foreground(LCD_BLACK); #endif m = rb->menu_init(digital_items, sizeof(digital_items) / sizeof(*digital_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: rb->set_option("Show Seconds", &settings.digital[digital_seconds], INT, digital_seconds_text, 2, NULL); break; case 1: rb->set_option("Show Date", &settings.digital[digital_date], INT, digital_date_text, 3, NULL); break; case 2: rb->set_option("Blinking Colon", &settings.digital[digital_blinkcolon], INT, digital_blinkcolon_text, 2, NULL); break; case 3: rb->set_option("Time Format", &settings.digital[digital_format], INT, digital_format_text, 2, NULL); break; default: done = true; break; } rb->menu_exit(m); } } /************************** * Fullscreen settings menu *************************/ void fullscreen_settings_menu(void) { int m=0, result; done = false; #ifdef HAVE_LCD_COLOR rb->lcd_set_background(LCD_RGBPACK(180,200,230)); rb->lcd_set_foreground(LCD_BLACK); #endif m = rb->menu_init(fullscreen_items, sizeof(fullscreen_items) / sizeof(*fullscreen_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: rb->set_option("Show Border", &settings.fullscreen[fullscreen_border], INT, fullscreen_border_text, 2, NULL); break; case 1: rb->set_option("Show Second Hand", &settings.fullscreen[fullscreen_secondhand], INT, fullscreen_secondhand_text, 2, NULL); break; default: done = true; break; } rb->menu_exit(m); } } /********************** * Binary settings menu *********************/ void binary_settings_menu(void) { int m=0, result; done = false; #ifdef HAVE_LCD_COLOR rb->lcd_set_background(LCD_RGBPACK(180,200,230)); rb->lcd_set_foreground(LCD_BLACK); #endif m = rb->menu_init(binary_items, sizeof(binary_items) / sizeof(*binary_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: rb->set_option("Display Mode", &settings.binary[binary_mode], INT, binary_mode_text, 2, NULL); break; default: done = true; break; } rb->menu_exit(m); } } /********************* * Plain settings menu ********************/ void plain_settings_menu(void) { int m=0, result; done = false; #ifdef HAVE_LCD_COLOR rb->lcd_set_background(LCD_RGBPACK(180,200,230)); rb->lcd_set_foreground(LCD_BLACK); #endif m = rb->menu_init(plain_items, sizeof(plain_items) / sizeof(*plain_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: rb->set_option("Show Date", &settings.plain[plain_date], INT, plain_date_text, 3, NULL); break; case 1: rb->set_option("Show Seconds", &settings.plain[plain_seconds], INT, plain_seconds_text, 2, NULL); break; case 2: rb->set_option("Blinking Colon", &settings.plain[plain_blinkcolon], INT, plain_blinkcolon_text, 2, NULL); break; case 3: rb->set_option("Time Format", &settings.plain[plain_format], INT, plain_format_text, 2, NULL); break; default: done = true; break; } rb->menu_exit(m); } } /************************************** * Settings screen for the current mode *************************************/ void settings_screen(void) { set_standard_colors(); if(settings.clock == ANALOG) analog_settings_menu(); else if(settings.clock == DIGITAL) digital_settings_menu(); else if(settings.clock == FULLSCREEN) fullscreen_settings_menu(); else if(settings.clock == BINARY) binary_settings_menu(); else if(settings.clock == PLAIN) plain_settings_menu(); set_digital_colors(); } /*********************************************************** * Confirm resetting of settings, used in general_settings() **********************************************************/ void confirm_reset(void) { int result=0; rb->set_option("Reset all settings?", &result, INT, noyes_text, 2, NULL); if(result == 1) /* reset! */ { reset_settings(); rb->splash(HZ, true, "Settings reset!"); } else rb->splash(HZ, true, "Settings NOT reset."); } /************************************ * General settings. Reset, save, etc ***********************************/ void general_settings(void) { int m, result; done = false; set_standard_colors(); m = rb->menu_init(general_settings_items, sizeof(general_settings_items) / sizeof(*general_settings_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: confirm_reset(); break; case 1: save_settings(false); rb->splash(HZ, true, "Settings saved"); break; case 2: rb->set_option("Save On Exit", &settings.general[general_savesetting], INT, saving_options_text, 2, NULL); /* if we no longer save on exit, we better save now to remember that */ if(settings.general[general_savesetting] == 0) save_settings(false); break; case 3: rb->set_option("Show Counter", &settings.general[general_counter], INT, show_counter_text, 2, NULL); break; case 4: rb->set_option("Backlight Settings", &settings.general[general_backlight], INT, backlight_settings_text, 3, NULL); break; case 5: rb->set_option("Idle Poweroff (temporary)", &idle_poweroff, INT, idle_poweroff_text, 2, NULL); break; default: done=true; break; } rb->menu_exit(m); } set_digital_colors(); } /**************************************** * Draws the extras, IE border, digits... ***************************************/ void draw_extras(int year, int day, int month, int hour, int minute, int second) { int i; struct tm* current_time = rb->get_time(); char moday[8]; char dateyr[6]; char tmhrmin[7]; char tmsec[3]; /* american date readout */ if(settings.analog[analog_date] == 1) rb->snprintf(moday, sizeof(moday), "%02d/%02d", month, day); else rb->snprintf(moday, sizeof(moday), "%02d.%02d", day, month); rb->snprintf(dateyr, sizeof(dateyr), "%d", year); rb->snprintf(tmhrmin, sizeof(tmhrmin), "%02d:%02d", hour, minute); rb->snprintf(tmsec, sizeof(tmsec), "%02d", second); /* Analog Extras */ if(settings.clock == ANALOG) { if(settings.analog[analog_time] != 0) /* Digital readout */ { draw_smalldigit(hour/10, SMALLDIGIT_WIDTH*0, 0); draw_smalldigit(hour%10, SMALLDIGIT_WIDTH*1, 0); draw_smalldigit(COLON, SMALLDIGIT_WIDTH*2, 0); draw_smalldigit(minute/10, SMALLDIGIT_WIDTH*3, 0); draw_smalldigit(minute%10, SMALLDIGIT_WIDTH*4, 0); draw_smalldigit(second/10, SMALLDIGIT_WIDTH*1.5, SMALLDIGIT_HEIGHT); draw_smalldigit(second%10, SMALLDIGIT_WIDTH*2.5, SMALLDIGIT_HEIGHT); /* AM/PM indicator */ if(settings.analog[analog_time] == 2) { if(current_time->tm_hour > 12) /* PM */ draw_digit(ICON_PM, LCD_WIDTH-DIGIT_WIDTH, DIGIT_HEIGHT/2-DIGIT_HEIGHT); else /* AM */ draw_digit(ICON_AM, LCD_WIDTH-DIGIT_WIDTH, DIGIT_HEIGHT/2-DIGIT_HEIGHT); } } if(settings.analog[analog_date] != 0) /* Date readout */ { if(settings.analog[analog_date] == 1) { draw_smalldigit(month/10, SMALLDIGIT_WIDTH*0, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(month%10, SMALLDIGIT_WIDTH*1, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(SLASH, SMALLDIGIT_WIDTH*2, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(day/10, SMALLDIGIT_WIDTH*3, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(day%10, SMALLDIGIT_WIDTH*4, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(year/1000, SMALLDIGIT_WIDTH*0.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(year%1000/100, SMALLDIGIT_WIDTH*1.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(year%100/10, SMALLDIGIT_WIDTH*2.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(year%10, SMALLDIGIT_WIDTH*3.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); } else if(settings.analog[analog_date] == 2) { draw_smalldigit(day/10, SMALLDIGIT_WIDTH*0, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(day%10, SMALLDIGIT_WIDTH*1, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(PERIOD, SMALLDIGIT_WIDTH*2, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(month/10, SMALLDIGIT_WIDTH*3, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(month%10, SMALLDIGIT_WIDTH*4, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(year/1000, SMALLDIGIT_WIDTH*0.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(year%1000/100, SMALLDIGIT_WIDTH*1.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(year%100/10, SMALLDIGIT_WIDTH*2.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(year%10, SMALLDIGIT_WIDTH*3.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); } } } else if(settings.clock == DIGITAL) { /* Date readout */ if(settings.digital[digital_date] == 1) /* american mode */ { draw_smallsegment(month/10, SMALLSEG_WIDTH*0+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(month%10, SMALLSEG_WIDTH*1+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(SLASH, SMALLSEG_WIDTH*2+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(day/10, SMALLSEG_WIDTH*3+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(day%10, SMALLSEG_WIDTH*4+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(SLASH, SMALLSEG_WIDTH*5+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year/1000, SMALLSEG_WIDTH*6+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year%1000/100, SMALLSEG_WIDTH*7+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year%100/10, SMALLSEG_WIDTH*8+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year%10, SMALLSEG_WIDTH*9+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); } else if(settings.digital[digital_date] == 2) /* european mode */ { draw_smallsegment(day/10, SMALLSEG_WIDTH*0+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(day%10, SMALLSEG_WIDTH*1+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(PERIOD, SMALLSEG_WIDTH*2+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(month/10, SMALLSEG_WIDTH*3+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(month%10, SMALLSEG_WIDTH*4+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(PERIOD, SMALLSEG_WIDTH*5+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year/1000, SMALLSEG_WIDTH*6+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year%1000/100, SMALLSEG_WIDTH*7+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year%100/10, SMALLSEG_WIDTH*8+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); draw_smallsegment(year%10, SMALLSEG_WIDTH*9+SMALLSEG_XOFS(10), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET*2); } } else if(settings.clock == FULLSCREEN) /* Fullscreen mode */ { if(settings.fullscreen[fullscreen_border]) { for(i=0; i < 60; i+=5) /* Draw the circle */ rb->lcd_fillrect(xminute_full[i]-1, yminute_full[i]-1, 3, 3); } } else if(settings.clock == PLAIN) /* Plain mode */ { /* Date readout */ if(settings.plain[plain_date] == 1) /* american mode */ { draw_smalldigit(month/10, SMALLDIGIT_WIDTH*0+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(month%10, SMALLDIGIT_WIDTH*1+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(SLASH, SMALLDIGIT_WIDTH*2+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(day/10, SMALLDIGIT_WIDTH*3+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(day%10, SMALLDIGIT_WIDTH*4+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(SLASH, SMALLDIGIT_WIDTH*5+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year/1000, SMALLDIGIT_WIDTH*6+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year%1000/100, SMALLDIGIT_WIDTH*7+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year%100/10, SMALLDIGIT_WIDTH*8+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year%10, SMALLDIGIT_WIDTH*9+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); } else if(settings.plain[plain_date] == 2) /* european mode */ { draw_smalldigit(day/10, SMALLDIGIT_WIDTH*0+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(day%10, SMALLDIGIT_WIDTH*1+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(PERIOD, SMALLDIGIT_WIDTH*2+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(month/10, SMALLDIGIT_WIDTH*3+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(month%10, SMALLDIGIT_WIDTH*4+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(PERIOD, SMALLDIGIT_WIDTH*5+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year/1000, SMALLDIGIT_WIDTH*6+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year%1000/100, SMALLDIGIT_WIDTH*7+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year%100/10, SMALLDIGIT_WIDTH*8+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); draw_smalldigit(year%10, SMALLDIGIT_WIDTH*9+SMALLDIGIT_XOFS(10), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET*2); } } } /*************** * Select a mode **************/ void mode_selector(void) { int m, result; done = false; set_standard_colors(); m = rb->menu_init(mode_selector_items, sizeof(mode_selector_items) / sizeof(*mode_selector_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); /* check for this, so if the user exits the menu without * making a selection, it won't change to some weird value. */ if(result >= 0) settings.clock = result+1; done = true; rb->menu_exit(m); } set_digital_colors(); } /********************* * Display the counter ********************/ void show_counter(void) { /* increment counter */ if(counting) passed_time = *rb->current_tick - start_tick; else passed_time = 0; displayed_value = counter + passed_time; displayed_value = displayed_value / HZ; /* these are the REAL displayed values */ count_s = displayed_value % 60; count_m = displayed_value % 3600 / 60; count_h = displayed_value / 3600; if(settings.general[general_counter]) { if(settings.clock == ANALOG) { draw_smalldigit(count_h/10, LCD_WIDTH-SMALLDIGIT_WIDTH*5, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(count_h%10, LCD_WIDTH-SMALLDIGIT_WIDTH*4, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(COLON, LCD_WIDTH-SMALLDIGIT_WIDTH*3, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(count_m/10, LCD_WIDTH-SMALLDIGIT_WIDTH*2, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(count_m%10, LCD_WIDTH-SMALLDIGIT_WIDTH, LCD_HEIGHT-SMALLDIGIT_HEIGHT*2); draw_smalldigit(count_s/10, LCD_WIDTH-SMALLDIGIT_WIDTH*3.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); draw_smalldigit(count_s%10, LCD_WIDTH-SMALLDIGIT_WIDTH*2.5, LCD_HEIGHT-SMALLDIGIT_HEIGHT); } else if(settings.clock == DIGITAL) { draw_smallsegment(count_h/10, SMALLSEG_WIDTH*0+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(count_h%10, SMALLSEG_WIDTH*1+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(COLON, SMALLSEG_WIDTH*2+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(count_m/10, SMALLSEG_WIDTH*3+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(count_m%10, SMALLSEG_WIDTH*4+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(COLON, SMALLSEG_WIDTH*5+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(count_s/10, SMALLSEG_WIDTH*6+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); draw_smallsegment(count_s%10, SMALLSEG_WIDTH*7+SMALLSEG_XOFS(8), LCD_HEIGHT-SMALLSEG_HEIGHT*LCD_OFFSET); } else if(settings.clock == FULLSCREEN) { draw_smalldigit(count_h/10, SMALLDIGIT_WIDTH*0+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(count_h%10, SMALLDIGIT_WIDTH*1+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(COLON, SMALLDIGIT_WIDTH*2+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(count_m/10, SMALLDIGIT_WIDTH*3+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(count_m%10, SMALLDIGIT_WIDTH*4+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(COLON, SMALLDIGIT_WIDTH*5+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(count_s/10, SMALLDIGIT_WIDTH*6+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); draw_smalldigit(count_s%10, SMALLDIGIT_WIDTH*7+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*1.5); } else if(settings.clock == PLAIN) { draw_smalldigit(count_h/10, SMALLDIGIT_WIDTH*0+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(count_h%10, SMALLDIGIT_WIDTH*1+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(COLON, SMALLDIGIT_WIDTH*2+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(count_m/10, SMALLDIGIT_WIDTH*3+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(count_m%10, SMALLDIGIT_WIDTH*4+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(COLON, SMALLDIGIT_WIDTH*5+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(count_s/10, SMALLDIGIT_WIDTH*6+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); draw_smalldigit(count_s%10, SMALLDIGIT_WIDTH*7+SMALLDIGIT_XOFS(8), LCD_HEIGHT-SMALLDIGIT_HEIGHT*LCD_OFFSET); } } } /*********** * Main menu **********/ void main_menu(void) { int m, result; done = false; set_standard_colors(); m = rb->menu_init(main_menu_items, sizeof(main_menu_items) / sizeof(*main_menu_items), NULL, NULL, NULL, NULL); while(!done) { result = rb->menu_show(m); switch(result) { case 0: rb->lcd_setfont(FONT_SYSFIXED); done = true; break; case 1: mode_selector(); break; case 2: settings_screen(); break; case 3: general_settings(); break; case 4: exit_clock = true; done = true; break; default: done=true; break; } rb->menu_exit(m); } rb->lcd_setfont(FONT_SYSFIXED); set_digital_colors(); } /********************************************************************** * Plugin starts here **********************************************************************/ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { int button; /* time/date ints */ int hour, minute, second; int temphour; int last_second = -1; int year, day, month; bool counter_btn_held = false; struct tm* current_time; (void)parameter; rb = api; #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); #endif init_clock(); /* init xlcd functions */ xlcd_init(rb); set_digital_colors(); while(!exit_clock) { /********************* * Time info *********************/ current_time = rb->get_time(); hour = current_time->tm_hour; minute = current_time->tm_min; second = current_time->tm_sec; temphour = current_time->tm_hour; /********************* * Date info *********************/ year = current_time->tm_year + 1900; day = current_time->tm_mday; month = current_time->tm_mon + 1; done = false; if(second != last_second) { rb->lcd_clear_display(); /* Analog mode */ if(settings.clock == ANALOG) analog_clock(hour, minute, second); /* Digital mode */ else if(settings.clock == DIGITAL) { if(settings.digital[digital_blinkcolon]) digital_clock(hour, minute, second, second & 1); else digital_clock(hour, minute, second, true); } /* Fullscreen mode */ else if(settings.clock == FULLSCREEN) fullscreen_clock(hour, minute, second); /* Binary mode */ else if(settings.clock == BINARY) binary_clock(hour, minute, second); /* Plain mode */ else if(settings.clock == PLAIN) { if(settings.plain[plain_blinkcolon]) plain_clock(hour, minute, second, second & 1); else plain_clock(hour, minute, second, true); } /* show counter */ show_counter(); } if(settings.analog[analog_time] == 2 && temphour == 0) temphour = 12; if(settings.analog[analog_time] == 2 && temphour > 12) temphour -= 12; /* all the "extras" - readouts/displays */ draw_extras(year, day, month, temphour, minute, second); if(!idle_poweroff) rb->reset_poweroff_timer(); rb->lcd_update(); /************************* * Scan for button presses ************************/ button = rb->button_get_w_tmo(HZ/10); switch (button) { case COUNTER_TOGGLE_BUTTON: /* start/stop counter */ if(settings.general[general_counter]) { if(!counter_btn_held) /* Ignore if the counter was reset */ { if(counting) { counting = false; counter += passed_time; } else { counting = true; start_tick = *rb->current_tick; } } counter_btn_held = false; } break; case COUNTER_RESET_BUTTON: /* reset counter */ if(settings.general[general_counter]) { counter_btn_held = true; /* Ignore the release event */ counter = 0; start_tick = *rb->current_tick; } break; case MODE_NEXT_BUTTON: if(settings.clock < CLOCK_MODES) settings.clock++; else settings.clock = 1; set_digital_colors(); break; case MODE_PREV_BUTTON: if(settings.clock > 1) settings.clock--; else settings.clock = CLOCK_MODES; set_digital_colors(); break; case MENU_BUTTON: /* main menu */ #ifdef ALT_MENU_BUTTON case ALT_MENU_BUTTON: #endif main_menu(); break; default: if(rb->default_event_handler_ex(button, cleanup, NULL) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; } } cleanup(NULL); return PLUGIN_OK; }