Line data Source code
1 : /* 2 : IS31FL3195 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 IS31FL3195 */ 20 : 21 : #include "IS31FL3195.h" 22 : 23 : #if AP_NOTIFY_IS31FL3195_ENABLED 24 : 25 : #include <utility> 26 : 27 : #include <AP_HAL/AP_HAL.h> 28 : 29 : extern const AP_HAL::HAL& hal; 30 : 31 : #define IS31FL3195_LED_BRIGHT 255 // full brightness 32 : #define IS31FL3195_LED_MEDIUM 170 // medium brightness 33 : #define IS31FL3195_LED_DIM 85 // dim 34 : #define IS31FL3195_LED_OFF 0 // off 35 : 36 : #define REGISTER_MAGIC_VLAUE 0xc5 37 : 38 : enum class Register { 39 : PRODUCT_ID = 0x00, // not really product ID, rather address of this LED 40 : SHUTDOWN_CONTROL = 0x01, 41 : OUT1 = 0x10, 42 : OUT2 = 0x21, 43 : OUT3 = 0x32, 44 : COLOR_UPDATE = 0x50, 45 : RESET = 0x5f, 46 : }; 47 : 48 10470 : IS31FL3195::IS31FL3195(uint8_t bus, uint8_t addr) 49 : : RGBLed(IS31FL3195_LED_OFF, IS31FL3195_LED_BRIGHT, IS31FL3195_LED_MEDIUM, IS31FL3195_LED_DIM) 50 10470 : , _bus(bus) 51 10470 : , _addr(addr) 52 : { 53 10470 : } 54 : 55 10470 : bool IS31FL3195::init(void) 56 : { 57 10470 : _dev = hal.i2c_mgr->get_device_ptr(_bus, _addr); 58 10470 : if (!_dev) { 59 0 : return false; 60 : } 61 10470 : WITH_SEMAPHORE(_dev->get_semaphore()); 62 : 63 10470 : _dev->set_retries(10); 64 : 65 : // check the PRODUCT_ID register to check we have found the device. The product ID register 66 : // should contain the 8 bit I2C address 67 : uint8_t v; 68 10470 : if (!_dev->read_registers((uint8_t)Register::PRODUCT_ID, &v, 1) || v != _addr<<1U) { 69 8376 : return false; 70 : } 71 : 72 : // reset the device and probe to see if this device looks like an IS31FL3195: 73 2094 : if (!_dev->write_register((uint8_t)Register::RESET, REGISTER_MAGIC_VLAUE)) { 74 0 : return false; 75 : } 76 : 77 : // reset delay; unsure if this is really required: 78 2094 : hal.scheduler->delay_microseconds(100); 79 : 80 : // check SHUTDOWN_CONTROL as an additional ID after reset 81 2094 : if (!_dev->read_registers((uint8_t)Register::SHUTDOWN_CONTROL, &v, 1) || v != 0xf0) { 82 0 : return false; 83 : } 84 : 85 : // come out of shutdown mode 86 2094 : if (!_dev->write_register((uint8_t)Register::SHUTDOWN_CONTROL, 0xf1)) { 87 0 : return false; 88 : } 89 : 90 2094 : _dev->set_retries(1); 91 : 92 : // update at 50Hz 93 2094 : _dev->register_periodic_callback(20000, FUNCTOR_BIND_MEMBER(&IS31FL3195::_timer, void)); 94 : 95 2094 : return true; 96 10470 : } 97 : 98 : // set_rgb - set color as a combination of red, green and blue values 99 363999 : bool IS31FL3195::hw_set_rgb(uint8_t red, uint8_t green, uint8_t blue) 100 : { 101 363999 : rgb[0] = red; 102 363999 : rgb[1] = green; 103 363999 : rgb[2] = blue; 104 363999 : _need_update = true; 105 363999 : return true; 106 : } 107 : 108 7790460 : void IS31FL3195::_timer(void) 109 : { 110 7790460 : if (!_need_update) { 111 7426486 : return; 112 : } 113 363974 : _need_update = false; 114 : 115 : // write color values 116 363974 : _dev->write_register(uint8_t(Register::OUT1), rgb[0]); 117 363974 : _dev->write_register(uint8_t(Register::OUT2), rgb[1]); 118 363974 : _dev->write_register(uint8_t(Register::OUT3), rgb[2]); 119 363974 : _dev->write_register(uint8_t(Register::COLOR_UPDATE), REGISTER_MAGIC_VLAUE); 120 : } 121 : 122 : #endif // AP_NOTIFY_IS31FL3195_ENABLED