NeoPixel.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include "AP_Notify/AP_Notify.h"
  14. #include "NeoPixel.h"
  15. #include "SRV_Channel/SRV_Channel.h"
  16. // This limit is from the dshot driver rcout groups limit
  17. #define AP_NOTIFY_NEOPIXEL_MAX_INSTANCES 4
  18. #ifndef HAL_NEOPIXEL_COUNT
  19. #define HAL_NEOPIXEL_COUNT 1
  20. #endif
  21. // Datasheet: https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf
  22. // 24bit msg as 3 byte GRB (not RGB) where first bit is G7, and last bit is B0
  23. // (first) G7|G6|G5|G4|G3|G2|G1|G0|R7|R6|R5|R4|R3|R2|R1|R0|B7|B6|B5|B4|B3|B2|B1|B0 (last)
  24. #define NEOPIXEL_LED_LOW 0x33
  25. #define NEOPIXEL_LED_MEDIUM 0x7F
  26. #define NEOPIXEL_LED_HIGH 0xFF
  27. #define NEOPIXEL_LED_OFF 0x00
  28. extern const AP_HAL::HAL& hal;
  29. NeoPixel::NeoPixel() :
  30. RGBLed(NEOPIXEL_LED_OFF, NEOPIXEL_LED_HIGH, NEOPIXEL_LED_MEDIUM, NEOPIXEL_LED_LOW)
  31. {
  32. }
  33. bool NeoPixel::hw_init()
  34. {
  35. init_ports();
  36. hal.scheduler->register_io_process(FUNCTOR_BIND_MEMBER(&NeoPixel::timer, void));
  37. return true;
  38. }
  39. uint16_t NeoPixel::init_ports()
  40. {
  41. uint16_t mask = 0;
  42. for (uint16_t i=0; i<AP_NOTIFY_NEOPIXEL_MAX_INSTANCES; i++) {
  43. const SRV_Channel::Aux_servo_function_t fn = (SRV_Channel::Aux_servo_function_t)((uint8_t)SRV_Channel::k_LED_neopixel1 + i);
  44. if (!SRV_Channels::function_assigned(fn)) {
  45. continue;
  46. }
  47. mask |= SRV_Channels::get_output_channel_mask(fn);
  48. }
  49. if (mask != 0) {
  50. for (uint16_t chan=0; chan<16; chan++) {
  51. if ((1U<<chan) & mask) {
  52. hal.rcout->set_neopixel_num_LEDs(chan, HAL_NEOPIXEL_COUNT);
  53. }
  54. }
  55. }
  56. last_mask = mask;
  57. return mask;
  58. }
  59. void NeoPixel::timer()
  60. {
  61. WITH_SEMAPHORE(_sem);
  62. const uint32_t now_ms = AP_HAL::millis();
  63. if (now_ms - _last_init_ms >= 1000) {
  64. _last_init_ms = now_ms;
  65. enable_mask = init_ports();
  66. }
  67. }
  68. bool NeoPixel::hw_set_rgb(uint8_t red, uint8_t green, uint8_t blue)
  69. {
  70. if (enable_mask == 0) {
  71. // nothing is enabled, no pins set as LED output
  72. return true;
  73. }
  74. for (uint16_t chan=0; chan<16; chan++) {
  75. if ((1U<<chan) & enable_mask) {
  76. hal.rcout->set_neopixel_rgb_data(chan, (1U<<HAL_NEOPIXEL_COUNT)-1, red, green, blue);
  77. }
  78. }
  79. hal.rcout->neopixel_send();
  80. return true;
  81. }