1/*
2 * Generic LED controller ops
3 *
4 * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * This is like an abstract class for leds, a real implementation provides
25 * functions for the ops that use the underlying, eg, OS gpio arrangements.
26 */
27
28/* only b15 significant for GPIO */
29typedef uint16_t lws_led_intensity_t;
30typedef uint16_t lws_led_seq_phase_t;
31
32/* the normalized max intensity */
33#define LWS_LED_MAX_INTENSITY (0xffff)
34
35/* the normalized 360 degree phase count for intensity functions */
36#define LWS_LED_FUNC_PHASE 65536
37/* used when the sequence doesn't stop by itself and goes around forever */
38#define LWS_SEQ_LEDPHASE_TOTAL_ENDLESS (-1)
39
40#define LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS 33
41
42struct lws_led_state; /* opaque */
43struct lws_pwm_ops; /* forward ref */
44
45typedef lws_led_intensity_t (*lws_led_lookup_t)(lws_led_seq_phase_t ph);
46
47typedef struct lws_led_sequence_def_t {
48 lws_led_lookup_t func;
49 lws_led_seq_phase_t ledphase_offset;
50 int ledphase_total; /* 65536= one cycle */
51 uint16_t ms;
52 uint8_t flags;
53} lws_led_sequence_def_t;
54
55enum {
56 LLSI_CURR,
57 LLSI_NEXT,
58 LLSI_TRANS
59};
60
61typedef struct lws_led_state_ch
62{
63 const lws_led_sequence_def_t *seq; /* NULL = inactive */
64 lws_led_seq_phase_t ph;
65 lws_led_seq_phase_t step;
66 int phase_budget;
67 lws_led_intensity_t last;
68 /**< at the end of the sequence we decouple the sequencer, but leave
69 * the last computed sample behind for further transitions to base off
70 */
71} lws_led_state_ch_t;
72
73typedef struct lws_led_state_chs
74{
75 lws_led_state_ch_t seqs[3];
76} lws_led_state_chs_t;
77
78/* this should always be first in the subclassed implementation types */
79
80typedef struct lws_led_ops {
81 void (*intensity)(const struct lws_led_ops *lo, const char *name,
82 lws_led_intensity_t inten);
83 /**< for BOOL led control like GPIO, only inten b15 is significant */
84 struct lws_led_state * (*create)(const struct lws_led_ops *led_ops);
85 void (*destroy)(struct lws_led_state *);
86} lws_led_ops_t;
87
88typedef struct lws_led_gpio_map {
89 const char *name;
90 _lws_plat_gpio_t gpio;
91 lws_led_lookup_t intensity_correction;
92 /**< May be NULL. If GPIO-based LED, ignored. If pwm_ops provided,
93 * NULL means use default CIE 100% correction function. If non-NULL,
94 * use the pointed-to correction function. This is useful to provide
95 * LED-specific intensity correction / scaling so different types of
96 * LED can "look the same". */
97 const struct lws_pwm_ops *pwm_ops;
98 /**< if NULL, gpio controls the led directly. If set to a pwm_ops,
99 * the led control is outsourced to the pwm controller. */
100 uint8_t active_level;
101} lws_led_gpio_map_t;
102
103typedef struct lws_led_gpio_controller {
104 const lws_led_ops_t led_ops;
105
106 const lws_gpio_ops_t *gpio_ops;
107 const lws_led_gpio_map_t *led_map;
108 uint8_t count_leds;
109} lws_led_gpio_controller_t;
110
111/* ops */
112
113LWS_VISIBLE LWS_EXTERN struct lws_led_state *
114lws_led_gpio_create(const lws_led_ops_t *led_ops);
115
116LWS_VISIBLE LWS_EXTERN void
117lws_led_gpio_destroy(struct lws_led_state *lcs);
118
119/**
120 * lws_led_gpio_intensity() - set the static intensity of an led
121 *
122 * \param lo: the base class of the led controller
123 * \param index: which led in the controller set
124 * \param inten: 16-bit unsigned intensity
125 *
126 * For LEDs controlled by a BOOL like GPIO, only inten b15 is significant.
127 * For PWM type LED control, as many bits as the hardware can support from b15
128 * down are significant.
129 */
130LWS_VISIBLE LWS_EXTERN void
131lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name,
132 lws_led_intensity_t inten);
133
134LWS_VISIBLE LWS_EXTERN int
135lws_led_transition(struct lws_led_state *lcs, const char *name,
136 const lws_led_sequence_def_t *next,
137 const lws_led_sequence_def_t *trans);
138
139
140#define lws_led_gpio_ops \
141 { \
142 .create = lws_led_gpio_create, \
143 .destroy = lws_led_gpio_destroy, \
144 .intensity = lws_led_gpio_intensity, \
145 }
146
147