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
51 static peripheral_i2c_h g_i2c_h = NULL;
52 static unsigned int ref_count = 0;
54 int resource_pca9685_set_frequency(unsigned int freq_hz)
56 int ret = PERIPHERAL_ERROR_NONE;
57 double prescale_value = 0.0;
62 prescale_value = 25000000.0; // 25MHz
63 prescale_value /= 4096.0; // 12-bit
64 prescale_value /= (double)freq_hz;
65 prescale_value -= 1.0;
67 prescale = (int)floor(prescale_value + 0.5);
69 ret = peripheral_i2c_read_register_byte(g_i2c_h, MODE1, &oldmode);
70 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to read register");
72 newmode = (oldmode & 0x7F) | 0x10; // sleep
73 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, newmode); // go to sleep
74 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
76 ret = peripheral_i2c_write_register_byte(g_i2c_h, PRESCALE, prescale);
77 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
79 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, oldmode);
80 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
84 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, (oldmode | 0x80));
85 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
90 int resource_pca9685_set_value_to_channel(unsigned int channel, int on, int off)
92 int ret = PERIPHERAL_ERROR_NONE;
93 retvm_if(g_i2c_h == NULL, -1, "Not initialized yet");
95 ret = peripheral_i2c_write_register_byte(g_i2c_h,
96 LED0_ON_L + 4*channel, on & 0xFF);
97 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
99 ret = peripheral_i2c_write_register_byte(g_i2c_h,
100 LED0_ON_H + 4*channel, on >> 8);
101 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
103 ret = peripheral_i2c_write_register_byte(g_i2c_h,
104 LED0_OFF_L + 4*channel, off & 0xFF);
105 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
107 ret = peripheral_i2c_write_register_byte(g_i2c_h,
108 LED0_OFF_H + 4*channel, off >> 8);
109 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
114 int resource_pca9685_set_value_to_all(int on, int off)
116 int ret = PERIPHERAL_ERROR_NONE;
117 retvm_if(g_i2c_h == NULL, -1, "Not initialized yet");
119 ret = peripheral_i2c_write_register_byte(g_i2c_h,
120 ALL_LED_ON_L, on & 0xFF);
121 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
123 ret = peripheral_i2c_write_register_byte(g_i2c_h,
124 ALL_LED_ON_H, on >> 8);
125 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
127 ret = peripheral_i2c_write_register_byte(g_i2c_h,
128 ALL_LED_OFF_L, off & 0xFF);
129 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
131 ret = peripheral_i2c_write_register_byte(g_i2c_h,
132 ALL_LED_OFF_H, off >> 8);
133 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
138 int resource_pca9685_init(void)
141 int ret = PERIPHERAL_ERROR_NONE;
145 _D("Already initialized - ref_count[%u]\n", ref_count);
149 ret = peripheral_i2c_open(RPI3_I2C_BUS, PCA9685_ADDRESS, &g_i2c_h);
150 if (ret != PERIPHERAL_ERROR_NONE) {
151 _E("failed to open pca9685-[bus:%d, addr:%d]",
152 RPI3_I2C_BUS, PCA9685_ADDRESS);
155 ret = resource_pca9685_set_value_to_all(0, 0);
156 retvm_if(ret, -1, "failed to set value to register");
158 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE2, OUTDRV);
159 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
161 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, ALLCALL);
162 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
164 usleep(500); // wait for oscillator
166 ret = peripheral_i2c_read_register_byte(g_i2c_h, MODE1, &mode1);
167 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to read register");
169 mode1 = mode1 & (~SLEEP); // # wake up (reset sleep)
170 ret = peripheral_i2c_write_register_byte(g_i2c_h, MODE1, mode1);
171 retvm_if(ret != PERIPHERAL_ERROR_NONE, -1, "failed to write register");
173 usleep(500); // wait for oscillator
175 ret = resource_pca9685_set_frequency(60);
177 _E("failed to set frequency");
178 peripheral_i2c_close(g_i2c_h);
187 int resource_pca9685_fini(void)
191 _D("ref count - %u", ref_count);
194 _D("finalizing pca9685");
195 resource_pca9685_set_value_to_all(0, 0);
196 peripheral_i2c_close(g_i2c_h);