From b932b2dd1faaf3091b13af7d213041a737e40fac Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 4 Oct 2016 13:43:02 +1100 Subject: [PATCH] extmod/machine_spi: Use delay_half, not baudrate, for internal timing. The delay_half parameter must be specified by the port to set up the timing of the software SPI. This allows the port to adjust the timing value to better suit its timing characteristics, as well as provide a more accurate printing of the baudrate. --- esp8266/modpybspi.c | 20 +++++++++++++++++--- extmod/machine_spi.c | 4 +++- extmod/machine_spi.h | 2 +- stmhal/spi.c | 19 ++++++++++++++++--- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/esp8266/modpybspi.c b/esp8266/modpybspi.c index acc3c25125..e974547111 100644 --- a/esp8266/modpybspi.c +++ b/esp8266/modpybspi.c @@ -36,10 +36,24 @@ /******************************************************************************/ // MicroPython bindings for SPI +STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) { + return 500000 / delay_half; +} + +STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) { + uint32_t delay_half = 500000 / baudrate; + // round delay_half up so that: actual_baudrate <= requested_baudrate + if (500000 % baudrate != 0) { + delay_half += 1; + } + return delay_half; +} + STATIC void pyb_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, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)", - self->baudrate, self->polarity, self->phase, self->sck, self->mosi, self->miso); + baudrate_from_delay_half(self->delay_half), + self->polarity, self->phase, self->sck, self->mosi, self->miso); } STATIC void pyb_spi_init_helper(mp_machine_soft_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -56,7 +70,7 @@ STATIC void pyb_spi_init_helper(mp_machine_soft_spi_obj_t *self, size_t n_args, mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_baudrate].u_int != -1) { - self->baudrate = args[ARG_baudrate].u_int; + self->delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int); } if (args[ARG_polarity].u_int != -1) { self->polarity = args[ARG_polarity].u_int; @@ -86,7 +100,7 @@ mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t); self->base.type = &pyb_spi_type; // set defaults - self->baudrate = 500000; + self->delay_half = baudrate_to_delay_half(500000); self->polarity = 0; self->phase = 0; self->sck = 14; diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index 3a34b7fb08..b0bd76faf9 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -34,8 +34,10 @@ void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) { mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in; + uint32_t delay_half = self->delay_half; + // only MSB transfer is implemented - uint32_t delay_half = 500000 / self->baudrate + 1; + for (size_t i = 0; i < len; ++i) { uint8_t data_out = src[i]; uint8_t data_in = 0; diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h index e1922c6e8b..316d06646e 100644 --- a/extmod/machine_spi.h +++ b/extmod/machine_spi.h @@ -37,7 +37,7 @@ typedef struct _mp_machine_spi_p_t { typedef struct _mp_machine_soft_spi_obj_t { mp_obj_base_t base; - uint32_t baudrate; + uint32_t delay_half; // microsecond delay for half SCK period uint8_t polarity; uint8_t phase; mp_hal_pin_obj_t sck; diff --git a/stmhal/spi.c b/stmhal/spi.c index 46da05facf..8ec6f86275 100644 --- a/stmhal/spi.c +++ b/stmhal/spi.c @@ -944,10 +944,23 @@ STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_tab /* code for soft implementation ***********************************************/ +STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) { + return 500000 / delay_half; +} + +STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) { + uint32_t delay_half = 500000 / baudrate; + // round delay_half up so that: actual_baudrate <= requested_baudrate + if (500000 % baudrate != 0) { + delay_half += 1; + } + return delay_half; +} + STATIC void 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, "SPI(-1, baudrate=%u, polarity=%u, phase=%u, sck=%q, mosi=%q, miso=%q)", - self->baudrate, self->polarity, self->phase, + baudrate_from_delay_half(self->delay_half), self->polarity, self->phase, self->sck->name, self->mosi->name, self->miso->name); } @@ -957,7 +970,7 @@ STATIC mp_obj_t machine_soft_spi_make_new(mp_arg_val_t *args) { self->base.type = &machine_soft_spi_type; // set parameters - self->baudrate = args[ARG_NEW_baudrate].u_int; + self->delay_half = baudrate_to_delay_half(args[ARG_NEW_baudrate].u_int); self->polarity = args[ARG_NEW_polarity].u_int; self->phase = args[ARG_NEW_phase].u_int; if (args[ARG_NEW_bits].u_int != 8) { @@ -989,7 +1002,7 @@ STATIC void machine_soft_spi_init(mp_obj_t self_in, mp_arg_val_t *args) { // update parameters if (args[ARG_INIT_baudrate].u_int != -1) { - self->baudrate = args[ARG_INIT_baudrate].u_int; + self->delay_half = baudrate_to_delay_half(args[ARG_INIT_baudrate].u_int); } if (args[ARG_INIT_polarity].u_int != -1) { self->polarity = args[ARG_INIT_polarity].u_int;