Skip to content

Add RP2040 displayio.ParallelBus Support #4130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 16, 2021
Merged
3 changes: 2 additions & 1 deletion ports/atmel-samd/boards/pyportal/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ void board_init(void) {
&pin_PB06, // Chip select
&pin_PB09, // Write
&pin_PB04, // Read
&pin_PA00); // Reset
&pin_PA00, // Reset
0); // Frequency

displayio_display_obj_t *display = &displays[0].display;
display->base.type = &displayio_display_type;
Expand Down
3 changes: 2 additions & 1 deletion ports/atmel-samd/boards/pyportal_titano/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ void board_init(void) {
&pin_PB06, // Chip select
&pin_PB09, // Write
&pin_PB04, // Read
&pin_PA00); // Reset
&pin_PA00, // Reset
0); // Frequency

displayio_display_obj_t *display = &displays[0].display;
display->base.type = &displayio_display_type;
Expand Down
22 changes: 11 additions & 11 deletions ports/atmel-samd/common-hal/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/microcontroller/__init__.h"

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* self,
const mcu_pin_obj_t* data0, const mcu_pin_obj_t* command, const mcu_pin_obj_t* chip_select,
const mcu_pin_obj_t* write, const mcu_pin_obj_t* read, const mcu_pin_obj_t* reset) {
void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) {

uint8_t data_pin = data0->number;
if (data_pin % 8 != 0) {
Expand All @@ -55,7 +55,7 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
wrconfig |= 0xff << (data_pin % 32);
}
g->WRCONFIG.reg = wrconfig;
self->bus = ((uint8_t*) &g->OUT.reg) + (data0->number % 32 / 8);
self->bus = ((uint8_t *)&g->OUT.reg) + (data0->number % 32 / 8);

self->command.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->command, command);
Expand Down Expand Up @@ -95,7 +95,7 @@ void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* sel
}
}

void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self) {
void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t *self) {
for (uint8_t i = 0; i < 8; i++) {
reset_pin_number(self->data0_pin + i);
}
Expand All @@ -108,7 +108,7 @@ void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self)
}

bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
if (self->reset.base.type == &mp_type_NoneType) {
return false;
}
Expand All @@ -124,17 +124,17 @@ bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
}

bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
return true;
}

void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA);
uint32_t* clear_write = (uint32_t*) &self->write_group->OUTCLR.reg;
uint32_t* set_write = (uint32_t*) &self->write_group->OUTSET.reg;
uint32_t *clear_write = (uint32_t *)&self->write_group->OUTCLR.reg;
uint32_t *set_write = (uint32_t *)&self->write_group->OUTSET.reg;
uint32_t mask = self->write_mask;
for (uint32_t i = 0; i < data_length; i++) {
*clear_write = mask;
Expand All @@ -144,6 +144,6 @@ void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byt
}

void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {
displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj);
displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
}
2 changes: 1 addition & 1 deletion ports/esp32s2/common-hal/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset) {
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) {

uint8_t data_pin = data0->number;
if (data_pin % 8 != 0) {
Expand Down
2 changes: 1 addition & 1 deletion ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset) {
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) {

mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
}
Expand Down
2 changes: 1 addition & 1 deletion ports/nrf/common-hal/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset) {
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) {

uint8_t data_pin = data0->number;
if (data_pin % 8 != 0) {
Expand Down
2 changes: 2 additions & 0 deletions ports/raspberrypi/bindings/rp2pio/StateMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self,
void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self);
bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self);

void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self);

void common_hal_rp2pio_statemachine_restart(rp2pio_statemachine_obj_t *self);
void common_hal_rp2pio_statemachine_stop(rp2pio_statemachine_obj_t *self);
void common_hal_rp2pio_statemachine_run(rp2pio_statemachine_obj_t *self, const uint16_t *instructions, size_t len);
Expand Down
107 changes: 99 additions & 8 deletions ports/raspberrypi/common-hal/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,128 @@
#include "py/runtime.h"
#include "shared-bindings/digitalio/DigitalInOut.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "bindings/rp2pio/StateMachine.h"
#include "common-hal/rp2pio/StateMachine.h"

static const uint16_t parallel_program[] = {
// .side_set 1
// .wrap_target
0x6008, // out pins, 8 side 0
0xB042 // nop side 1
// .wrap
};

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset) {
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) {

uint8_t data_pin = data0->number;
for (uint8_t i = 0; i < 8; i++) {
if (!pin_number_is_free(data_pin + i)) {
mp_raise_ValueError_varg(translate("Bus pin %d is already in use"), i);
}
}

uint8_t write_pin = write->number;
if (!pin_number_is_free(write_pin)) {
mp_raise_ValueError_varg(translate("Bus pin %d is already in use"), write_pin);
}

self->command.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->command, command);
common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL);

self->chip_select.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select);
common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL);

self->read.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->read, read);
common_hal_digitalio_digitalinout_switch_to_output(&self->read, true, DRIVE_MODE_PUSH_PULL);

self->data0_pin = data_pin;
self->write = write_pin;

self->reset.base.type = &mp_type_NoneType;
if (reset != NULL) {
self->reset.base.type = &digitalio_digitalinout_type;
common_hal_digitalio_digitalinout_construct(&self->reset, reset);
common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL);
never_reset_pin_number(reset->number);
common_hal_displayio_parallelbus_reset(self);
}

mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
// TODO: Implement with PIO and DMA.
never_reset_pin_number(command->number);
never_reset_pin_number(chip_select->number);
never_reset_pin_number(write_pin);
never_reset_pin_number(read->number);
for (uint8_t i = 0; i < 8; i++) {
never_reset_pin_number(data_pin + i);
}

common_hal_rp2pio_statemachine_construct(&self->state_machine,
parallel_program, sizeof(parallel_program) / sizeof(parallel_program[0]),
frequency * 2, // frequency multiplied by 2 as 2 PIO instructions
NULL, 0, // init
data0, 8, 0, 255, // first out pin, # out pins
NULL, 0, 0, 0, // first in pin, # in pins
NULL, 0, 0, 0, // first set pin
write, 1, 0, 1, // first sideset pin
true, // exclusive pin usage
true, 8, true, // TX, auto pull every 8 bits. shift left to output msb first
false, // wait for TX stall
false, 32, true // RX setting we don't use
);

common_hal_rp2pio_statemachine_never_reset(&self->state_machine);
}

void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t *self) {
common_hal_rp2pio_statemachine_deinit(&self->state_machine);

for (uint8_t i = 0; i < 8; i++) {
reset_pin_number(self->data0_pin + i);
}

reset_pin_number(self->command.pin->number);
reset_pin_number(self->chip_select.pin->number);
reset_pin_number(self->write);
reset_pin_number(self->read.pin->number);
reset_pin_number(self->reset.pin->number);
}

bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
return false;
displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
if (self->reset.base.type == &mp_type_NoneType) {
return false;
}

common_hal_digitalio_digitalinout_set_value(&self->reset, false);
common_hal_mcu_delay_us(4);
common_hal_digitalio_digitalinout_set_value(&self->reset, true);
return true;
}

bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
return false;
return true;
}

bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {

return false;
displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->chip_select, false);
return true;
}

void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type,
display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) {

displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);

common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA);
common_hal_rp2pio_statemachine_write(&self->state_machine, data, data_length, 1);
}

void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {

displayio_parallelbus_obj_t *self = MP_OBJ_TO_PTR(obj);
common_hal_digitalio_digitalinout_set_value(&self->chip_select, true);
}
9 changes: 9 additions & 0 deletions ports/raspberrypi/common-hal/displayio/ParallelBus.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,18 @@
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_DISPLAYIO_PARALLELBUS_H

#include "common-hal/digitalio/DigitalInOut.h"
#include "bindings/rp2pio/StateMachine.h"
#include "common-hal/rp2pio/StateMachine.h"

typedef struct {
mp_obj_base_t base;
digitalio_digitalinout_obj_t command;
digitalio_digitalinout_obj_t chip_select;
digitalio_digitalinout_obj_t reset;
digitalio_digitalinout_obj_t read;
uint8_t write;
uint8_t data0_pin;
rp2pio_statemachine_obj_t state_machine;
} displayio_parallelbus_obj_t;

#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
2 changes: 1 addition & 1 deletion ports/stm/common-hal/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset) {
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) {

mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
}
Expand Down
5 changes: 3 additions & 2 deletions shared-bindings/displayio/ParallelBus.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,15 @@
//| ...
//|
STATIC mp_obj_t displayio_parallelbus_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_data0, ARG_command, ARG_chip_select, ARG_write, ARG_read, ARG_reset };
enum { ARG_data0, ARG_command, ARG_chip_select, ARG_write, ARG_read, ARG_reset, ARG_frequency };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_data0, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_command, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_chip_select, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_write, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_read, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_reset, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
{ MP_QSTR_frequency, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 30000000 } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
Expand All @@ -82,7 +83,7 @@ STATIC mp_obj_t displayio_parallelbus_make_new(const mp_obj_type_t *type, size_t
displayio_parallelbus_obj_t *self = &allocate_display_bus_or_raise()->parallel_bus;
self->base.type = &displayio_parallelbus_type;

common_hal_displayio_parallelbus_construct(self, data0, command, chip_select, write, read, reset);
common_hal_displayio_parallelbus_construct(self, data0, command, chip_select, write, read, reset, args[ARG_frequency].u_int);
return self;
}

Expand Down
2 changes: 1 addition & 1 deletion shared-bindings/displayio/ParallelBus.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extern const mp_obj_type_t displayio_parallelbus_type;

void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t *self,
const mcu_pin_obj_t *data0, const mcu_pin_obj_t *command, const mcu_pin_obj_t *chip_select,
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset);
const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency);

void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t *self);

Expand Down