summaryrefslogtreecommitdiff
path: root/apps/plugins/clicker.c
blob: 196faf223e05106c63a405a826fcebbd174df934 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "plugin.h"
#include "lib/pluginlib_actions.h"
#include "lib/pluginlib_exit.h"

#define MAX_DIGITS 128

/* data is stored like this:
   units: data[0] &0xF;
   10s:   data[0] >> 4;
   100s:  data[1] &0xF;
   100s:  data[1] >> 4;
   etc.
*/
/* 0xF in a nibble indicates no digit */
unsigned char count_data[MAX_DIGITS/2];

/* this plugin is really the epitome of overkill :D */
unsigned char read_digit(int idx)
{
    if(idx%2)
        return count_data[idx/2] >> 4;
    else
        return count_data[idx/2] &0xF;
}

void write_digit(int idx, unsigned char val)
{
    unsigned char raw=count_data[idx/2];
    if(idx%2)
    {
        /* isolate the LOW half because we're changing the HIGH half */
        raw &= 0x0F;
        raw |= val << 4;
    }
    else
    {
        raw &= 0xF0;
        raw |= val;
    }
    count_data[idx/2]=raw;
}

void increment(void)
{
    int units_digit=read_digit(0)+1;
    if(units_digit<10)
    {
        write_digit(0, units_digit);
        return;
    }
    /* there's been a carry in the units place */
    int carry=1;
    write_digit(0, 0);
    for(int i=1;i<MAX_DIGITS && carry;++i)
    {
        int read_value=read_digit(i);
        if(read_value==0xF)
            read_value=0;
        int digit=read_value + carry;
        if(digit<10)
        {
            carry=0;
        }
        else
        {
            carry=1;
            digit=0;
        }
        write_digit(i, digit);
    }
}

void draw(void)
{
    rb->lcd_clear_display();
    int next_x=0;
    for(int i=MAX_DIGITS-1;i>=0;--i)
    {
        int digit=read_digit(i);
        if(digit!=0xF)
        {
            rb->lcd_putsf(next_x, 0, "%d", digit);
            next_x++;
        }
    }
}

enum plugin_status plugin_start(const void* param){
    (void)param;
    rb->memset(count_data, 0xFF, sizeof(count_data));
    write_digit(0, 0);
    draw();
    rb->lcd_update();
    const struct button_mapping *ctxs[]={pla_main_ctx};
    int run=1;
    int f=0;

    while (run == 1) {
        int btn;
        switch (btn=pluginlib_getaction(-1,ctxs,1))
        {
        case PLA_SELECT:
            if (f != 1) {
                increment();
                draw();
                rb->lcd_update();
                f=1;
            }
            break;
        case PLA_EXIT:
        case PLA_CANCEL:
            run=0;
            break;
        default :
            f=0;
            exit_on_usb(btn);
            break;
        }
    }
    return PLUGIN_OK;
}