Skip to content

Commit 93dee74

Browse files
authored
Merge pull request #664 from QB4-dev/feat-implement-pca9632
Feat implement pca9632
2 parents 9062165 + fc22d10 commit 93dee74

File tree

14 files changed

+657
-1
lines changed

14 files changed

+657
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example
225225
| **led_strip** | RMT-based driver for WS2812B/SK6812/APA106/SM16703 LED strips | MIT | esp32, esp32s2, esp32c3, esp32s3, esp32c6, esp32h2, esp32p4, esp32c5 | yes |
226226
| **led_strip_spi** | SPI-based driver for SK9822/APA102 LED strips | MIT | esp32, esp32c3, esp8266, esp32s2, esp32c3, esp32s3, esp32c6, esp32h2, esp32p4, esp32c5 | yes |
227227
| **max7219** | Driver for 8-Digit LED display drivers, MAX7219/MAX7221 | BSD-3-Clause | esp32, esp32s2, esp32c3, esp32s3, esp32c2, esp32c6, esp32h2, esp32p4, esp32c5, esp32c61 | yes |
228+
| **pca9632** | Driver for PCA9632 4-channel PWM chip | BSD-3-Clause | esp32, esp8266, esp32s2, esp32c3, esp32s3, esp32c2, esp32c6, esp32h2, esp32p4, esp32c5, esp32c61 | yes |
228229

229230

230231

@@ -366,7 +367,7 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example
366367

367368
- [Gunar Schorcht](https://github.com/gschorcht): `bme680` `ccs811` `sht3x` `sts3x`
368369

369-
- [Jakub Turek](https://github.com/QB4-dev): `impulse_sensor` `l3gx` `lsm303`
370+
- [Jakub Turek](https://github.com/QB4-dev): `impulse_sensor` `l3gx` `lsm303` `pca9632`
370371

371372
- [Jan Veeh](https://github.com/janveeh): `icm42670`
372373

components/pca9632/.eil.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: pca9632
2+
description: Driver for PCA9632 4-channel PWM chip
3+
version: 1.0.0
4+
groups:
5+
- led
6+
code_owners:
7+
- qb4-dev
8+
depends:
9+
- i2cdev
10+
- log
11+
- esp_idf_lib_helpers
12+
thread_safe: yes
13+
targets:
14+
- esp32
15+
- esp8266
16+
- esp32s2
17+
- esp32c3
18+
- esp32s3
19+
- esp32c2
20+
- esp32c6
21+
- esp32h2
22+
- esp32p4
23+
- esp32c5
24+
- esp32c61
25+
license: BSD-3
26+
copyrights:
27+
- name: qb4-dev
28+
year: 2024
29+

components/pca9632/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
idf_component_register(
2+
SRCS pca9632.c
3+
INCLUDE_DIRS .
4+
REQUIRES i2cdev log esp_idf_lib_helpers
5+
)

components/pca9632/LICENSE

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Copyright (c) 2024 Jakub Turek <qb4.dev@gmail.com>
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are met:
5+
6+
1. Redistributions of source code must retain the above copyright notice,
7+
this list of conditions and the following disclaimer.
8+
9+
2. Redistributions in binary form must reproduce the above copyright notice,
10+
this list of conditions and the following disclaimer in the documentation
11+
and/or other materials provided with the distribution.
12+
13+
3. Neither the name of the copyright holder nor the names of itscontributors
14+
may be used to endorse or promote products derived from this software without
15+
specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

components/pca9632/component.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
COMPONENT_ADD_INCLUDEDIRS = .
2+
COMPONENT_DEPENDS = i2cdev log esp_idf_lib_helpers

components/pca9632/pca9632.c

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/*
2+
* Copyright (c) 2023 Jakub Turek <qb4.dev@gmail.com>
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are met:
6+
*
7+
* 1. Redistributions of source code must retain the above copyright notice,
8+
* this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright notice,
10+
* this list of conditions and the following disclaimer in the documentation
11+
* and/or other materials provided with the distribution.
12+
* 3. Neither the name of the copyright holder nor the names of itscontributors
13+
* may be used to endorse or promote products derived from this software without
14+
* specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*/
27+
28+
/**
29+
* @file pca9632.c
30+
* @defgroup pca9632 pca9632
31+
* @{
32+
*
33+
* ESP-IDF Driver for PCA9632 4-channel PWM chip
34+
*
35+
* Copyright (c) 2023 Jakub Turek <qb4.dev@gmail.com>
36+
*
37+
* BSD Licensed as described in the file LICENSE
38+
*/
39+
#include <esp_idf_lib_helpers.h>
40+
#include "pca9632.h"
41+
42+
#define I2C_FREQ_HZ 400000
43+
44+
// Register definitions (page 11, table 7)
45+
#define REG_MODE1 0x00
46+
#define REG_MODE2 0x01
47+
#define REG_PWM0 0x02
48+
#define REG_PWM1 0x03
49+
#define REG_PWM2 0x04
50+
#define REG_PWM3 0x05
51+
#define REG_GRPPWM 0x06
52+
#define REG_GRPFREQ 0x07
53+
#define REG_LEDOUT 0x08
54+
#define REG_SUBADR1 0x09
55+
#define REG_SUBADR2 0x0A
56+
#define REG_SUBADR3 0x0B
57+
#define REG_ALLCALLADR 0x0C
58+
59+
// Bits in REG_MODE1 (page 12, table 8)
60+
#define BIT_AI2 7
61+
#define BIT_AI1 6
62+
#define BIT_AI0 5
63+
#define BIT_SLEEP 4
64+
#define BIT_SUB1 3
65+
#define BIT_SUB2 2
66+
#define BIT_SUB3 1
67+
#define BIT_ALLCALL 0
68+
69+
// Bits in REG_MODE2 (page 12-13, table 9)
70+
#define BIT_DMBLNK 5
71+
#define BIT_INVRT 4
72+
#define BIT_OCH 3
73+
#define BIT_OUTDRV 2
74+
#define BIT_OUTNE1 1
75+
#define BIT_OUTNE0 0
76+
77+
// Bits in REG_LEDOUT (page 14, table 13)
78+
#define BIT_LDR3 6
79+
#define BIT_LDR2 4
80+
#define BIT_LDR1 2
81+
#define BIT_LDR0 0
82+
83+
#define CHECK(x) \
84+
do \
85+
{ \
86+
esp_err_t __; \
87+
if ((__ = x) != ESP_OK) \
88+
return __; \
89+
} \
90+
while (0)
91+
#define CHECK_ARG(VAL) \
92+
do \
93+
{ \
94+
if (!(VAL)) \
95+
return ESP_ERR_INVALID_ARG; \
96+
} \
97+
while (0)
98+
99+
static esp_err_t pca9632_read_reg(i2c_dev_t *dev, uint8_t reg, uint8_t *val)
100+
{
101+
CHECK_ARG(dev && val);
102+
103+
I2C_DEV_TAKE_MUTEX(dev);
104+
I2C_DEV_CHECK(dev, i2c_dev_read_reg(dev, reg, val, 1));
105+
I2C_DEV_GIVE_MUTEX(dev);
106+
107+
return ESP_OK;
108+
}
109+
110+
static esp_err_t pca9632_write_reg(i2c_dev_t *dev, uint8_t reg, uint8_t val)
111+
{
112+
CHECK_ARG(dev);
113+
114+
I2C_DEV_TAKE_MUTEX(dev);
115+
I2C_DEV_CHECK(dev, i2c_dev_write_reg(dev, reg, &val, 1));
116+
I2C_DEV_GIVE_MUTEX(dev);
117+
return ESP_OK;
118+
}
119+
120+
esp_err_t pca9632_init_desc(i2c_dev_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio)
121+
{
122+
CHECK_ARG(dev && (addr == PCA9632_I2C_ADDR));
123+
124+
dev->port = port;
125+
dev->addr = addr;
126+
dev->cfg.sda_io_num = sda_gpio;
127+
dev->cfg.scl_io_num = scl_gpio;
128+
#if HELPER_TARGET_IS_ESP32
129+
dev->cfg.master.clk_speed = I2C_FREQ_HZ;
130+
#endif
131+
132+
return i2c_dev_create_mutex(dev);
133+
}
134+
135+
esp_err_t pca9632_free_desc(i2c_dev_t *dev)
136+
{
137+
CHECK_ARG(dev);
138+
return i2c_dev_delete_mutex(dev);
139+
}
140+
141+
esp_err_t pca9632_init(i2c_dev_t *dev)
142+
{
143+
CHECK_ARG(dev);
144+
// clear/ reset registers
145+
pca9632_write_reg(dev, REG_MODE1, 0x00);
146+
pca9632_write_reg(dev, REG_MODE2, 0x00);
147+
// set default states
148+
pca9632_set_led_driver_all(dev, LDR_INDIV);
149+
pca9632_set_group_control_mode(dev, GROUP_CONTROL_MODE_DIMMING);
150+
return ESP_OK;
151+
}
152+
153+
esp_err_t pca9632_set_autoincrement(i2c_dev_t *dev, pca9632_autoincr_mode_t ai)
154+
{
155+
CHECK_ARG(dev);
156+
uint8_t val;
157+
158+
switch (ai)
159+
{
160+
case AI_ALL:
161+
val = (1 << BIT_AI2) | (0 << BIT_AI1) | (0 << BIT_AI0);
162+
break;
163+
164+
case AI_INDIV:
165+
val = (1 << BIT_AI2) | (1 << BIT_AI1) | (0 << BIT_AI0);
166+
break;
167+
168+
case AI_GLOBAL:
169+
val = (1 << BIT_AI2) | (0 << BIT_AI1) | (1 << BIT_AI0);
170+
break;
171+
172+
case AI_INDIV_GLOBAL:
173+
val = (1 << BIT_AI2) | (1 << BIT_AI1) | (1 << BIT_AI0);
174+
break;
175+
176+
case AI_DISABLED:
177+
default:
178+
val = (0 << BIT_AI2) | (0 << BIT_AI1) | (0 << BIT_AI0);
179+
break;
180+
}
181+
182+
return pca9632_write_reg(dev, REG_MODE1, val);
183+
}
184+
185+
esp_err_t pca9632_set_group_control_mode(i2c_dev_t *dev, pca9632_gcm_t mode)
186+
{
187+
CHECK_ARG(dev);
188+
uint8_t reg;
189+
190+
pca9632_read_reg(dev, REG_MODE2, &reg);
191+
switch (mode)
192+
{
193+
case GROUP_CONTROL_MODE_BLINKING:
194+
return pca9632_write_reg(dev, REG_MODE2, reg | (1 << BIT_DMBLNK));
195+
196+
case GROUP_CONTROL_MODE_DIMMING:
197+
default:
198+
return pca9632_write_reg(dev, REG_MODE2, reg & ~(1 << BIT_DMBLNK));
199+
}
200+
return ESP_ERR_INVALID_ARG;
201+
}
202+
203+
esp_err_t pca9632_set_output_params(i2c_dev_t *dev, bool invert, pca9632_outdrv_t outdrv)
204+
{
205+
CHECK_ARG(dev);
206+
uint8_t reg;
207+
uint8_t val;
208+
209+
pca9632_read_reg(dev, REG_MODE2, &reg);
210+
211+
val = reg & ~((1 << BIT_INVRT) | (1 << BIT_OUTDRV)); // clear bits
212+
val = reg | ((invert << BIT_INVRT) | (outdrv << BIT_OUTDRV)); // set bits
213+
return pca9632_write_reg(dev, REG_MODE2, val);
214+
}
215+
216+
esp_err_t pca9632_set_pwm(i2c_dev_t *dev, pca9632_led_t channel, uint8_t duty)
217+
{
218+
CHECK_ARG(dev);
219+
220+
switch (channel)
221+
{
222+
case LED0:
223+
return pca9632_write_reg(dev, REG_PWM0, duty);
224+
case LED1:
225+
return pca9632_write_reg(dev, REG_PWM1, duty);
226+
case LED2:
227+
return pca9632_write_reg(dev, REG_PWM2, duty);
228+
case LED3:
229+
return pca9632_write_reg(dev, REG_PWM3, duty);
230+
default:
231+
break;
232+
}
233+
return ESP_ERR_INVALID_ARG;
234+
}
235+
236+
esp_err_t pca9632_set_pwm_all(i2c_dev_t *dev, uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3)
237+
{
238+
CHECK_ARG(dev);
239+
240+
CHECK(pca9632_write_reg(dev, REG_PWM0, led0));
241+
CHECK(pca9632_write_reg(dev, REG_PWM1, led1));
242+
CHECK(pca9632_write_reg(dev, REG_PWM2, led2));
243+
CHECK(pca9632_write_reg(dev, REG_PWM3, led3));
244+
return ESP_ERR_INVALID_ARG;
245+
}
246+
247+
esp_err_t pca9632_set_grp_pwm(i2c_dev_t *dev, uint8_t val)
248+
{
249+
CHECK_ARG(dev);
250+
return pca9632_write_reg(dev, REG_GRPPWM, val);
251+
}
252+
253+
esp_err_t pca9632_set_grp_freq(i2c_dev_t *dev, uint8_t val)
254+
{
255+
CHECK_ARG(dev);
256+
return pca9632_write_reg(dev, REG_GRPFREQ, val);
257+
}
258+
259+
esp_err_t pca9632_set_led_driver(i2c_dev_t *dev, pca9632_led_t channel, pca9632_ldr_t ldr)
260+
{
261+
CHECK_ARG(dev);
262+
uint8_t reg;
263+
uint8_t val;
264+
uint8_t shift;
265+
266+
pca9632_read_reg(dev, REG_LEDOUT, &reg);
267+
switch (channel)
268+
{
269+
case LED0:
270+
shift = BIT_LDR0;
271+
break;
272+
case LED1:
273+
shift = BIT_LDR1;
274+
break;
275+
case LED2:
276+
shift = BIT_LDR2;
277+
break;
278+
case LED3:
279+
shift = BIT_LDR3;
280+
break;
281+
default:
282+
return ESP_ERR_INVALID_ARG;
283+
}
284+
285+
val = reg & ~(0b11 << shift); // clear both bits of LDR
286+
val |= (ldr << shift);
287+
return ESP_ERR_INVALID_ARG;
288+
}
289+
290+
esp_err_t pca9632_set_led_driver_all(i2c_dev_t *dev, pca9632_ldr_t ldr)
291+
{
292+
CHECK_ARG(dev);
293+
uint8_t val = (ldr << BIT_LDR3 | ldr << BIT_LDR2 | ldr << BIT_LDR1 | ldr << BIT_LDR0);
294+
return pca9632_write_reg(dev, REG_LEDOUT, val);
295+
}

0 commit comments

Comments
 (0)