It is currently Wed Jul 06, 2011 6:41 pm

All times are UTC - 8 hours




 Page 1 of 1 [ 5 posts ] 
Author Message
 Post subject: LED Number Clock
PostPosted: Mon Mar 07, 2011 6:37 pm 

Joined: Fri Mar 04, 2011 3:53 pm
Posts: 3
Location: Seattle, WA
I took the code that Duane wrote for the Binary LED clock and updated it to display numbers using the LED graphics.

It runs the battery down pretty quick and so I am trying to figure out a way to toggle the watch to sleep using the button but I haven't quite figured out how to make that work yet.

/**
*
* LED Number Clock
*  Displays time using LED graphics.
*
* Copyright (C) 2011, David Bates [email protected]
*
*   based on:

*   Binary/BCD clock
*
*   Read digits from top to bottom - hours/10, hours%10, mins/10, mins%10, secs/10, secs%10
*
*   Copyright (C) 2011, Duane Maxwell [email protected]
*
*   Permission to use, copy, modify, and/or distribute this software for 
*   any purpose with or without fee is hereby granted, provided that the 
*   above copyright notice and this permission notice appear in all copies. 

*   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 
*   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 
*   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 
*   BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 
*   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
*   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
*   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
*   SOFTWARE.
**/

#include <pulse_os.h>
#include <pulse_types.h>
#include <stdint.h>

#define LED_SIZE 10
#define H_OFFSET 4
#define V_OFFSET 4
#define ROW_SIZE 4
#define COL_SIZE 5
#define HR_L_X_ORIGIN 0
#define HR_L_Y_ORIGIN 0
#define HR_R_X_ORIGIN 5
#define HR_R_Y_ORIGIN 0
#define MN_L_X_ORIGIN 0
#define MN_L_Y_ORIGIN 6
#define MN_R_X_ORIGIN 5
#define MN_R_Y_ORIGIN 6

bool firstStart=true;
bool displayON=true;

static int numMap[] = {
    1022367, 559240, 991119,  1019791, 561049,
    1019679, 1023761, 559247, 1023903, 561055
};

static color24_t offColors[] = {
{0x00,0x00,0x00,0x00},
{0x11,0x00,0x00,0x00},
{0x11,0x11,0x11,0x00},
{0x22,0x00,0x00,0x00},
{0x22,0x11,0x11,0x00},
{0x33,0x11,0x11,0x00},
{0x22,0x22,0x22,0x00},
{0x33,0x33,0x33,0x00},
{0x44,0x22,0x22,0x00},
{0x55,0x33,0x33,0x00},
{0x77,0x55,0x55,0x00},
{0xBB,0xBB,0xBB,0x00}
};

char offMap[] =
"AAAAAAAAAA"
"AAAAAAAAAA"
"AAAKDDBAAA"
"AAJDDDDAAA"
"AADDDDDAAA"
"AADDDDDAAA"
"AAADDDFAAA"
"AAABDFAAAA"
"AAAAAAAAAA"
"AAAAAAAAAA";

static color24_t onColors[] = {
{0x00,0x00,0x00,0x00},
{0x11,0x00,0x00,0x00},
{0x22,0x00,0x00,0x00},
{0x33,0x00,0x00,0x00},
{0x44,0x00,0x00,0x00},
{0x55,0x00,0x00,0x00},
{0x66,0x00,0x00,0x00},
{0x77,0x00,0x00,0x00},
{0x77,0x11,0x11,0x00},
{0x88,0x00,0x00,0x00},
{0xAA,0x00,0x00,0x00},
{0xBB,0x00,0x00,0x00},
{0x99,0x33,0x33,0x00},
{0xAA,0x22,0x22,0x00},
{0xCC,0x00,0x00,0x00},
{0xDD,0x00,0x00,0x00},
{0xEE,0x00,0x00,0x00},
{0xFF,0x00,0x00,0x00},
{0xFF,0x11,0x11,0x00},
{0xFF,0x22,0x22,0x00},
{0xEE,0x33,0x33,0x00},
{0xFF,0x55,0x55,0x00},
{0xEE,0xBB,0xBB,0x00}
};

char onMap[] =
"AAAAAAAAAA"
"AABCDDCBAA"
"AACEEEECAA"
"ACENPPGECA"
"ADGVRROGDA"
"ADGLRRJGDA"
"ACEGJJGECA"
"AACEEEECAA"
"AABCDDCAAA"
"AAAAAAAAAA";

/****************************************************************/
/*            Application drawing methods                       */
/****************************************************************/
void drawLED(int y,int x,int on) {
    int xx = (x*LED_SIZE)+H_OFFSET;
    int yy = (y*LED_SIZE)+V_OFFSET;
    pulse_set_draw_window(xx,yy,xx+LED_SIZE-1,yy+LED_SIZE-1);
    char *map = on ? onMap : offMap;
    color24_t *colors = on ? onColors : offColors;
    for (int i=0;i<LED_SIZE*LED_SIZE; i++) {
        pulse_draw_point24(colors[*map++-'A']);
    }
}

void drawNum(int originX, int originY, int num) {
    int mask=1;
    for(int i=0;i<=(ROW_SIZE*COL_SIZE)-1;i++) {   
   drawLED((i/ROW_SIZE)+originY,(i%ROW_SIZE)+originX,numMap[num]&mask);
   mask=mask<<1;
    }
}   

void drawTime(int hour, int min) {
    drawNum(HR_L_X_ORIGIN, HR_L_Y_ORIGIN, hour/10);
    drawNum(HR_R_X_ORIGIN, HR_R_Y_ORIGIN, hour%10);
    drawNum(MN_L_X_ORIGIN, MN_L_Y_ORIGIN, min/10);
    drawNum(MN_R_X_ORIGIN, MN_R_Y_ORIGIN, min%10);
}

void drawTimeGraphics() {
    struct pulse_time_tm tm;
    pulse_get_time_date(&tm);
    int hour = tm.tm_hour;
   
    if(hour>12) {
        hour-=12;
    }   

    if(firstStart) {
        drawTime(hour, tm.tm_min);
        firstStart=false;
    }
    else {
        if(0==tm.tm_sec) {
            drawTime(hour, tm.tm_min);
         }
    }   
}

void handle_button_causing_wakeup() {
    if(displayON) {
       pulse_blank_canvas();
        displayON=false;
        pulse_update_power_down_timer(0);
    }
    else {
        pulse_blank_canvas();   
        displayON=true;
    }
}

/****************************************************************/
/*                 Pulse SDK methods                            */
/****************************************************************/
void main_app_init() {
    pulse_blank_canvas();
    pulse_oled_set_brightness(100);
    pulse_register_callback(ACTION_WOKE_FROM_BUTTON, &handle_button_causing_wakeup);
}

void main_app_handle_button_down() {
}

void main_app_handle_button_up() {
}

void main_app_loop() {
    drawTimeGraphics();
}

void main_app_handle_doz() {
    for (int i = 100; i >= 0; i-=6) {
        pulse_oled_set_brightness(i);
        pulse_mdelay(30);
    }
}

void main_app_handle_hardware_update(enum PulseHardwareEvent event) {
}



Offline
 Profile  
 
 Post subject: Re: LED Number Clock
PostPosted: Mon Mar 07, 2011 11:23 pm 
User avatar

Joined: Mon Feb 14, 2011 7:07 pm
Posts: 172
Awesome! Yeah, we'll definitely give you a hand with that power saving stuff. I saw your email to [email protected]



_________________
---

Lead designer of inPulse
Offline
 Profile  
 
 Post subject: Re: LED Number Clock
PostPosted: Tue Mar 08, 2011 4:32 pm 
User avatar

Joined: Tue Feb 15, 2011 10:35 pm
Posts: 7
Hey,

So here's the code where you click the button to go to sleep and click it to wake up. First of all in your code you would never actually send the watch to sleep. Dimming the brightness of the screen is not the same as sending it to sleep. To send it to sleep you have to call
pulse_update_power_down_timer(100);
where 100 is the value in milliseconds of how long from now, should the watch go to sleep. When you click the button to wake it up, the handle_button_causing_wakeup() is called. Now the handle_button_causing_wakeup() is ONLY called when the watch wakes up, so if you want to put the device to sleep when you click the button you'd have to do that from main_app_handle_button_down() or main_app_handle_button_up().

So now, when the watch is awake, when you click the button it goes to main_app_handle_button_down() where it will power it down in 100ms. When the device is off clicking the button will go to handle_button_causing_wakeup() where it will set the brightness to 100, erase the canvas, and draw the time. You don't even need the displayON variable. However, notice that I introduced the firstStart=true. As far as I can see firstStart is there so that if the time isn't changed, it won't redraw it, as that would be useless and use even more battery. Without setting firstStart true in handle_button_causing_wakeup() the screen would remain black when you wake up, and time would only be shown when the minute would change.

/**
*
* LED Number Clock
*  Displays time using LED graphics.
*
* Copyright (C) 2011, David Bates [email protected]
*
*   based on:
*
*   Binary/BCD clock
*
*   Read digits from top to bottom - hours/10, hours%10, mins/10, mins%10, secs/10, secs%10
*
*   Copyright (C) 2011, Duane Maxwell [email protected]
*
*   Permission to use, copy, modify, and/or distribute this software for
*   any purpose with or without fee is hereby granted, provided that the
*   above copyright notice and this permission notice appear in all copies.
*
*   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
*   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
*   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
*   BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
*   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
*   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
*   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
*   SOFTWARE.
**/

#include <pulse_os.h>
#include <pulse_types.h>
#include <stdint.h>

#define LED_SIZE 10
#define H_OFFSET 4
#define V_OFFSET 4
#define ROW_SIZE 4
#define COL_SIZE 5
#define HR_L_X_ORIGIN 0
#define HR_L_Y_ORIGIN 0
#define HR_R_X_ORIGIN 5
#define HR_R_Y_ORIGIN 0
#define MN_L_X_ORIGIN 0
#define MN_L_Y_ORIGIN 6
#define MN_R_X_ORIGIN 5
#define MN_R_Y_ORIGIN 6

bool firstStart=true;
bool displayON=true;

static int numMap[] = {
    1022367, 559240, 991119,  1019791, 561049,
    1019679, 1023761, 559247, 1023903, 561055
};

static color24_t offColors[] = {
{0x00,0x00,0x00,0x00},
{0x11,0x00,0x00,0x00},
{0x11,0x11,0x11,0x00},
{0x22,0x00,0x00,0x00},
{0x22,0x11,0x11,0x00},
{0x33,0x11,0x11,0x00},
{0x22,0x22,0x22,0x00},
{0x33,0x33,0x33,0x00},
{0x44,0x22,0x22,0x00},
{0x55,0x33,0x33,0x00},
{0x77,0x55,0x55,0x00},
{0xBB,0xBB,0xBB,0x00}
};

char offMap[] =
"AAAAAAAAAA"
"AAAAAAAAAA"
"AAAKDDBAAA"
"AAJDDDDAAA"
"AADDDDDAAA"
"AADDDDDAAA"
"AAADDDFAAA"
"AAABDFAAAA"
"AAAAAAAAAA"
"AAAAAAAAAA";

static color24_t onColors[] = {
{0x00,0x00,0x00,0x00},
{0x11,0x00,0x00,0x00},
{0x22,0x00,0x00,0x00},
{0x33,0x00,0x00,0x00},
{0x44,0x00,0x00,0x00},
{0x55,0x00,0x00,0x00},
{0x66,0x00,0x00,0x00},
{0x77,0x00,0x00,0x00},
{0x77,0x11,0x11,0x00},
{0x88,0x00,0x00,0x00},
{0xAA,0x00,0x00,0x00},
{0xBB,0x00,0x00,0x00},
{0x99,0x33,0x33,0x00},
{0xAA,0x22,0x22,0x00},
{0xCC,0x00,0x00,0x00},
{0xDD,0x00,0x00,0x00},
{0xEE,0x00,0x00,0x00},
{0xFF,0x00,0x00,0x00},
{0xFF,0x11,0x11,0x00},
{0xFF,0x22,0x22,0x00},
{0xEE,0x33,0x33,0x00},
{0xFF,0x55,0x55,0x00},
{0xEE,0xBB,0xBB,0x00}
};

char onMap[] =
"AAAAAAAAAA"
"AABCDDCBAA"
"AACEEEECAA"
"ACENPPGECA"
"ADGVRROGDA"
"ADGLRRJGDA"
"ACEGJJGECA"
"AACEEEECAA"
"AABCDDCAAA"
"AAAAAAAAAA";

/****************************************************************/
/*            Application drawing methods                       */
/****************************************************************/
void drawLED(int y,int x,int on) {
    int xx = (x*LED_SIZE)+H_OFFSET;
    int yy = (y*LED_SIZE)+V_OFFSET;
    pulse_set_draw_window(xx,yy,xx+LED_SIZE-1,yy+LED_SIZE-1);
    char *map = on ? onMap : offMap;
    color24_t *colors = on ? onColors : offColors;
    for (int i=0;i<LED_SIZE*LED_SIZE; i++) {
        pulse_draw_point24(colors[*map++-'A']);
    }
}

void drawNum(int originX, int originY, int num) {
    int mask=1;
    for(int i=0;i<=(ROW_SIZE*COL_SIZE)-1;i++) {
   drawLED((i/ROW_SIZE)+originY,(i%ROW_SIZE)+originX,numMap[num]&mask);
   mask=mask<<1;
    }
}

void drawTime(int hour, int min) {
    drawNum(HR_L_X_ORIGIN, HR_L_Y_ORIGIN, hour/10);
    drawNum(HR_R_X_ORIGIN, HR_R_Y_ORIGIN, hour%10);
    drawNum(MN_L_X_ORIGIN, MN_L_Y_ORIGIN, min/10);
    drawNum(MN_R_X_ORIGIN, MN_R_Y_ORIGIN, min%10);
}

void drawTimeGraphics() {
    struct pulse_time_tm tm;
    pulse_get_time_date(&tm);
    int hour = tm.tm_hour;

    if(hour>12) {
        hour-=12;
    }

    if(firstStart) {
        drawTime(hour, tm.tm_min);
        firstStart=false;
    }
    else {
        if(0==tm.tm_sec) {
            drawTime(hour, tm.tm_min);
         }
    }
}

void handle_button_causing_wakeup() {
    displayON=true;
    firstStart=true;
    pulse_oled_set_brightness(100);
    pulse_blank_canvas();
    drawTimeGraphics();
}

/****************************************************************/
/*                 Pulse SDK methods                            */
/****************************************************************/
void main_app_init() {
    pulse_blank_canvas();
    pulse_oled_set_brightness(100);
    pulse_register_callback(ACTION_WOKE_FROM_BUTTON, &handle_button_causing_wakeup);
}

void main_app_handle_button_down() {
        displayON=false;
        pulse_update_power_down_timer(100);
}

void main_app_handle_button_up() {
}

void main_app_loop() {
    drawTimeGraphics();
}

void main_app_handle_doz() {
    for (int i = 100; i >= 0; i-=6) {
        pulse_oled_set_brightness(i);
        pulse_mdelay(30);
    }
}

void main_app_handle_hardware_update(enum PulseHardwareEvent event) {
}


Offline
 Profile  
 
 Post subject: Re: LED Number Clock
PostPosted: Tue Mar 08, 2011 6:38 pm 

Joined: Fri Mar 04, 2011 3:53 pm
Posts: 3
Location: Seattle, WA
Oh I see, so the main_app_handle_button_* methods only run while the watch is in a non-sleep state. Then to have it do something from a sleep state you have to do it indirectly by registering a callback against the ACTION_WOKE_FROM_BUTTON event in pulse_register_callback method. Do I have that right?


Offline
 Profile  
 
 Post subject: Re: LED Number Clock
PostPosted: Tue Mar 08, 2011 7:53 pm 
User avatar

Joined: Tue Feb 15, 2011 10:35 pm
Posts: 7
Well you can't actually perform any functions while you are sleeping as that will mean the CPU is running which would defeat the point of power saving. By registering the callback against the ACTION_WOKE_FROM_BUTTON you basically tell the watch that when it is woken from a button press, it should go to that function you registered. I also believe that if you are to register two functions against the same action, then the second one would overwrite the first one.


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 5 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: