diff options
Diffstat (limited to 'drivers/avr/apa102.c')
| -rw-r--r--[-rwxr-xr-x] | drivers/avr/apa102.c | 147 |
1 files changed, 71 insertions, 76 deletions
diff --git a/drivers/avr/apa102.c b/drivers/avr/apa102.c index 55a0d5777..f4d97a158 100755..100644 --- a/drivers/avr/apa102.c +++ b/drivers/avr/apa102.c | |||
| @@ -1,24 +1,24 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * APA102 lib V1.0a | 2 | * APA102 lib V1.0a |
| 3 | * | 3 | * |
| 4 | * Controls APA102 RGB-LEDs | 4 | * Controls APA102 RGB-LEDs |
| 5 | * Author: Mikkel (Duckle29 on github) | 5 | * Author: Mikkel (Duckle29 on github) |
| 6 | * | 6 | * |
| 7 | * Dec 22th, 2017 v1.0a Initial Version | 7 | * Dec 22th, 2017 v1.0a Initial Version |
| 8 | * | 8 | * |
| 9 | * This program is free software: you can redistribute it and/or modify | 9 | * This program is free software: you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
| 11 | * the Free Software Foundation, either version 2 of the License, or | 11 | * the Free Software Foundation, either version 2 of the License, or |
| 12 | * (at your option) any later version. | 12 | * (at your option) any later version. |
| 13 | * | 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, | 14 | * This program is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | * GNU General Public License for more details. | 17 | * GNU General Public License for more details. |
| 18 | * | 18 | * |
| 19 | * You should have received a copy of the GNU General Public License | 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include "apa102.h" | 23 | #include "apa102.h" |
| 24 | #include <avr/interrupt.h> | 24 | #include <avr/interrupt.h> |
| @@ -27,75 +27,70 @@ | |||
| 27 | #include "debug.h" | 27 | #include "debug.h" |
| 28 | 28 | ||
| 29 | // Setleds for standard RGB | 29 | // Setleds for standard RGB |
| 30 | void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds){ | 30 | void inline apa102_setleds(LED_TYPE *ledarray, uint16_t leds) { apa102_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF)); } |
| 31 | apa102_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF), _BV(RGB_CLK_PIN & 0xF)); | ||
| 32 | } | ||
| 33 | 31 | ||
| 34 | void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK){ | 32 | void static inline apa102_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask_DI, uint8_t pinmask_CLK) { |
| 35 | pinMode(RGB_DI_PIN, PinDirectionOutput); | 33 | pinMode(RGB_DI_PIN, PinDirectionOutput); |
| 36 | pinMode(RGB_CLK_PIN, PinDirectionOutput); | 34 | pinMode(RGB_CLK_PIN, PinDirectionOutput); |
| 37 | 35 | ||
| 38 | apa102_send_array((uint8_t*)ledarray,leds) | 36 | apa102_send_array((uint8_t *)ledarray, leds) |
| 39 | } | 37 | } |
| 40 | 38 | ||
| 41 | void apa102_send_array(uint8_t *data, uint16_t leds){ // Data is struct of 3 bytes. RGB - leds is number of leds in data | 39 | void apa102_send_array(uint8_t *data, uint16_t leds) { // Data is struct of 3 bytes. RGB - leds is number of leds in data |
| 42 | apa102_start_frame(); | 40 | apa102_start_frame(); |
| 43 | while(leds--){ | 41 | while (leds--) { |
| 44 | apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r); | 42 | apa102_send_frame(0xFF000000 | (data->b << 16) | (data->g << 8) | data->r); |
| 45 | data++; | 43 | data++; |
| 46 | } | 44 | } |
| 47 | apa102_end_frame(leds); | 45 | apa102_end_frame(leds); |
| 48 | } | 46 | } |
| 49 | 47 | ||
| 50 | void apa102_send_frame(uint32_t frame){ | 48 | void apa102_send_frame(uint32_t frame) { |
| 51 | for(uint32_t i=0xFF; i>0;){ | 49 | for (uint32_t i = 0xFF; i > 0;) { |
| 52 | apa102_send_byte(frame & i); | 50 | apa102_send_byte(frame & i); |
| 53 | i = i << 8; | 51 | i = i << 8; |
| 54 | } | 52 | } |
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | void apa102_start_frame(){ | 55 | void apa102_start_frame() { apa102_send_frame(0); } |
| 58 | apa102_send_frame(0); | ||
| 59 | } | ||
| 60 | 56 | ||
| 61 | void apa102_end_frame(uint16_t leds) | 57 | void apa102_end_frame(uint16_t leds) { |
| 62 | { | 58 | // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h |
| 63 | // This function has been taken from: https://github.com/pololu/apa102-arduino/blob/master/APA102.h | 59 | // and adapted. The code is MIT licensed. I think thats compatible? |
| 64 | // and adapted. The code is MIT licensed. I think thats compatible? | ||
| 65 | 60 | ||
| 66 | // We need to send some more bytes to ensure that all the LEDs in the | 61 | // We need to send some more bytes to ensure that all the LEDs in the |
| 67 | // chain see their new color and start displaying it. | 62 | // chain see their new color and start displaying it. |
| 68 | // | 63 | // |
| 69 | // The data stream seen by the last LED in the chain will be delayed by | 64 | // The data stream seen by the last LED in the chain will be delayed by |
| 70 | // (count - 1) clock edges, because each LED before it inverts the clock | 65 | // (count - 1) clock edges, because each LED before it inverts the clock |
| 71 | // line and delays the data by one clock edge. Therefore, to make sure | 66 | // line and delays the data by one clock edge. Therefore, to make sure |
| 72 | // the last LED actually receives the data we wrote, the number of extra | 67 | // the last LED actually receives the data we wrote, the number of extra |
| 73 | // edges we send at the end of the frame must be at least (count - 1). | 68 | // edges we send at the end of the frame must be at least (count - 1). |
| 74 | // For the APA102C, that is sufficient. | 69 | // For the APA102C, that is sufficient. |
| 75 | // | 70 | // |
| 76 | // The SK9822 only updates after it sees 32 zero bits followed by one more | 71 | // The SK9822 only updates after it sees 32 zero bits followed by one more |
| 77 | // rising edge. To avoid having the update time depend on the color of | 72 | // rising edge. To avoid having the update time depend on the color of |
| 78 | // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means | 73 | // the last LED, we send a dummy 0xFF byte. (Unfortunately, this means |
| 79 | // that partial updates of the beginning of an LED strip are not possible; | 74 | // that partial updates of the beginning of an LED strip are not possible; |
| 80 | // the LED after the last one you are trying to update will be black.) | 75 | // the LED after the last one you are trying to update will be black.) |
| 81 | // After that, to ensure that the last LED in the chain sees 32 zero bits | 76 | // After that, to ensure that the last LED in the chain sees 32 zero bits |
| 82 | // and a rising edge, we need to send at least 65 + (count - 1) edges. It | 77 | // and a rising edge, we need to send at least 65 + (count - 1) edges. It |
| 83 | // is sufficent and simpler to just send (5 + count/16) bytes of zeros. | 78 | // is sufficent and simpler to just send (5 + count/16) bytes of zeros. |
| 84 | // | 79 | // |
| 85 | // We are ignoring the specification for the end frame in the APA102/SK9822 | 80 | // We are ignoring the specification for the end frame in the APA102/SK9822 |
| 86 | // datasheets because it does not actually ensure that all the LEDs will | 81 | // datasheets because it does not actually ensure that all the LEDs will |
| 87 | // start displaying their new colors right away. | 82 | // start displaying their new colors right away. |
| 88 | 83 | ||
| 89 | apa102_send_byte(0xFF); | 84 | apa102_send_byte(0xFF); |
| 90 | for (uint16_t i = 0; i < 5 + leds / 16; i++){ | 85 | for (uint16_t i = 0; i < 5 + leds / 16; i++) { |
| 91 | apa102_send_byte(0); | 86 | apa102_send_byte(0); |
| 92 | } | 87 | } |
| 93 | } | 88 | } |
| 94 | 89 | ||
| 95 | void apa102_send_byte(uint8_t byte){ | 90 | void apa102_send_byte(uint8_t byte) { |
| 96 | uint8_t i; | 91 | uint8_t i; |
| 97 | for (i = 0; i < 8; i++){ | 92 | for (i = 0; i < 8; i++) { |
| 98 | digitalWrite(RGB_DI_PIN, !!(byte & (1 << (7-i))); | 93 | digitalWrite(RGB_DI_PIN, !!(byte & (1 << (7-i))); |
| 99 | digitalWrite(RGB_CLK_PIN, PinLevelHigh); | 94 | digitalWrite(RGB_CLK_PIN, PinLevelHigh); |
| 100 | } | 95 | } |
| 101 | } | 96 | } |
