8000 extmod/machine_spi.c: Support firstbit=machine.LSB for machine.SoftSPI. by robert-hh · Pull Request #15436 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

extmod/machine_spi.c: Support firstbit=machine.LSB for machine.SoftSPI. #15436

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 1 commit into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions drivers/bus/softspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,39 +44,48 @@ int mp_soft_spi_ioctl(void *self_in, uint32_t cmd) {
return 0;
}

static uint8_t swap_bits(uint8_t byte) {
const static uint8_t swap_table[16] = {
0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
};
return ((swap_table[byte & 0x0f] << 4) | swap_table[byte >> 4]);
}

void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
mp_soft_spi_obj_t *self = (mp_soft_spi_obj_t*)self_in;
uint32_t delay_half = self->delay_half;

// only MSB transfer is implemented

// If a port defines MICROPY_HW_SOFTSPI_MIN_DELAY, and the configured
// delay_half is equal to this value, then the software SPI implementation
// will run as fast as possible, limited only by CPU speed and GPIO time.
#ifdef MICROPY_HW_SOFTSPI_MIN_DELAY
if (delay_half == MICROPY_HW_SOFTSPI_MIN_DELAY) {
for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_out = self->firstbit != MICROPY_PY_MACHINE_SPI_MSB ?
src[i] : swap_bits(src[i]);
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
for (int j = 0; j < 8; ++j, data_out >>= 1) {
mp_hal_pin_write(self->mosi, data_out & 1);
mp_hal_pin_write(self->sck, 1 - self->polarity);
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
mp_hal_pin_write(self->sck, self->polarity);
}
if (dest != NULL) {
dest[i] = data_in;
dest[i] = self->firstbit == MICROPY_PY_MACHINE_SPI_MSB ?
data_in : swap_bits(data_in);
}
}
return;
}
#endif

for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_out = self->firstbit != MICROPY_PY_MACHINE_SPI_MSB ?
src[i] : swap_bits(src[i]);
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
for (int j = 0; j < 8; ++j, data_out >>= 1) {
mp_hal_pin_write(self->mosi, data_out & 1);
if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, 1 - self->polarity);
Expand All @@ -94,7 +103,8 @@ void mp_soft_spi_transfer(void *self_in, size_t len, const uint8_t *src, uint8_t
}
}
if (dest != NULL) {
dest[i] = data_in;
dest[i] = self->firstbit == MICROPY_PY_MACHINE_SPI_MSB ?
data_in : swap_bits(data_in);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions drivers/bus/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ typedef struct _mp_soft_spi_obj_t {
uint32_t delay_half; // microsecond delay for half SCK period
uint8_t polarity;
uint8_t phase;
uint8_t firstbit;
mp_hal_pin_obj_t sck;
mp_hal_pin_obj_t mosi;
mp_hal_pin_obj_t miso;
Expand Down
20 changes: 8 additions & 12 deletions extmod/machine_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@

#include "extmod/modmachine.h"

// if a port didn't define MSB/LSB constants then provide them
#ifndef MICROPY_PY_MACHINE_SPI_MSB
#define MICROPY_PY_MACHINE_SPI_MSB (0)
#define MICROPY_PY_MACHINE_SPI_LSB (1)
#endif

/******************************************************************************/
// MicroPython bindings for generic machine.SPI

Expand Down Expand Up @@ -154,9 +148,9 @@ static uint32_t baudrate_to_delay_half(uint32_t baudrate) {

static void mp_machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u,"
mp_printf(print, "SoftSPI(baudrate=%u, polarity=%u, phase=%u, firstbit=%u,"
" sck=" MP_HAL_PIN_FMT ", mosi=" MP_HAL_PIN_FMT ", miso=" MP_HAL_PIN_FMT ")",
baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase,
baudrate_from_delay_half(self->spi.delay_half), self->spi.polarity, self->spi.phase, self->spi.firstbit,
mp_hal_pin_name(self->spi.sck), mp_hal_pin_name(self->spi.mosi), mp_hal_pin_name(self->spi.miso));
}

Expand Down Expand Up @@ -185,9 +179,7 @@ static mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
if (args[ARG_bits].u_int != 8) {
mp_raise_ValueError(MP_ERROR_TEXT("bits must be 8"));
}
if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) {
mp_raise_ValueError(MP_ERROR_TEXT("firstbit must be MSB"));
}
self->spi.firstbit = args[ARG_firstbit].u_int;
if (args[ARG_sck].u_obj == MP_OBJ_NULL
|| args[ARG_mosi].u_obj == MP_OBJ_NULL
|| args[ARG_miso].u_obj == MP_OBJ_NULL) {
Expand All @@ -206,11 +198,12 @@ static mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in;

enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso };
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
Expand All @@ -227,6 +220,9 @@ static void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, cons
if (args[ARG_phase].u_int != -1) {
self->spi.phase = args[ARG_phase].u_int;
}
if (args[ARG_firstbit].u_int != -1) {
self->spi.firstbit = args[ARG_firstbit].u_int;
}
if (args[ARG_sck].u_obj != MP_OBJ_NULL) {
self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
}
Expand Down
2 changes: 0 add 8000 itions & 2 deletions ports/esp32/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@
#define MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SPI_MSB (0)
#define MICROPY_PY_MACHINE_SPI_LSB (1)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
#ifndef MICROPY_PY_MACHINE_DAC
#define MICROPY_PY_MACHINE_DAC (SOC_DAC_SUPPORTED)
Expand Down
6 changes: 6 additions & 0 deletions py/mpconfig.h
676B
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,12 @@ typedef double mp_float_t;
#define MICROPY_PY_MACHINE_SOFTSPI (0)
#endif

// Values of SPI.MSB and SPI.LSB constants
#ifndef MICROPY_PY_MACHINE_SPI_MSB
#define MICROPY_PY_MACHINE_SPI_MSB (0)
#define MICROPY_PY_MACHINE_SPI_LSB (1)
#endif

// Whether to provide the "machine.Timer" class
#ifndef MICROPY_PY_MACHINE_TIMER
#define MICROPY_PY_MACHINE_TIMER (0)
Expand Down
Loading
0