Skip to content

Commit 5134fda

Browse files
committed
shift_reg: add shift_reg component
The feature is a driver to interface the microcontroller with shift registers just using 3 pins: Clock, Data and Latch. For further information, please, take a look at the component [README.md](components/shift_reg/README.md). Feature requested by issue #457.
1 parent fca4578 commit 5134fda

File tree

16 files changed

+558
-0
lines changed

16 files changed

+558
-0
lines changed

.github/labeler.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,14 @@ labels:
536536
- "components/sgp40/**"
537537
- "components/sgp40/.eil.yml"
538538
- "examples/sgp40/**"
539+
- label: "area:components:shift_reg"
540+
sync: true
541+
matcher:
542+
files:
543+
any:
544+
- "components/shift_reg/**"
545+
- "components/shift_reg/.eil.yml"
546+
- "examples/shift_reg/**"
539547
- label: "area:components:sht3x"
540548
sync: true
541549
matcher:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ or [GitLab examples](https://gitlab.com/UncleRus/esp-idf-lib/tree/master/example
213213
| **lc709203f** | Driver for LC709203F battery fuel gauge | ISC | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | Yes
214214
| **pca9685** | Driver for 16-channel, 12-bit PWM PCA9685 | BSD-3 | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | Yes
215215
| **rda5807m** | Driver for single-chip broadcast FM radio tuner RDA5807M | BSD-3 | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | Yes
216+
| **shift_reg** | Driver for generic shift register interface. | ISC | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | Yes
216217
| **tca9548** | Driver for TCA9548A/PCA9548A low-voltage 8-channel I2C switch | BSD-3 | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | Yes
217218
| **tda74xx** | Driver for TDA7439/TDA7439DS/TDA7440D audioprocessors | MIT | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | Yes
218219
| **ultrasonic** | Driver for ultrasonic range meters, e.g. HC-SR04, HY-SRF05 | BSD-3 | `esp32`, `esp8266`, `esp32s2`, `esp32c3` | No

components/shift_reg/.eil.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
components:
3+
- name: shift_reg
4+
description: Driver for generic shift register interface.
5+
group: misc
6+
groups: []
7+
code_owners: jaimealbq
8+
depends:
9+
# FIXME conditional depends
10+
- name: driver
11+
- name: log
12+
- name: esp_idf_lib_helpers
13+
thread_safe: yes
14+
targets:
15+
- name: esp32
16+
- name: esp8266
17+
- name: esp32s2
18+
- name: esp32c3
19+
licenses:
20+
- name: ISC
21+
copyrights:
22+
- author:
23+
name: jaimealbq
24+
year: 2022
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
if(${IDF_TARGET} STREQUAL esp8266)
2+
set(req esp8266 log esp_idf_lib_helpers)
3+
else()
4+
set(req driver log esp_idf_lib_helpers)
5+
endif()
6+
7+
idf_component_register(
8+
SRCS shift_reg.c
9+
INCLUDE_DIRS .
10+
REQUIRES ${req}
11+
)

components/shift_reg/LICENSE

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2022 Jaime Albuquerque <[email protected]>
2+
3+
Permission to use, copy, modify, and distribute this software for any
4+
purpose with or without fee is hereby granted, provided that the above
5+
copyright notice and this permission notice appear in all copies.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

components/shift_reg/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# `Shift Register`
2+
This driver can be used as an interface with a shift register in (still in progress) and out (such as [74HC595](https://www.ti.com/lit/ds/symlink/sn74hc595.pdf)).
3+
4+
## Usage
5+
To use the library, it needs to be configured before initialize. To do so a `shift_reg_config_t` needs to be set.
6+
7+
### Configuration
8+
The `shift_reg_config_t` struct store all necessaries configurtions and value of aech register.
9+
10+
* `uint8_t num_reg` - Number of registers which will be used
11+
* `uint8_t *reg_value` - Vector for the last value of all registers; it can be used for know what is the actual value of the registers
12+
13+
### Mode configuration
14+
* `struct mode`
15+
* `shift_reg_dir_t dir` - Direction mode of the shift register
16+
* `shift_reg_bit_mode_t bit_mode` - Bit mode
17+
18+
### Pin configurations
19+
* `struct pin`
20+
* `gpio_num_t clk` - Clock pin
21+
* `gpio_num_t data` - Data/Signal pin
22+
* `gpio_num_t latch` - Latch pin
23+
24+
#### Direcition mode
25+
The `shift_reg_dir_t` says the direction of the register.
26+
* `SHIFT_DIR_OUTPUT` - Set the register as output
27+
* `SHIFT_DIR_INPUT` - Set the register as input
28+
* `SHIFT_DIR_INPUT_OUTPUT` - Set the register as output and input
29+
30+
#### First bit configuration
31+
The `shift_reg_bit_mode_t` says the bit mode of the data.
32+
* `SHIFT_BIT_MODE_LSB` - Start send data from the lowest significant bit
33+
* `SHIFT_BIT_MODE_MSB` - Start send data from the most significandt bit
34+
35+
### Initialization
36+
To initialize the shift register it is going to need to call the `esp_err_t shift_reg_init(shift_reg_config_t *dev)`, by passing the created shift register configurations.
37+
38+
### De-initialization
39+
Since the `uint8_t *reg_value` is created accordingly of the number of registers, the vector allocate the necessary size in the heap memory, so `esp_err_t shift_reg_deinit(shift_reg_config_t *dev)` can be used to free this memory.
40+
41+
### Sending the data
42+
To send the intended data, call the `esp_err_t shift_reg_send(uint8_t *data, uint8_t len, shift_reg_config_t *dev)` function, where:
43+
* `data` - the address of the bening of the data
44+
* `len` - the length of the data in bytes
45+
* `dev` - the shift register interface to be used
46+
47+
**NOTE**: The data sent will be just in the internal memory (register(s)) of the shift register(s), and not reflected in the pins. See lataching pins to see how the pins can be set.
48+
49+
### Latching pins
50+
To set the pins as it is in the internal memory of the register(s), the function `esp_err_t shift_reg_latch(shift_reg_config_t *dev);` needs to be called. It will be latched by the passed shifter interface.
51+
52+
## TODO
53+
* [ ] Implement input shift register
54+
* [ ] Interface with [hd44780](../hd44780/)
55+
56+
# Author
57+
Jaime Albuquerque
58+
* GitHub: [jaimealbq](https://github.com/jaimealbq)
59+
* GitLab: [jaimealbq](https://gitlab.com/jaimealbq)
60+
* LinkedIn: [Jaime Albuquerque](https://www.linkedin.com/in/jaimealbq)

components/shift_reg/component.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
COMPONENT_ADD_INCLUDEDIRS = .
2+
3+
ifdef CONFIG_IDF_TARGET_ESP8266
4+
COMPONENT_DEPENDS = esp8266 log esp_idf_lib_helpers
5+
else
6+
COMPONENT_DEPENDS = driver log esp_idf_lib_helpers
7+
endif

components/shift_reg/shift_reg.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
* Copyright (c) 2022 Jaime Albuquerque <[email protected]>
3+
*
4+
* Permission to use, copy, modify, and distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*/
16+
17+
#include "shift_reg.h"
18+
19+
static char *tag = "shift_reg";
20+
21+
esp_err_t shift_reg_init(shift_reg_config_t *dev)
22+
{
23+
esp_err_t err = ESP_FAIL;
24+
25+
if (dev == NULL)
26+
{
27+
ESP_LOGE(tag, "%s: must have the configuration of the shift register", __func__);
28+
err = ESP_ERR_INVALID_ARG;
29+
return err;
30+
}
31+
32+
dev->reg_value = (uint8_t *)malloc(dev->num_reg); // Create an array with all registers
33+
34+
if (dev->reg_value == NULL)
35+
{
36+
ESP_LOGE(tag, "%s: no heap memory to allocate reg_value", __func__);
37+
err = ESP_ERR_NO_MEM;
38+
return err;
39+
}
40+
41+
memset(dev->reg_value, 0, dev->num_reg); // Start all registers as 0
42+
43+
gpio_config_t io_conf;
44+
45+
// disable interrupt
46+
io_conf.intr_type = GPIO_INTR_DISABLE;
47+
48+
switch (dev->mode.dir)
49+
{
50+
case SHIFT_DIR_OUTPUT:
51+
// set as output mode
52+
io_conf.mode = GPIO_MODE_OUTPUT;
53+
uint32_t buf32_0 = 0;
54+
uint32_t buf32_1 = 0;
55+
uint64_t result = 0;
56+
57+
if (dev->pin.clk >= 32)
58+
buf32_1 |= 1 << (dev->pin.clk - 32);
59+
else
60+
buf32_0 |= 1 << dev->pin.clk;
61+
62+
if (dev->pin.latch >= 32)
63+
buf32_1 |= 1 << (dev->pin.latch - 32);
64+
else
65+
buf32_0 |= 1 << dev->pin.latch;
66+
67+
if (dev->pin.data >= 32)
68+
buf32_1 |= 1 << (dev->pin.data - 32);
69+
else
70+
buf32_0 |= 1 << dev->pin.data;
71+
72+
result = ((uint64_t)buf32_1 << 32) | ((uint64_t)buf32_0 << 0);
73+
74+
io_conf.pin_bit_mask = result;
75+
76+
break;
77+
78+
default:
79+
ESP_LOGE(tag, "%s: Mode of shift register not found", __func__);
80+
err = ESP_ERR_INVALID_ARG;
81+
break;
82+
}
83+
// disable pull-down mode
84+
io_conf.pull_down_en = 0;
85+
// disable pull-up mode
86+
io_conf.pull_up_en = 0;
87+
// configure GPIO with the given settings
88+
err = gpio_config(&io_conf);
89+
90+
return err;
91+
}
92+
93+
esp_err_t shift_reg_deinit(shift_reg_config_t *dev)
94+
{
95+
if (dev == NULL)
96+
{
97+
ESP_LOGE(tag, "%s: must have a valid argument;", __func__);
98+
return ESP_ERR_INVALID_ARG;
99+
}
100+
101+
free(dev->reg_value);
102+
return ESP_OK;
103+
}
104+
105+
esp_err_t shift_reg_send(shift_reg_config_t *dev, uint8_t *data, uint8_t len)
106+
{
107+
esp_err_t err = ESP_FAIL;
108+
109+
if (dev == NULL || len > dev->num_reg || data == NULL)
110+
{
111+
ESP_LOGE(tag, "%s: must have a valid argument;", __func__);
112+
err = ESP_ERR_INVALID_ARG;
113+
return err;
114+
}
115+
116+
if (dev->mode.bit_mode == SHIFT_BIT_MODE_MSB)
117+
{
118+
for (uint8_t i = 0; i < len; i++)
119+
{
120+
shift_reg_send8bits(dev, data[i]);
121+
dev->reg_value[i] = data[i];
122+
}
123+
}
124+
else
125+
{
126+
for (int8_t i = len - 1; i >= 0; i--)
127+
{
128+
shift_reg_send8bits(dev, data[i]);
129+
dev->reg_value[i] = data[i];
130+
}
131+
}
132+
133+
err = ESP_OK;
134+
135+
return err;
136+
}
137+
138+
esp_err_t shift_reg_send8bits(shift_reg_config_t *dev, uint8_t data)
139+
{
140+
esp_err_t err = ESP_FAIL;
141+
142+
if (dev == NULL)
143+
{
144+
ESP_LOGE(tag, "%s: must have a valid argument;", __func__);
145+
err = ESP_ERR_INVALID_ARG;
146+
return err;
147+
}
148+
149+
if (dev->mode.bit_mode == SHIFT_BIT_MODE_MSB)
150+
{
151+
// MSB Mode
152+
for (int8_t i = 7; i >= 0; i--)
153+
{
154+
if ((data >> i) & 1)
155+
{
156+
gpio_set_level(dev->pin.data, true);
157+
}
158+
else
159+
{
160+
gpio_set_level(dev->pin.data, false);
161+
}
162+
163+
gpio_set_level(dev->pin.clk, true);
164+
ets_delay_us(1);
165+
gpio_set_level(dev->pin.clk, false);
166+
ets_delay_us(1);
167+
}
168+
}
169+
else
170+
{
171+
// LSB Mode
172+
for (int8_t i = 0; i < 8; i++)
173+
{
174+
if ((data >> i) & 1)
175+
{
176+
gpio_set_level(dev->pin.data, true);
177+
}
178+
else
179+
{
180+
gpio_set_level(dev->pin.data, false);
181+
}
182+
183+
gpio_set_level(dev->pin.clk, true);
184+
ets_delay_us(1);
185+
gpio_set_level(dev->pin.clk, false);
186+
ets_delay_us(1);
187+
}
188+
}
189+
190+
err = ESP_OK;
191+
192+
return err;
193+
}
194+
195+
esp_err_t shift_reg_latch(shift_reg_config_t *dev)
196+
{
197+
gpio_set_level(dev->pin.latch, true);
198+
ets_delay_us(1);
199+
gpio_set_level(dev->pin.latch, false);
200+
ets_delay_us(1);
201+
202+
return ESP_OK;
203+
}

0 commit comments

Comments
 (0)