Future Electronics
/
sequana-rgb-led_summmit2019
LED driver.
main.cpp@8:edc0db715dda, 2019-03-22 (annotated)
- Committer:
- Seb_Sok
- Date:
- Fri Mar 22 13:23:42 2019 +0000
- Revision:
- 8:edc0db715dda
- Parent:
- 7:41cf0397d6ee
- Child:
- 9:de0cfb4301d5
rev. 1.5
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 | #define NUM_LEDS_LIGHTING 3 |
lru | 0:da2de84c3c04 | 114 | |
lru | 2:a83100cd9c9a | 115 | // Keeps indexes of LEDs that should be on in the next step. |
Seb_Sok | 3:b5cec57779aa | 116 | uint32_t led_index; |
Seb_Sok | 7:41cf0397d6ee | 117 | uint32_t dir_flag = 0; // Variable specifying the rotation direction of the leds |
Seb_Sok | 7:41cf0397d6ee | 118 | uint32_t button_was_pressed_counter = 0; |
Seb_Sok | 3:b5cec57779aa | 119 | |
lru | 2:a83100cd9c9a | 120 | // Current color. |
lru | 0:da2de84c3c04 | 121 | BGR24_color_t current_col[NUM_LEDS_LIGHTING]; |
lru | 0:da2de84c3c04 | 122 | |
Seb_Sok | 3:b5cec57779aa | 123 | // User button initialization |
Seb_Sok | 3:b5cec57779aa | 124 | DigitalIn UserButton(P0_4, PullUp); |
Seb_Sok | 3:b5cec57779aa | 125 | |
lru | 0:da2de84c3c04 | 126 | // main() runs in its own thread in the OS |
lru | 0:da2de84c3c04 | 127 | int main() { |
Seb_Sok | 3:b5cec57779aa | 128 | int color_step = 0, led_counter = 0; |
lru | 0:da2de84c3c04 | 129 | |
lru | 0:da2de84c3c04 | 130 | leds.set_dma_usage(DMA_USAGE_ALWAYS); |
lru | 0:da2de84c3c04 | 131 | |
Seb_Sok | 3:b5cec57779aa | 132 | // Infinite loop |
lru | 0:da2de84c3c04 | 133 | while (true) { |
Seb_Sok | 3:b5cec57779aa | 134 | |
Seb_Sok | 3:b5cec57779aa | 135 | // Checks if the button is pressed. |
Seb_Sok | 3:b5cec57779aa | 136 | if(UserButton == 0 && button_was_pressed_counter == 0) |
Seb_Sok | 3:b5cec57779aa | 137 | { |
Seb_Sok | 3:b5cec57779aa | 138 | // Changing the direction of rotation of the leds. |
Seb_Sok | 3:b5cec57779aa | 139 | // If dir_flag is 1 then rotate right otherwise rotate left. |
Seb_Sok | 3:b5cec57779aa | 140 | if(dir_flag == 1) dir_flag = 0; |
Seb_Sok | 3:b5cec57779aa | 141 | else dir_flag = 1; |
Seb_Sok | 3:b5cec57779aa | 142 | |
Seb_Sok | 3:b5cec57779aa | 143 | button_was_pressed_counter = 5; |
Seb_Sok | 3:b5cec57779aa | 144 | } |
Seb_Sok | 3:b5cec57779aa | 145 | |
Seb_Sok | 3:b5cec57779aa | 146 | // If the button was pressed wait for 400 ms (5 * 80 ms) to eliminate vibrations contacts. |
Seb_Sok | 3:b5cec57779aa | 147 | if(button_was_pressed_counter){ |
Seb_Sok | 3:b5cec57779aa | 148 | button_was_pressed_counter--; |
Seb_Sok | 3:b5cec57779aa | 149 | } |
Seb_Sok | 3:b5cec57779aa | 150 | |
lru | 2:a83100cd9c9a | 151 | // This defines phase relationship between rotating pattern |
lru | 2:a83100cd9c9a | 152 | // and color change. |
lru | 2:a83100cd9c9a | 153 | // As there are 8 steps for the whole circle (8 LEDs) |
lru | 2:a83100cd9c9a | 154 | // value of 6 means the color changes every 3/4 of rotation. |
Seb_Sok | 3:b5cec57779aa | 155 | if (++color_step == 6) { |
lru | 2:a83100cd9c9a | 156 | color_step = 0; |
lru | 2:a83100cd9c9a | 157 | current_col[2] = gen_color(); |
Seb_Sok | 3:b5cec57779aa | 158 | current_col[1] = dim(current_col[2], 25); |
Seb_Sok | 3:b5cec57779aa | 159 | current_col[0] = dim(current_col[2], 5); |
lru | 2:a83100cd9c9a | 160 | } |
lru | 2:a83100cd9c9a | 161 | |
lru | 2:a83100cd9c9a | 162 | // Set up lighting pattern for current step. |
Seb_Sok | 3:b5cec57779aa | 163 | for (int i = 0; i < NUM_LEDS_LIGHTING; i++) { |
Seb_Sok | 3:b5cec57779aa | 164 | |
Seb_Sok | 3:b5cec57779aa | 165 | if(led_counter + i > 7) led_index = led_counter + i - 8; |
Seb_Sok | 3:b5cec57779aa | 166 | else led_index = led_counter + i; |
Seb_Sok | 3:b5cec57779aa | 167 | |
Seb_Sok | 4:59c5b7dee5bc | 168 | // The function is used to set the direction of the "tail". |
Seb_Sok | 5:b84ce6bea4ac | 169 | leds.set_color(led_index, current_col[i]); |
Seb_Sok | 4:59c5b7dee5bc | 170 | |
lru | 0:da2de84c3c04 | 171 | } |
Seb_Sok | 3:b5cec57779aa | 172 | |
Seb_Sok | 3:b5cec57779aa | 173 | // Turn off / turn on all the buffer of leds prepared above. |
lru | 0:da2de84c3c04 | 174 | leds.refresh(); |
lru | 0:da2de84c3c04 | 175 | |
Seb_Sok | 3:b5cec57779aa | 176 | // Do nothing for 80 ms |
Seb_Sok | 3:b5cec57779aa | 177 | wait_ms(80); |
Seb_Sok | 3:b5cec57779aa | 178 | |
Seb_Sok | 6:44851bff34a4 | 179 | // This function is used to set the direction of rotation of the leds |
Seb_Sok | 3:b5cec57779aa | 180 | if(UserButton){ |
Seb_Sok | 7:41cf0397d6ee | 181 | if(++led_counter > 7) led_counter = 0; // Left spin |
Seb_Sok | 7:41cf0397d6ee | 182 | } |
Seb_Sok | 4:59c5b7dee5bc | 183 | |
Seb_Sok | 3:b5cec57779aa | 184 | |
Seb_Sok | 3:b5cec57779aa | 185 | // Turn off all LEDs, so we have a dark frame buffer again. |
lru | 2:a83100cd9c9a | 186 | // Must be done after delay, as with DMA refresh() operation |
lru | 2:a83100cd9c9a | 187 | // only starts LEDs updating from the frame buffer. |
Seb_Sok | 3:b5cec57779aa | 188 | for (int i = 0; i < 8; i++) { |
Seb_Sok | 3:b5cec57779aa | 189 | leds.set_color(i, BGR24_color_t(0,0,0)); |
Seb_Sok | 3:b5cec57779aa | 190 | } |
Seb_Sok | 3:b5cec57779aa | 191 | |
lru | 0:da2de84c3c04 | 192 | |
lru | 0:da2de84c3c04 | 193 | } |
Seb_Sok | 3:b5cec57779aa | 194 | |
lru | 0:da2de84c3c04 | 195 | } |