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 */ 29 typedef uint16_t lws_led_intensity_t; 30 typedef 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 42 struct lws_led_state; /* opaque */ 43 struct lws_pwm_ops; /* forward ref */ 44 45 typedef lws_led_intensity_t (*lws_led_lookup_t)(lws_led_seq_phase_t ph); 46 47 typedef 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 55 enum { 56 LLSI_CURR, 57 LLSI_NEXT, 58 LLSI_TRANS 59 }; 60 61 typedef 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 73 typedef 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 80 typedef 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 88 typedef 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 103 typedef 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 113 LWS_VISIBLE LWS_EXTERN struct lws_led_state * 114 lws_led_gpio_create(const lws_led_ops_t *led_ops); 115 116 LWS_VISIBLE LWS_EXTERN void 117 lws_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 */ 130 LWS_VISIBLE LWS_EXTERN void 131 lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name, 132 lws_led_intensity_t inten); 133 134 LWS_VISIBLE LWS_EXTERN int 135 lws_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