Future Electronics
/
sequana-rgb-led-example
Example program to blink RGB LEDs on Sequana board in a rotating pattern.
main.cpp@2:a83100cd9c9a, 2019-03-04 (annotated)
- Committer:
- lru
- Date:
- Mon Mar 04 14:15:06 2019 +0000
- Revision:
- 2:a83100cd9c9a
- Parent:
- 0:da2de84c3c04
Updated color selection algorithm
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lru | 0:da2de84c3c04 | 1 | /* |
lru | 0:da2de84c3c04 | 2 | * Mbed OS example program for Future Electronics Sequana board. |
lru | 0:da2de84c3c04 | 3 | * |
lru | 0:da2de84c3c04 | 4 | * Copyright (c) 2018 Future Electronics |
lru | 0:da2de84c3c04 | 5 | * |
lru | 0:da2de84c3c04 | 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
lru | 0:da2de84c3c04 | 7 | * you may not use this file except in compliance with the License. |
lru | 0:da2de84c3c04 | 8 | * You may obtain a copy of the License at |
lru | 0:da2de84c3c04 | 9 | * |
lru | 0:da2de84c3c04 | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
lru | 0:da2de84c3c04 | 11 | * |
lru | 0:da2de84c3c04 | 12 | * Unless required by applicable law or agreed to in writing, software |
lru | 0:da2de84c3c04 | 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
lru | 0:da2de84c3c04 | 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
lru | 0:da2de84c3c04 | 15 | * See the License for the specific language governing permissions and |
lru | 0:da2de84c3c04 | 16 | * limitations under the License. |
lru | 0:da2de84c3c04 | 17 | */ |
lru | 0:da2de84c3c04 | 18 | |
lru | 0:da2de84c3c04 | 19 | // This example demonstrates used of ROHM BD2808 24-channel LED Controller |
lru | 0:da2de84c3c04 | 20 | // and its driver library on Sequana board. |
lru | 0:da2de84c3c04 | 21 | |
lru | 0:da2de84c3c04 | 22 | #include "mbed.h" |
lru | 0:da2de84c3c04 | 23 | #include "BD2808.h" |
lru | 0:da2de84c3c04 | 24 | |
lru | 0:da2de84c3c04 | 25 | BD2808 leds; |
lru | 0:da2de84c3c04 | 26 | |
lru | 2:a83100cd9c9a | 27 | // Return new color value by dimming the current color to x% |
lru | 0:da2de84c3c04 | 28 | BGR24_color_t dim(BGR24_color_t color, uint8_t percent) |
lru | 0:da2de84c3c04 | 29 | { |
lru | 0:da2de84c3c04 | 30 | BGR24_color_t new_color; |
lru | 0:da2de84c3c04 | 31 | |
lru | 0:da2de84c3c04 | 32 | new_color.r = color.r * percent / 100; |
lru | 0:da2de84c3c04 | 33 | new_color.g = color.g * percent / 100; |
lru | 0:da2de84c3c04 | 34 | new_color.b = color.b * percent / 100; |
lru | 0:da2de84c3c04 | 35 | |
lru | 0:da2de84c3c04 | 36 | return new_color; |
lru | 0:da2de84c3c04 | 37 | } |
lru | 0:da2de84c3c04 | 38 | |
lru | 0:da2de84c3c04 | 39 | #define sat(x) (uint8_t)((x) > 255? 255 : (x) < 0? 0 : (x)) |
lru | 0:da2de84c3c04 | 40 | |
lru | 2:a83100cd9c9a | 41 | // This function generates color sequence. Each call to this function |
lru | 2:a83100cd9c9a | 42 | // returns the next color in a sequence. |
lru | 2:a83100cd9c9a | 43 | // Color sequence generation algorithm is such, that it provides |
lru | 2:a83100cd9c9a | 44 | // smooth color swipe, keeping intensity roughly the same. |
lru | 0:da2de84c3c04 | 45 | BGR24_color_t gen_color() |
lru | 0:da2de84c3c04 | 46 | { |
lru | 2:a83100cd9c9a | 47 | const uint8_t step = 40; |
lru | 0:da2de84c3c04 | 48 | const uint8_t max = 200; |
lru | 2:a83100cd9c9a | 49 | static uint32_t phase = 0; |
lru | 0:da2de84c3c04 | 50 | static int32_t r = max; |
lru | 0:da2de84c3c04 | 51 | static int32_t g = max; |
lru | 0:da2de84c3c04 | 52 | static int32_t b = 0; |
lru | 2:a83100cd9c9a | 53 | static int32_t base_level = 6; |
lru | 0:da2de84c3c04 | 54 | |
lru | 2:a83100cd9c9a | 55 | #define step_up(x) do { if ((x += step) > max) x = max; } while(0) |
lru | 2:a83100cd9c9a | 56 | #define step_down(x, v) do { x -= step; if (x < v) x = v;} while (0) |
lru | 0:da2de84c3c04 | 57 | |
lru | 2:a83100cd9c9a | 58 | switch (phase) { |
lru | 2:a83100cd9c9a | 59 | case 0: |
lru | 2:a83100cd9c9a | 60 | // swiping from reddish into blueish |
lru | 2:a83100cd9c9a | 61 | step_down(r, 0); |
lru | 2:a83100cd9c9a | 62 | g = base_level; |
lru | 2:a83100cd9c9a | 63 | step_up(b); |
lru | 2:a83100cd9c9a | 64 | if (r == 0) phase++; |
lru | 2:a83100cd9c9a | 65 | break; |
lru | 2:a83100cd9c9a | 66 | case 1: |
lru | 2:a83100cd9c9a | 67 | // swiping from blueish into greenish to level off blue |
lru | 2:a83100cd9c9a | 68 | r = 0; |
lru | 2:a83100cd9c9a | 69 | step_up(g); |
lru | 2:a83100cd9c9a | 70 | step_down(b, base_level); |
lru | 2:a83100cd9c9a | 71 | if (b == base_level) phase++; |
lru | 2:a83100cd9c9a | 72 | break; |
lru | 2:a83100cd9c9a | 73 | case 2: |
lru | 2:a83100cd9c9a | 74 | // swiping from greenish into reddish |
lru | 2:a83100cd9c9a | 75 | step_up(r); |
lru | 2:a83100cd9c9a | 76 | step_down(g, 0); |
lru | 2:a83100cd9c9a | 77 | b = base_level; |
lru | 2:a83100cd9c9a | 78 | if (g == 0) phase++; |
lru | 2:a83100cd9c9a | 79 | break; |
lru | 2:a83100cd9c9a | 80 | case 3: |
lru | 2:a83100cd9c9a | 81 | // swiping from reddish into blueish to level off red |
lru | 2:a83100cd9c9a | 82 | step_down(r, base_level); |
lru | 2:a83100cd9c9a | 83 | g = 0; |
lru | 2:a83100cd9c9a | 84 | step_up(b); |
lru | 2:a83100cd9c9a | 85 | if (r == base_level) phase++; |
lru | 2:a83100cd9c9a | 86 | break; |
lru | 2:a83100cd9c9a | 87 | case 4: |
lru | 2:a83100cd9c9a | 88 | // swiping from blueish into greenish |
lru | 2:a83100cd9c9a | 89 | r = base_level; |
lru | 2:a83100cd9c9a | 90 | step_up(g); |
lru | 2:a83100cd9c9a | 91 | step_down(b, 0); |
lru | 2:a83100cd9c9a | 92 | if (b == 0) phase++; |
lru | 2:a83100cd9c9a | 93 | break; |
lru | 2:a83100cd9c9a | 94 | case 5: |
lru | 2:a83100cd9c9a | 95 | // swiping from greenish into reddish to level off green |
lru | 2:a83100cd9c9a | 96 | step_up(r); |
lru | 2:a83100cd9c9a | 97 | step_down(g, base_level); |
lru | 2:a83100cd9c9a | 98 | b = 0; |
lru | 2:a83100cd9c9a | 99 | if (g == base_level) { |
lru | 2:a83100cd9c9a | 100 | phase = 0; |
lru | 2:a83100cd9c9a | 101 | base_level *= 2; |
lru | 2:a83100cd9c9a | 102 | if (base_level > 200) { |
lru | 2:a83100cd9c9a | 103 | base_level = 6; |
lru | 2:a83100cd9c9a | 104 | } |
lru | 2:a83100cd9c9a | 105 | g = base_level; |
lru | 0:da2de84c3c04 | 106 | } |
lru | 2:a83100cd9c9a | 107 | break; |
lru | 0:da2de84c3c04 | 108 | } |
lru | 0:da2de84c3c04 | 109 | |
lru | 0:da2de84c3c04 | 110 | return BGR24_color_t(sat(b), sat(g), sat(r)); |
lru | 0:da2de84c3c04 | 111 | } |
lru | 0:da2de84c3c04 | 112 | |
lru | 0:da2de84c3c04 | 113 | |
lru | 0:da2de84c3c04 | 114 | #define NUM_LEDS_LIGHTING 3 |
lru | 0:da2de84c3c04 | 115 | |
lru | 2:a83100cd9c9a | 116 | // Keeps indexes of LEDs that should be on in the next step. |
lru | 0:da2de84c3c04 | 117 | uint32_t led_index[NUM_LEDS_LIGHTING] = {0, 1, 2}; |
lru | 2:a83100cd9c9a | 118 | // Current color. |
lru | 0:da2de84c3c04 | 119 | BGR24_color_t current_col[NUM_LEDS_LIGHTING]; |
lru | 0:da2de84c3c04 | 120 | |
lru | 0:da2de84c3c04 | 121 | // main() runs in its own thread in the OS |
lru | 0:da2de84c3c04 | 122 | int main() { |
lru | 2:a83100cd9c9a | 123 | int color_step = 0; |
lru | 0:da2de84c3c04 | 124 | |
lru | 0:da2de84c3c04 | 125 | leds.set_dma_usage(DMA_USAGE_ALWAYS); |
lru | 0:da2de84c3c04 | 126 | |
lru | 0:da2de84c3c04 | 127 | while (true) { |
lru | 2:a83100cd9c9a | 128 | // This defines phase relationship between rotating pattern |
lru | 2:a83100cd9c9a | 129 | // and color change. |
lru | 2:a83100cd9c9a | 130 | // As there are 8 steps for the whole circle (8 LEDs) |
lru | 2:a83100cd9c9a | 131 | // value of 6 means the color changes every 3/4 of rotation. |
lru | 2:a83100cd9c9a | 132 | if (++color_step == 6) { |
lru | 2:a83100cd9c9a | 133 | color_step = 0; |
lru | 2:a83100cd9c9a | 134 | current_col[2] = gen_color(); |
lru | 2:a83100cd9c9a | 135 | current_col[1] = dim(current_col[2], 50); |
lru | 2:a83100cd9c9a | 136 | current_col[0] = dim(current_col[2], 10); |
lru | 2:a83100cd9c9a | 137 | } |
lru | 2:a83100cd9c9a | 138 | |
lru | 2:a83100cd9c9a | 139 | // Set up lighting pattern for current step. |
lru | 0:da2de84c3c04 | 140 | for (int i = 0; i < NUM_LEDS_LIGHTING; ++i) { |
lru | 0:da2de84c3c04 | 141 | leds.set_color(led_index[i], current_col[i]); |
lru | 0:da2de84c3c04 | 142 | } |
lru | 0:da2de84c3c04 | 143 | leds.refresh(); |
lru | 0:da2de84c3c04 | 144 | |
lru | 0:da2de84c3c04 | 145 | wait_ms(50); |
lru | 2:a83100cd9c9a | 146 | // Turn off set LEDs, so we have a dark frame buffer again. |
lru | 2:a83100cd9c9a | 147 | // Must be done after delay, as with DMA refresh() operation |
lru | 2:a83100cd9c9a | 148 | // only starts LEDs updating from the frame buffer. |
lru | 0:da2de84c3c04 | 149 | leds.set_color(led_index[0], BGR24_color_t(0,0,0)); |
lru | 0:da2de84c3c04 | 150 | |
lru | 2:a83100cd9c9a | 151 | // Update lighting LED indexes for the next step. |
lru | 0:da2de84c3c04 | 152 | for (int i = 0; i < NUM_LEDS_LIGHTING; ++i) { |
lru | 0:da2de84c3c04 | 153 | if (++led_index[i] == 8) led_index[i] = 0; |
lru | 0:da2de84c3c04 | 154 | } |
lru | 0:da2de84c3c04 | 155 | } |
lru | 0:da2de84c3c04 | 156 | } |