LCOV - code coverage report
Current view: top level - AP_Notify - LP5562.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 46 52 88.5 %
Date: 2026-09-09 11:02:08 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :   LP5562 I2C driver
       3             : */
       4             : /*
       5             :    This program is free software: you can redistribute it and/or modify
       6             :    it under the terms of the GNU General Public License as published by
       7             :    the Free Software Foundation, either version 3 of the License, or
       8             :    (at your option) any later version.
       9             : 
      10             :    This program is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :    GNU General Public License for more details.
      14             : 
      15             :    You should have received a copy of the GNU General Public License
      16             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17             :  */
      18             : 
      19             : /* LED driver for LP5562 */
      20             : 
      21             : #include "LP5562.h"
      22             : 
      23             : #if AP_NOTIFY_LP5562_ENABLED
      24             : 
      25             : #include <AP_HAL/AP_HAL.h>
      26             : 
      27             : extern const AP_HAL::HAL& hal;
      28             : 
      29             : #define LP5562_LED_BRIGHT  255    // full brightness
      30             : #define LP5562_LED_MEDIUM  170    // medium brightness
      31             : #define LP5562_LED_DIM     85     // dim
      32             : #define LP5562_LED_OFF     0      // off
      33             : 
      34             : enum class Register {
      35             :     ENABLE  = 0x00,
      36             :     B_PWM   = 0x02,
      37             :     G_PWM   = 0x03,
      38             :     R_PWM   = 0x04,
      39             :     B_CURRENT= 0x05,
      40             :     G_CURRENT= 0x06,
      41             :     R_CURRENT= 0x07,
      42             :     CONFIG  = 0x08,
      43             :     RESET   = 0x0D,
      44             :     LED_MAP = 0x70,
      45             : };
      46             : 
      47       10470 : LP5562::LP5562(uint8_t bus, uint8_t addr)
      48             :     : RGBLed(LP5562_LED_OFF, LP5562_LED_BRIGHT, LP5562_LED_MEDIUM, LP5562_LED_DIM)
      49       10470 :     , _bus(bus)
      50       10470 :     , _addr(addr)
      51             : {
      52       10470 : }
      53             : 
      54       10470 : bool LP5562::init(void)
      55             : {
      56       10470 :     _dev = hal.i2c_mgr->get_device_ptr(_bus, _addr);
      57       10470 :     if (!_dev) {
      58           0 :         return false;
      59             :     }
      60             : 
      61       10470 :     if (!configure_dev()) {
      62        8376 :         delete _dev;
      63        8376 :         _dev = nullptr;
      64        8376 :         return false;
      65             :     }
      66             : 
      67        2094 :     _dev->register_periodic_callback(20000, FUNCTOR_BIND_MEMBER(&LP5562::_timer, void));
      68             : 
      69        2094 :     return true;
      70             : }
      71             : 
      72       10470 : bool LP5562::configure_dev()
      73             : {
      74       10470 :     WITH_SEMAPHORE(_dev->get_semaphore());
      75             : 
      76       10470 :     _dev->set_retries(10);
      77             : 
      78             :     // reset the device and probe to see if this device looks like an LP5662:
      79       10470 :     if (!_dev->write_register((uint8_t)Register::RESET, 0xff)) {
      80        8376 :         return false;
      81             :     }
      82             : 
      83             :     // reset delay; unsure if this is really required:
      84        2094 :     hal.scheduler->delay_microseconds(100);
      85             : 
      86             :     // check the GBR PWM control registers have their reset values:
      87        8376 :     for (uint8_t i=(uint8_t)Register::B_CURRENT; i<=(uint8_t)Register::R_CURRENT; i++) {
      88             :         uint8_t value;
      89        6282 :         if (!_dev->read_registers(i, &value, 1)) {
      90           0 :             return false;
      91             :         }
      92        6282 :         if (value != 0xAF) {  // 0xAF is the startup value for these registers per datasheet
      93           0 :             return false;
      94             :         }
      95             :     }
      96             : 
      97             :     //  values here are taken literally from 7.3.2 in the datasheet.
      98             :     //  See the simulator for register breakdown.
      99             : 
     100             :     // chip enable:
     101        2094 :     if (!_dev->write_register((uint8_t)Register::ENABLE, 0b1000000)) {
     102           0 :         return false;
     103             :     }
     104             : 
     105             :     // start-up-delay:
     106        2094 :     hal.scheduler->delay_microseconds(500);
     107             : 
     108             :     // use internal clock:
     109        2094 :     if (!_dev->write_register((uint8_t)Register::CONFIG, 0b00000001)) {
     110           0 :         return false;
     111             :     }
     112             : 
     113             :     // set direct PWM control:
     114        2094 :     if (!_dev->write_register((uint8_t)Register::LED_MAP, 0b00000000)) {
     115           0 :         return false;
     116             :     }
     117             : 
     118        2094 :     _dev->set_retries(1);
     119             : 
     120        2094 :     return true;
     121       10470 : }
     122             : 
     123             : // set_rgb - set color as a combination of red, green and blue values
     124      363999 : bool LP5562::hw_set_rgb(uint8_t red, uint8_t green, uint8_t blue)
     125             : {
     126      363999 :     bgr[0] = blue;
     127      363999 :     bgr[1] = green;
     128      363999 :     bgr[2] = red;
     129      363999 :     _need_update = true;
     130      363999 :     return true;
     131             : }
     132             : 
     133     7790472 : void LP5562::_timer(void)
     134             : {
     135     7790472 :     if (!_need_update) {
     136     7426497 :         return;
     137             :     }
     138      363975 :     _need_update = false;
     139             : 
     140     1455900 :     for (uint8_t i=0; i< ARRAY_SIZE(bgr); i++) {
     141     1091925 :         const uint8_t new_colour = bgr[i];
     142     1091925 :         const uint8_t last_sent = last_sent_bgr[i];
     143     1091925 :         if (new_colour == last_sent) {
     144      582462 :             continue;
     145             :         }
     146             :         // note that new_colour is already scaled by supplying
     147             :         // brightness values in the constructor.
     148             : 
     149             :         // take advantage of the linear layout of the registers.  The
     150             :         // direct PWM registers start at 0x02 for blue:
     151      509463 :         _dev->write_register((uint8_t)0x02 + i, new_colour);
     152             : 
     153      509463 :         last_sent_bgr[i] = new_colour;
     154             :     }
     155             : }
     156             : 
     157             : #endif  // AP_NOTIFY_LP5562_ENABLED

Generated by: LCOV version 1.14