Skip to content

Commit 351a0e7

Browse files
authored
Merge pull request adafruit#4047 from kmatch98/esp32s2_ParallelBus
Add initial ParallelBus support for ESP32-S2
2 parents d116ad0 + 61850ac commit 351a0e7

File tree

3 files changed

+184
-8
lines changed

3 files changed

+184
-8
lines changed

locale/circuitpython.pot

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ msgid "Buffer too short by %d bytes"
531531
msgstr ""
532532

533533
#: ports/atmel-samd/common-hal/displayio/ParallelBus.c
534+
#: ports/esp32s2/common-hal/displayio/ParallelBus.c
534535
#: ports/nrf/common-hal/displayio/ParallelBus.c
535536
#, c-format
536537
msgid "Bus pin %d is already in use"
@@ -800,6 +801,10 @@ msgstr ""
800801
msgid "Data 0 pin must be byte aligned"
801802
msgstr ""
802803

804+
#: ports/esp32s2/common-hal/displayio/ParallelBus.c
805+
msgid "Data 0 pin must be byte aligned."
806+
msgstr ""
807+
803808
#: shared-module/audiocore/WaveFile.c
804809
msgid "Data chunk must follow fmt chunk"
805810
msgstr ""
@@ -1584,7 +1589,6 @@ msgid ""
15841589
"PWM frequency not writable when variable_frequency is False on construction."
15851590
msgstr ""
15861591

1587-
#: ports/esp32s2/common-hal/displayio/ParallelBus.c
15881592
#: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
15891593
#: ports/stm/common-hal/displayio/ParallelBus.c
15901594
msgid "ParallelBus not yet supported"

ports/esp32s2/common-hal/displayio/ParallelBus.c

Lines changed: 168 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,35 +33,196 @@
3333
#include "shared-bindings/digitalio/DigitalInOut.h"
3434
#include "shared-bindings/microcontroller/__init__.h"
3535

36+
/*
37+
* Current pin limitations for ESP32-S2 ParallelBus:
38+
* - data0 pin must be byte aligned
39+
*/
40+
3641
void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* self,
3742
const mcu_pin_obj_t* data0, const mcu_pin_obj_t* command, const mcu_pin_obj_t* chip_select,
3843
const mcu_pin_obj_t* write, const mcu_pin_obj_t* read, const mcu_pin_obj_t* reset) {
3944

40-
mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
45+
uint8_t data_pin = data0->number;
46+
if (data_pin % 8 != 0) {
47+
mp_raise_ValueError(translate("Data 0 pin must be byte aligned."));
48+
}
49+
50+
for (uint8_t i = 0; i < 8; i++) {
51+
if (!pin_number_is_free(data_pin + i)) {
52+
mp_raise_ValueError_varg(translate("Bus pin %d is already in use"), i);
53+
}
54+
}
55+
56+
gpio_dev_t *g = &GPIO; // this is the GPIO registers, see "extern gpio_dev_t GPIO" from file:gpio_struct.h
57+
58+
// Setup the pins as "Simple GPIO outputs" see section 19.3.3 of the ESP32-S2 Reference Manual
59+
// Enable pins with "enable_w1ts"
60+
61+
for (uint8_t i = 0; i < 8; i++) {
62+
g->enable_w1ts = (0x1 << (data_pin + i));
63+
g->func_out_sel_cfg[data_pin + i].val= 256; /* setup output pin for simple GPIO Output, (0x100 = 256) */
64+
65+
}
66+
67+
/* From my understanding, there is a limitation of the ESP32-S2 that does not allow single-byte writes
68+
* into the GPIO registers. See section 10.3.3 regarding "non-aligned writes" into the registers.
69+
*/
70+
71+
72+
if (data_pin < 31) {
73+
self->bus = (uint32_t*) &g->out; //pointer to GPIO output register (for pins 0-31)
74+
} else {
75+
self->bus = (uint32_t*) &g->out1.val; //pointer to GPIO output register (for pins >= 32)
76+
}
77+
78+
/* SNIP - common setup of command, chip select, write and read pins, same as from SAMD and NRF ports */
79+
self->command.base.type = &digitalio_digitalinout_type;
80+
common_hal_digitalio_digitalinout_construct(&self->command, command);
81+
common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL);
82+
83+
self->chip_select.base.type = &digitalio_digitalinout_type;
84+
common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
85+
common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);
86+
87+
self->write.base.type = &digitalio_digitalinout_type;
88+
common_hal_digitalio_digitalinout_construct(&self->write, write);
89+
common_hal_digitalio_digitalinout_switch_to_output(&self->write, true, DRIVE_MODE_PUSH_PULL);
90+
91+
self->read.base.type = &digitalio_digitalinout_type;
92+
common_hal_digitalio_digitalinout_construct(&self->read, read);
93+
common_hal_digitalio_digitalinout_switch_to_output(&self->read, true, DRIVE_MODE_PUSH_PULL);
94+
95+
self->data0_pin = data_pin;
96+
97+
if (write->number < 32) {
98+
self->write_clear_register = (uint32_t*) &g->out_w1tc;
99+
self->write_set_register = (uint32_t*) &g->out_w1ts;
100+
} else {
101+
self->write_clear_register = (uint32_t*) &g->out1_w1tc.val;
102+
self->write_set_register = (uint32_t*) &g->out1_w1ts.val;
103+
}
104+
105+
// Check to see if the data and write pins are on the same register:
106+
if ( ( ((self->data0_pin < 32) && (write->number < 32)) ) ||
107+
( ((self->data0_pin > 31) && (write->number > 31)) ) ) {
108+
self->data_write_same_register = true; // data pins and write pin are on the same register
109+
} else {
110+
self->data_write_same_register = false; // data pins and write pins are on different registers
111+
}
112+
113+
114+
self->write_mask = 1 << (write->number % 32); /* the write pin triggers the LCD to latch the data */
115+
116+
/* SNIP - common setup of the reset pin, same as from SAMD and NRF ports */
117+
self->reset.base.type = &mp_type_NoneType;
118+
if (reset != NULL) {
119+
self->reset.base.type = &digitalio_digitalinout_type;
120+
common_hal_digitalio_digitalinout_construct(&self->reset, reset);
121+
common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
122+
never_reset_pin_number(reset->number);
123+
common_hal_displayio_parallelbus_reset(self);
124+
}
125+
126+
never_reset_pin_number(command->number);
127+
never_reset_pin_number(chip_select->number);
128+
never_reset_pin_number(write->number);
129+
never_reset_pin_number(read->number);
130+
for (uint8_t i = 0; i < 8; i++) {
131+
never_reset_pin_number(data_pin + i);
132+
}
133+
41134
}
42135

43136
void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self) {
137+
/* SNIP - same as from SAMD and NRF ports */
138+
for (uint8_t i = 0; i < 8; i++) {
139+
reset_pin_number(self->data0_pin + i);
140+
}
44141

142+
reset_pin_number(self->command.pin->number);
143+
reset_pin_number(self->chip_select.pin->number);
144+
reset_pin_number(self->write.pin->number);
145+
reset_pin_number(self->read.pin->number);
146+
reset_pin_number(self->reset.pin->number);
45147
}
46148

47149
bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
48-
return false;
150+
/* SNIP - same as from SAMD and NRF ports */
151+
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
152+
if (self->reset.base.type == &mp_type_NoneType) {
153+
return false;
154+
}
155+
156+
common_hal_digitalio_digitalinout_set_value(&self->reset, false);
157+
common_hal_mcu_delay_us(4);
158+
common_hal_digitalio_digitalinout_set_value(&self->reset, true);
159+
return true;
160+
49161
}
50162

51163
bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
52-
return false;
164+
/* SNIP - same as from SAMD and NRF ports */
165+
return true;
53166
}
54167

55168
bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
56-
57-
return false;
169+
/* SNIP - same as from SAMD and NRF ports */
170+
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
171+
common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
172+
return true;
58173
}
59174

60175
void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type,
61-
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
176+
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
177+
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
178+
common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA);
179+
180+
uint32_t* clear_write = self->write_clear_register;
181+
uint32_t* set_write = self->write_set_register;
182+
183+
const uint32_t mask = self->write_mask;
184+
185+
/* Setup structures for data writing. The ESP32-S2 port differs from the SAMD and NRF ports
186+
* because I have not found a way to write a single byte into the ESP32-S2 registers.
187+
* For the ESP32-S2, I create a 32-bit data_buffer that is used to transfer the data bytes.
188+
*/
189+
190+
*clear_write = mask; // Clear the write pin to prepare the registers before storing the
191+
// register value into data_buffer
192+
193+
const uint32_t data_buffer = *self->bus; // store the initial output register values into the data output buffer
194+
uint8_t* data_address = ((uint8_t*) &data_buffer) + (self->data0_pin / 8); /* address inside data_buffer where
195+
* each data byte will be written to the data pin registers
196+
*/
197+
198+
199+
if ( self->data_write_same_register ) { // data and write pins are on the same register
200+
for (uint32_t i = 0; i < data_length; i++) {
201+
202+
/* Note: If the write pin and data pins are controlled by the same GPIO register, we can eliminate
203+
* the "clear_write" step below, since the write pin is cleared when the data_buffer is written
204+
* to the bus.
205+
*/
206+
207+
*(data_address) = data[i]; // stuff the data byte into the data_buffer at the correct offset byte location
208+
*self->bus = data_buffer; // write the data to the output register
209+
*set_write = mask; // set the write pin
210+
}
211+
}
212+
else { // data and write pins are on different registers
213+
for (uint32_t i = 0; i < data_length; i++) {
214+
*clear_write = mask; // clear the write pin (See comment above, this may not be necessary).
215+
*(data_address) = data[i]; // stuff the data byte into the data_buffer at the correct offset byte location
216+
*self->bus = data_buffer; // write the data to the output register
217+
*set_write = mask; // set the write pin
218+
219+
}
220+
}
62221

63222
}
64223

65224
void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {
66-
225+
/* SNIP - same as from SAMD and NRF ports */
226+
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
227+
common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
67228
}

ports/esp32s2/common-hal/displayio/ParallelBus.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@
3131

3232
typedef struct {
3333
mp_obj_base_t base;
34+
uint32_t* bus; // pointer where 8 bits of data are written to the display
35+
digitalio_digitalinout_obj_t command;
36+
digitalio_digitalinout_obj_t chip_select;
37+
digitalio_digitalinout_obj_t reset;
38+
digitalio_digitalinout_obj_t write;
39+
digitalio_digitalinout_obj_t read;
40+
uint8_t data0_pin; // pin number for the lowest number data pin. Must be 8-bit aligned
41+
bool data_write_same_register; // if data and write pins are in the sare
42+
uint32_t* write_set_register; // pointer to the write group for setting the write bit to latch the data on the LCD
43+
uint32_t* write_clear_register; // pointer to the write group for clearing the write bit to latch the data on the LCD
44+
uint32_t write_mask; // bit mask for the single bit for the write pin register
3445
} displayio_parallelbus_obj_t;
3546

3647
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DISPLAYIO_PARALLELBUS_H

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy