| 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 | |