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>
25 #define RPI3_I2C_BUS 1
28 #define PCA9685_ADDRESS 0x40
35 #define LED0_ON_L 0x06
36 #define LED0_ON_H 0x07
37 #define LED0_OFF_L 0x08
38 #define LED0_OFF_H 0x09
39 #define ALL_LED_ON_L 0xFA
40 #define ALL_LED_ON_H 0xFB
41 #define ALL_LED_OFF_L 0xFC
42 #define ALL_LED_OFF_H 0xFD
52 PCA9685_CH_STATE_NONE,
53 PCA9685_CH_STATE_USED,
56 static peripheral_i2c_h g_i2c_h = NULL;
57 static unsigned int ref_count = 0;
58 static pca9685_ch_state_e ch_state[PCA9685_CH_MAX] = {PCA9685_CH_STATE_NONE, };
60 int resource_pca9685_set_frequency(unsigned int freq_hz)
62 int ret = PERIPHERAL_ERROR_NONE;
63 double prescale_value = 0.0;
68 prescale_value = 25000000.0; // 25MHz
69 prescale_value /= 4096.0; // 12-bit
70 prescale_value /= (double)freq_hz;
71 prescale_value -= 1.0;
73 prescale = (int)floor(prescale_value + 0.5);
75 ret = peripheral_i2c_read_register_byte(g_i2c_h, MODE1, &oldmode);
76 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to read register");
78 newmode = (oldmode & 0x7F) | 0x10; // sleep
79 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, newmode); // go to sleep
80 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
82 ret = peripheral_i2c_write_register_byte(g_i2c_h, PRESCALE, prescale);
83 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
85 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, oldmode);
86 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
90 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, (oldmode | 0x80));
91 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
96 int resource_pca9685_set_value_to_channel(unsigned int channel, int on, int off)
98 int ret = PERIPHERAL_ERROR_NONE;
99 retvm_if(g_i2c_h == NULL, -1, "Not initialized yet");
101 retvm_if(ch_state[channel] == PCA9685_CH_STATE_NONE, -1,
102 "ch[%u] is not in used state", channel);
104 ret = peripheral_i2c_write_register_byte(g_i2c_h,
105 LED0_ON_L + 4*channel, on & 0xFF);
106 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
108 ret = peripheral_i2c_write_register_byte(g_i2c_h,
109 LED0_ON_H + 4*channel, on >> 8);
110 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
112 ret = peripheral_i2c_write_register_byte(g_i2c_h,
113 LED0_OFF_L + 4*channel, off & 0xFF);
114 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
116 ret = peripheral_i2c_write_register_byte(g_i2c_h,
117 LED0_OFF_H + 4*channel, off >> 8);
118 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
123 static int resource_pca9685_set_value_to_all(int on, int off)
125 int ret = PERIPHERAL_ERROR_NONE;
126 retvm_if(g_i2c_h == NULL, -1, "Not initialized yet");
128 ret = peripheral_i2c_write_register_byte(g_i2c_h,
129 ALL_LED_ON_L, on & 0xFF);
130 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
132 ret = peripheral_i2c_write_register_byte(g_i2c_h,
133 ALL_LED_ON_H, on >> 8);
134 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
136 ret = peripheral_i2c_write_register_byte(g_i2c_h,
137 ALL_LED_OFF_L, off & 0xFF);
138 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
140 ret = peripheral_i2c_write_register_byte(g_i2c_h,
141 ALL_LED_OFF_H, off >> 8);
142 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
147 int resource_pca9685_init(unsigned int ch)
150 int ret = PERIPHERAL_ERROR_NONE;
152 if (ch == 0 || ch >= PCA9685_CH_MAX) {
153 _E("channel[%u] is out of range", ch);
157 if (ch_state[ch] == PCA9685_CH_STATE_USED) {
158 _E("channel[%u] is already in used state", ch);
163 goto PASS_OPEN_HANDLE;
165 ret = peripheral_i2c_open(RPI3_I2C_BUS, PCA9685_ADDRESS, &g_i2c_h);
166 if (ret != PERIPHERAL_ERROR_NONE) {
167 _E("failed to open pca9685-[bus:%d, addr:%d]",
168 RPI3_I2C_BUS, PCA9685_ADDRESS);
171 ret = resource_pca9685_set_value_to_all(0, 0);
173 _E("failed to reset all value to register");
177 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE2, OUTDRV);
178 if (ret != PERIPHERAL_ERROR_NONE) {
179 _E("failed to write register");
183 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, ALLCALL);
184 if (ret != PERIPHERAL_ERROR_NONE) {
185 _E("failed to write register");
189 usleep(500); // wait for oscillator
191 ret = peripheral_i2c_read_register_byte(g_i2c_h, MODE1, &mode1);
192 if (ret != PERIPHERAL_ERROR_NONE) {
193 _E("failed to read register");
197 mode1 = mode1 & (~SLEEP); // # wake up (reset sleep)
198 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, mode1);
199 if (ret != PERIPHERAL_ERROR_NONE) {
200 _E("failed to write register");
204 usleep(500); // wait for oscillator
206 ret = resource_pca9685_set_frequency(60);
208 _E("failed to set frequency");
214 ch_state[ch] = PCA9685_CH_STATE_USED;
215 _D("pca9685 - ref_count[%u]", ref_count);
216 _D("sets ch[%u] used state", ch);
222 peripheral_i2c_close(g_i2c_h);
228 int resource_pca9685_fini(unsigned int ch)
230 if (ch_state[ch] == PCA9685_CH_STATE_NONE) {
231 _E("channel[%u] is not in used state", ch);
234 resource_pca9685_set_value_to_channel(ch, 0, 0);
235 ch_state[ch] = PCA9685_CH_STATE_NONE;
238 _D("ref count - %u", ref_count);
240 if (ref_count == 0 && g_i2c_h) {
241 _D("finalizing pca9685");
242 resource_pca9685_set_value_to_all(0, 0);
243 peripheral_i2c_close(g_i2c_h);