~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to ToyKeeper/Ferrero_Rocher/level_calc.py

  • Committer: Selene Scriven
  • Date: 2015-03-17 08:56:50 UTC
  • mto: This revision was merged to the branch mainline in revision 124.
  • Revision ID: ubuntu@toykeeper.net-20150317085650-s89wr9h28n2co7z1
Added TheStar firmwares from _the_

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
import math
4
4
 
5
 
interactive = False
6
 
 
7
5
def main(args):
8
6
    """Calculates PWM levels for visually-linear steps.
9
7
    """
10
 
    # Get parameters from the user
11
 
    v = dict(pwm_max=255, pwm2_max=255)
12
 
    questions = [
13
 
            (int, 'num_levels', 4, 'How many total levels do you want?'),
14
 
            (int, 'pwm_min', 6, 'Lowest visible PWM level, for moon mode:'),
15
 
            (float, 'lm_min', 0.25, 'How bright is moon mode, in lumens?'),
16
 
            #(int, 'pwm_max', 255, 'Highest PWM level:'),
17
 
            (float, 'lm_max', 1000, 'How bright is the highest level, in lumens?'),
18
 
            (str, 'dual_pwm', 'n', 'Use dual PWM? [y/n]'),
19
 
            (float, 'pwm2_min', 6, 'Second channel, lowest visible PWM level:'),
20
 
            (float, 'lm2_min', 0.25, 'Second channel, how bright is the lowest mode, in lumens?'),
21
 
            #(float, 'pwm2_max', 255, 'Second channel, highest PWM level:'),
22
 
            (float, 'lm2_max', 140, 'Second channel, how bright is maximum, in lumens?'),
23
 
            ]
24
 
    for typ, name, default, text in questions:
25
 
        value = get_value(text, default, args)
26
 
        if not value:
27
 
            value = default
28
 
        else:
29
 
            value = typ(value)
30
 
        v[name] = value
31
 
        if (name == 'dual_pwm'  and  value == 'n'):
32
 
            # skip remaining questions if not using dual PWM
33
 
            break
34
 
 
35
 
    if v['dual_pwm'] == 'y':
36
 
        dual_pwm(v)
37
 
    else:
38
 
        single_pwm(v)
39
 
 
40
 
    if interactive: # Wait on exit, in case user invoked us by clicking an icon
41
 
        print 'Press Enter to exit:'
42
 
        raw_input()
43
 
 
44
 
def single_pwm(v):
45
 
    """Estimate the PWM levels for a one-channel driver."""
46
 
    visual_min = invpower(v['lm_min'])
47
 
    visual_max = invpower(v['lm_max'])
48
 
    step_size = (visual_max - visual_min) / (v['num_levels']-1)
 
8
    # change these values for each device:
 
9
    pwm_min = 0     # lowest visible PWM level, for moon mode
 
10
    lm_min = 10.0   # how bright is moon mode, in lumens?
 
11
    pwm_max = 255   # highest PWM level
 
12
    lm_max = 1300   # how bright is the highest level, in lumens?
 
13
    num_levels = 4  # how many total levels do you want?
 
14
    # The rest should work fine without changes
 
15
    visual_min = math.pow(lm_min, 1.0/3)
 
16
    visual_max = math.pow(lm_max, 1.0/3)
 
17
    step_size = (visual_max - visual_min) / (num_levels-1)
49
18
    modes = []
50
19
    goal = visual_min
51
 
    for i in range(v['num_levels']):
52
 
        goal_lm = power(goal)
53
 
        #pwm_float = ((goal_lm / v['lm_max']) * (256-v['pwm_min'])) + v['pwm_min'] - 1
54
 
        pwm_float = (((goal_lm-v['lm_min']) / (v['lm_max']-v['lm_min'])) \
55
 
                        * (255-v['pwm_min'])) \
56
 
                    + v['pwm_min']
 
20
    for i in range(num_levels):
 
21
        pwm_float = (((goal**3) / lm_max) * (256-pwm_min)) + pwm_min - 1
57
22
        pwm = int(round(pwm_float))
58
 
        pwm = max(min(pwm,v['pwm_max']),v['pwm_min'])
 
23
        pwm = max(min(pwm,pwm_max),pwm_min)
59
24
        modes.append(pwm)
60
 
        print '%i: visually %.2f (%.2f lm): %.2f/255' % (i+1, goal, goal_lm, pwm_float)
61
 
        goal += step_size
62
 
 
63
 
    print 'PWM values:', ','.join([str(i) for i in modes])
64
 
 
65
 
def dual_pwm(v):
66
 
    """Estimate the PWM levels for a two-channel driver.
67
 
    Assume the first channel is the brighter one, and second will be used for moon/low modes.
68
 
    """
69
 
    #visual_min = math.pow(v['lm2_min'], 1.0/power)
70
 
    #visual_max = math.pow(v['lm_max'], 1.0/power)
71
 
    visual_min = invpower(v['lm2_min'])
72
 
    visual_max = invpower(v['lm_max'])
73
 
    step_size = (visual_max - visual_min) / (v['num_levels']-1)
74
 
    modes = []
75
 
    goal = visual_min
76
 
    for i in range(v['num_levels']):
77
 
        goal_lm = power(goal)
78
 
        # Up to the second channel's limit, calculate things just like a 
79
 
        # single-channel driver (first channel will be zero)
80
 
        if goal_lm <= v['lm2_max']:
81
 
            pwm1_float = 0.0
82
 
            #pwm2_float = ((goal_lm / v['lm2_max']) * (256-v['pwm2_min'])) + v['pwm2_min'] - 1
83
 
            pwm2_float = (((goal_lm-v['lm2_min']) / (v['lm2_max']-v['lm2_min'])) \
84
 
                             * (255-v['pwm2_min'])) \
85
 
                         + v['pwm2_min']
86
 
            pwm1 = int(round(pwm1_float))
87
 
            pwm2 = int(round(pwm2_float))
88
 
            pwm2 = max(min(pwm2,v['pwm2_max']),v['pwm2_min'])
89
 
            modes.append((int(pwm1),int(pwm2)))
90
 
        # Above the second channel's limit, things get a little more 
91
 
        # complicated (second channel will be 255, first channel will be 
92
 
        # adjusted down by the max output of the second channel)
93
 
        else:
94
 
            if len(modes) == v['num_levels'] -1: # turbo is special
95
 
                #pwm1_float = ((goal_lm / v['lm_max']) * (256-v['pwm_min'])) + v['pwm_min'] - 1
96
 
                pwm1_float = float(v['pwm_max'])
97
 
                # on a FET+7135 driver, turbo works better without the 7135
98
 
                # (we're assuming FET+7135 here)
99
 
                pwm2_float = 0.0
100
 
            else: # not the highest mode yet
101
 
                #pwm1_float = (((goal_lm-v['lm2_max']) / v['lm_max']) * (256-v['pwm_min'])) + v['pwm_min'] - 1
102
 
                pwm1_float = (((goal_lm-v['lm_min']-v['lm2_max']) / (v['lm_max']-v['lm_min'])) \
103
 
                                 * (255-v['pwm_min'])) \
104
 
                             + v['pwm_min']
105
 
                pwm2_float = 255.0
106
 
            pwm1 = int(round(pwm1_float))
107
 
            pwm2 = int(round(pwm2_float))
108
 
            pwm1 = max(min(pwm1,v['pwm_max']),v['pwm_min'])
109
 
            modes.append((int(pwm1),int(pwm2)))
110
 
        print '%i: visually %.2f (%.2f lm): %.2f/255, %.2f/255' % (i+1, goal, goal_lm, pwm1_float, pwm2_float)
111
 
        goal += step_size
112
 
 
113
 
    print 'PWM1/FET  values:', ','.join([str(i[0]) for i in modes])
114
 
    print 'PWM2/7135 values:', ','.join([str(i[1]) for i in modes])
115
 
    print 'On a non-FET driver, the last mode should be 255 on both channels.'
116
 
 
117
 
def get_value(text, default, args):
118
 
    """Get input from the user, or from the command line args."""
119
 
    if args:
120
 
        result = args[0]
121
 
        del args[0]
122
 
    else:
123
 
        global interactive
124
 
        interactive = True
125
 
        print text, '(%s)' % (default),
126
 
        result = raw_input()
127
 
    result = result.strip()
128
 
    return result
129
 
 
130
 
def power(x):
131
 
    #return x**5
132
 
    return x**3
133
 
    #return x**2
134
 
    #return math.e**x
135
 
    #return 2.0**x
136
 
 
137
 
def invpower(x):
138
 
    #return math.pow(x, 1/5.0)
139
 
    return math.pow(x, 1/3.0)
140
 
    #return math.pow(x, 1/2.0)
141
 
    #return math.log(x, math.e)
142
 
    #return math.log(x, 2.0)
 
25
        print '%i: visually %.2f (%.2f lm): %.2f/255' % (i+1, goal, goal ** 3, pwm_float)
 
26
        goal += step_size
 
27
 
 
28
    print ','.join([str(i) for i in modes])
143
29
 
144
30
if __name__ == "__main__":
145
31
    import sys