1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #pragma once
25 
26 #include <string>
27 #include <mraa/i2c.h>
28 #include <mraa/gpio.h>
29 
30 #define PCA9685_I2C_BUS 0
31 #define PCA9685_DEFAULT_I2C_ADDR 0x60
32 // internal oscillator frequency
33 #define PCA9685_INTERNAL_OSC  25000000.0
34 
35 // This is a 'special' LED number, used to refer to the ALL_LED registers
36 // that affect all LED outputs at once.
37 #define PCA9685_ALL_LED 0xff
38 
39 namespace upm {
40 
41   /**
42    * @brief PCA9685 PWM Controller library
43    * @defgroup pca9685 libupm-pca9685
44    * @ingroup adafruit i2c led motor
45    */
46   /**
47    * @library pca9685
48    * @sensor pca9685
49    * @comname PCA9685 PWM Controller
50    * @type led motor
51    * @man adafruit
52    * @web http://www.adafruit.com/products/815
53    * @con i2c
54    *
55    * @brief API for the PCA9685 16-channel, 12-bit PWM LED Controller
56    *
57    * This controller is also used on the Adafruit* Motor Shield v2.3
58    * board to control up to 4 DC motors, 2 stepper motors, and 2 servo
59    * motors.
60    *
61    * This module was tested with the Adafruit Motor Shield v2.3
62    *
63    * @image html pca9685.jpg
64    * @snippet pca9685.cxx Interesting
65    */
66   class PCA9685 {
67   public:
68 
69     /**
70      * PCA9685 registers
71      */
72     typedef enum { REG_MODE1       = 0x00,
73                    REG_MODE2       = 0x01,
74                    REG_I2C_SA1     = 0x02, // I2C subaddress 1
75                    REG_I2C_SA2     = 0x03,
76                    REG_I2C_SA3     = 0x04,
77                    REG_ALLCALL     = 0x05, // I2C all call address
78 
79                    // LED output PWM control
80                    REG_LED0_ON_L   = 0x06, // LED0 ON low byte
81                    REG_LED0_ON_H   = 0x07, // LED0 ON high byte
82                    REG_LED0_OFF_L  = 0x08, // LED0 OFF low byte
83                    REG_LED0_OFF_H  = 0x09, // LED0 OFF high byte
84                    REG_LED1_ON_L   = 0x0a,
85                    REG_LED1_ON_H   = 0x0b,
86                    REG_LED1_OFF_L  = 0x0c,
87                    REG_LED1_OFF_H  = 0x0d,
88                    REG_LED2_ON_L   = 0x0e,
89                    REG_LED2_ON_H   = 0x0f,
90                    REG_LED2_OFF_L  = 0x10,
91                    REG_LED2_OFF_H  = 0x11,
92                    REG_LED3_ON_L   = 0x12,
93                    REG_LED3_ON_H   = 0x13,
94                    REG_LED3_OFF_L  = 0x14,
95                    REG_LED3_OFF_H  = 0x15,
96                    REG_LED4_ON_L   = 0x16,
97                    REG_LED4_ON_H   = 0x17,
98                    REG_LED4_OFF_L  = 0x18,
99                    REG_LED4_OFF_H  = 0x19,
100                    REG_LED5_ON_L   = 0x1a,
101                    REG_LED5_ON_H   = 0x1b,
102                    REG_LED5_OFF_L  = 0x1c,
103                    REG_LED5_OFF_H  = 0x1d,
104                    REG_LED6_ON_L   = 0x1e,
105                    REG_LED6_ON_H   = 0x1f,
106                    REG_LED6_OFF_L  = 0x20,
107                    REG_LED6_OFF_H  = 0x21,
108                    REG_LED7_ON_L   = 0x22,
109                    REG_LED7_ON_H   = 0x23,
110                    REG_LED7_OFF_L  = 0x24,
111                    REG_LED7_OFF_H  = 0x25,
112                    REG_LED8_ON_L   = 0x26,
113                    REG_LED8_ON_H   = 0x27,
114                    REG_LED8_OFF_L  = 0x28,
115                    REG_LED8_OFF_H  = 0x29,
116                    REG_LED9_ON_L   = 0x2a,
117                    REG_LED9_ON_H   = 0x2b,
118                    REG_LED9_OFF_L  = 0x2c,
119                    REG_LED9_OFF_H  = 0x2d,
120                    REG_LED10_ON_L  = 0x2e,
121                    REG_LED10_ON_H  = 0x2f,
122                    REG_LED10_OFF_L = 0x30,
123                    REG_LED10_OFF_H = 0x31,
124                    REG_LED11_ON_L  = 0x32,
125                    REG_LED11_ON_H  = 0x33,
126                    REG_LED11_OFF_L = 0x34,
127                    REG_LED11_OFF_H = 0x35,
128                    REG_LED12_ON_L  = 0x36,
129                    REG_LED12_ON_H  = 0x37,
130                    REG_LED12_OFF_L = 0x38,
131                    REG_LED12_OFF_H = 0x39,
132                    REG_LED13_ON_L  = 0x3a,
133                    REG_LED13_ON_H  = 0x3b,
134                    REG_LED13_OFF_L = 0x3c,
135                    REG_LED13_OFF_H = 0x3d,
136                    REG_LED14_ON_L  = 0x3e,
137                    REG_LED14_ON_H  = 0x3f,
138                    REG_LED14_OFF_L = 0x40,
139                    REG_LED14_OFF_H = 0x41,
140                    REG_LED15_ON_L  = 0x42,
141                    REG_LED15_ON_H  = 0x43,
142                    REG_LED15_OFF_L = 0x44,
143                    REG_LED15_OFF_H = 0x45,
144                    // 0x46-0xf9 reserved
145 
146                    REG_ALL_LED_ON_L  = 0xfa, // write all LED ON L
147                    REG_ALL_LED_ON_H  = 0xfb, // write all LED ON H
148                    REG_ALL_LED_OFF_L = 0xfc, // write all LED OFF L
149                    REG_ALL_LED_OFF_H = 0xfd, // write all LED OFF H
150                    REG_PRESCALE      = 0xfe,
151                    REG_TESTMODE      = 0xff  // don't use
152     } PCA9685_REG_T;
153 
154     /**
155      * MODE1 bits
156      */
157     typedef enum { MODE1_ALL_CALL    = 0x01, // all call status
158                    MODE1_SUB3        = 0x02, // subcall 3 status
159                    MODE1_SUB2        = 0x04, // subcall 2 status
160                    MODE1_SUB1        = 0x08, // subcall 1 status
161                    MODE1_SLEEP       = 0x10, // sleep/normal mode
162                    MODE1_AI          = 0x20, // auto-increment enable
163                    MODE1_EXTCLK      = 0x40, // external clock enable
164                    MODE1_RESTART     = 0x80  // restart status
165     } PCA9685_MODE1_T;
166 
167     /**
168      * MODE2 bits
169      */
170     typedef enum { MODE2_OUTNE0      = 0x01, // output driver enable bit 0
171                    MODE2_OUTNE       = 0x02, // output driver enable bit 1
172                    MODE2_OUTDRV      = 0x04, // output open-drain/totem pole
173                    MODE2_OCH         = 0x08, // output change on STOP or ACK
174                    MODE2_INVRT       = 0x10, // output logic state invert
175                    MODE2_RESERVE0    = 0x20, // reserved
176                    MODE2_RESERVE1    = 0x40, // reserved
177                    MODE2_RESERVE2    = 0x80  // reserved
178     } PCA9685_MODE2_T;
179 
180     /**
181      * PCA9685 constructor
182      *
183      * @param bus I2C bus to use
184      * @param address Address for this device
185      */
186     PCA9685(int bus, uint8_t address = PCA9685_DEFAULT_I2C_ADDR, bool raw = false);
187 
188     /**
189      * PCA9685 destructor
190      */
191     ~PCA9685();
192 
193     /**
194      * Writes a byte value into a register
195      *
196      * @param reg Register location to write into
197      * @param byte Byte to write
198      * @return True if successful
199      */
200     bool writeByte(uint8_t reg, uint8_t byte);
201 
202     /**
203      * Writes a word value into a register. Note: the device must have the
204      * auto-increment bit set in the MODE1 register to work.
205      *
206      * @param reg Register location to write into
207      * @param word Word to write
208      * @return True if successful
209      */
210     bool writeWord(uint8_t reg, uint16_t word);
211 
212     /**
213      * Reads a byte value from a register
214      *
215      * @param reg Register location to read from
216      * @return Value in a specified register
217      */
218     uint8_t readByte(uint8_t reg);
219 
220     /**
221      * Reads a word value from a register. Note: the device must have the
222      * auto-increment bit set in the MODE1 register to work.
223      *
224      * @param reg Register location to read from
225      * @return Value in a specified register
226      */
227     uint16_t readWord(uint8_t reg);
228 
229     /**
230      * Puts the device in or out of the sleep mode. The device is always
231      * in the sleep mode upon power-up.
232      *
233      * @param sleep True to put the device in the sleep mode, false to put out
234      * @return True if successful
235      */
236     bool setModeSleep(bool sleep);
237 
238     /**
239      * Sets or clears the FULL ON bit for a given LED
240      *
241      * @param led LED number; valid values are 0-15, PCA9685_ALL_LED
242      * @param val True to set the bit, false to clear it
243      * @return True if successful
244      */
245     bool ledFullOn(uint8_t led, bool val);
246 
247     /**
248      * Sets or clears the FULL OFF bit for a given LED. If the FULL ON
249      * bit is also set, FULL OFF has precedence.
250      *
251      * @param led LED number; valid values are 0-15, PCA9685_ALL_LED
252      * @param val True to set the bit, false to clear it
253      * @return True if successful
254      */
255     bool ledFullOff(uint8_t led, bool val);
256 
257     /**
258      * Sets the 'LED on' time (0-4,095). See the PCA9685 datasheet for details.
259      *
260      * @param led LED number; valid values are 0-15, PCA9685_ALL_LED
261      * @param time 12-bit value at which point the LED turns on
262      * @return True if successful
263      */
264     bool ledOnTime(uint8_t led, uint16_t time);
265 
266     /**
267      * Sets the 'LED off' time (0-4,095). See the PCA9685 datasheet for details.
268      *
269      * @param led LED number; valid values are 0-15, PCA9685_ALL_LED
270      * @param time 12-bit value at which point the LED turns off
271      * @return True if successful
272      */
273     bool ledOffTime(uint8_t led, uint16_t time);
274 
275     /**
276      * Sets the prescale value. See the PCA9685 datasheet for
277      * details. The prescale can only be set when the device is in
278      * the sleep mode.
279      *
280      * @param prescale Prescale value
281      * @return True if successful
282      */
283     bool setPrescale(uint8_t prescale);
284 
285     /**
286      * Sets the prescale value based on a desired frequency in Hz. The
287      * prescale can only be set when the device is in the sleep mode.
288      *
289      * @param hz Desired frequency in Hz
290      * @param oscFreq Oscillator frequency; default is 25 MHz
291      * @return True if successful
292      */
293     bool setPrescaleFromHz(float hz,
294                            float oscFreq=PCA9685_INTERNAL_OSC);
295 
296     /**
297      * Enables or disables the restart capability of the controller
298      *
299      * @param enabled True to enable, false to disable
300      * It is enabled by default.
301      */
enableRestart(bool enabled)302     void enableRestart(bool enabled) { m_restartEnabled = enabled; };
303 
304   private:
305     /**
306      * Enables the I2C register auto-increment. This needs to be enabled
307      * for write/readWord() to work. The contructor enables this by
308      * default.
309      *
310      * @param ai True to enable, false otherwise
311      */
312     bool enableAutoIncrement(bool ai);
313 
314     bool m_restartEnabled;
315     mraa_i2c_context m_i2c;
316     uint8_t m_addr;
317   };
318 }
319 
320 
321