2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Contact: Jeonghoon Park <jh1979.park@samsung.com>
6 * Licensed under the Flora License, Version 1.1 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://floralicense.org/license/
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <peripheral_io.h>
24 #include "resource/resource_PCA9685.h"
26 #define RPI3_I2C_BUS 1
29 #define PCA9685_ADDRESS 0x40
36 #define LED0_ON_L 0x06
37 #define LED0_ON_H 0x07
38 #define LED0_OFF_L 0x08
39 #define LED0_OFF_H 0x09
40 #define ALL_LED_ON_L 0xFA
41 #define ALL_LED_ON_H 0xFB
42 #define ALL_LED_OFF_L 0xFC
43 #define ALL_LED_OFF_H 0xFD
53 PCA9685_CH_STATE_NONE,
54 PCA9685_CH_STATE_USED,
57 static peripheral_i2c_h g_i2c_h = NULL;
58 static unsigned int ref_count = 0;
59 static pca9685_ch_state_e ch_state[PCA9685_CH_MAX + 1] = {PCA9685_CH_STATE_NONE, };
61 int resource_pca9685_set_frequency(unsigned int freq_hz)
63 int ret = PERIPHERAL_ERROR_NONE;
64 double prescale_value = 0.0;
69 prescale_value = 25000000.0; // 25MHz
70 prescale_value /= 4096.0; // 12-bit
71 prescale_value /= (double)freq_hz;
72 prescale_value -= 1.0;
74 prescale = (int)floor(prescale_value + 0.5);
76 ret = peripheral_i2c_read_register_byte(g_i2c_h, MODE1, &oldmode);
77 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to read register");
79 newmode = (oldmode & 0x7F) | 0x10; // sleep
80 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, newmode); // go to sleep
81 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
83 ret = peripheral_i2c_write_register_byte(g_i2c_h, PRESCALE, prescale);
84 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
86 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, oldmode);
87 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
91 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, (oldmode | 0x80));
92 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
97 int resource_pca9685_set_value_to_channel(unsigned int channel, int on, int off)
99 int ret = PERIPHERAL_ERROR_NONE;
100 retvm_if(g_i2c_h == NULL, -1, "Not initialized yet");
102 retvm_if(ch_state[channel] == PCA9685_CH_STATE_NONE, -1,
103 "ch[%u] is not in used state", channel);
105 ret = peripheral_i2c_write_register_byte(g_i2c_h,
106 LED0_ON_L + 4*channel, on & 0xFF);
107 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
109 ret = peripheral_i2c_write_register_byte(g_i2c_h,
110 LED0_ON_H + 4*channel, on >> 8);
111 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
113 ret = peripheral_i2c_write_register_byte(g_i2c_h,
114 LED0_OFF_L + 4*channel, off & 0xFF);
115 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
117 ret = peripheral_i2c_write_register_byte(g_i2c_h,
118 LED0_OFF_H + 4*channel, off >> 8);
119 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
124 static int resource_pca9685_set_value_to_all(int on, int off)
126 int ret = PERIPHERAL_ERROR_NONE;
127 retvm_if(g_i2c_h == NULL, -1, "Not initialized yet");
129 ret = peripheral_i2c_write_register_byte(g_i2c_h,
130 ALL_LED_ON_L, on & 0xFF);
131 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
133 ret = peripheral_i2c_write_register_byte(g_i2c_h,
134 ALL_LED_ON_H, on >> 8);
135 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
137 ret = peripheral_i2c_write_register_byte(g_i2c_h,
138 ALL_LED_OFF_L, off & 0xFF);
139 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
141 ret = peripheral_i2c_write_register_byte(g_i2c_h,
142 ALL_LED_OFF_H, off >> 8);
143 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
148 int resource_pca9685_init(unsigned int ch)
151 int ret = PERIPHERAL_ERROR_NONE;
153 if (ch > PCA9685_CH_MAX) {
154 _E("channel[%u] is out of range", ch);
158 if (ch_state[ch] == PCA9685_CH_STATE_USED) {
159 _E("channel[%u] is already in used state", ch);
164 goto PASS_OPEN_HANDLE;
166 ret = peripheral_i2c_open(RPI3_I2C_BUS, PCA9685_ADDRESS, &g_i2c_h);
167 if (ret != PERIPHERAL_ERROR_NONE) {
168 _E("failed to open pca9685-[bus:%d, addr:%d]",
169 RPI3_I2C_BUS, PCA9685_ADDRESS);
172 ret = resource_pca9685_set_value_to_all(0, 0);
174 _E("failed to reset all value to register");
178 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE2, OUTDRV);
179 if (ret != PERIPHERAL_ERROR_NONE) {
180 _E("failed to write register");
184 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, ALLCALL);
185 if (ret != PERIPHERAL_ERROR_NONE) {
186 _E("failed to write register");
190 usleep(500); // wait for oscillator
192 ret = peripheral_i2c_read_register_byte(g_i2c_h, MODE1, &mode1);
193 if (ret != PERIPHERAL_ERROR_NONE) {
194 _E("failed to read register");
198 mode1 = mode1 & (~SLEEP); // # wake up (reset sleep)
199 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, mode1);
200 if (ret != PERIPHERAL_ERROR_NONE) {
201 _E("failed to write register");
205 usleep(500); // wait for oscillator
207 ret = resource_pca9685_set_frequency(60);
209 _E("failed to set frequency");
215 ch_state[ch] = PCA9685_CH_STATE_USED;
216 _D("pca9685 - ref_count[%u]", ref_count);
217 _D("sets ch[%u] used state", ch);
223 peripheral_i2c_close(g_i2c_h);
229 int resource_pca9685_fini(unsigned int ch)
231 if (ch_state[ch] == PCA9685_CH_STATE_NONE) {
232 _E("channel[%u] is not in used state", ch);
235 resource_pca9685_set_value_to_channel(ch, 0, 0);
236 ch_state[ch] = PCA9685_CH_STATE_NONE;
239 _D("ref count - %u", ref_count);
241 if (ref_count == 0 && g_i2c_h) {
242 _D("finalizing pca9685");
243 resource_pca9685_set_value_to_all(0, 0);
244 peripheral_i2c_close(g_i2c_h);