Skip to content

Commit b932b2d

Browse files
committed
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.
1 parent 9f1e395 commit b932b2d

4 files changed

Lines changed: 37 additions & 8 deletions

File tree

esp8266/modpybspi.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,24 @@
3636
/******************************************************************************/
3737
// MicroPython bindings for SPI
3838

39+
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
40+
return 500000 / delay_half;
41+
}
42+
43+
STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) {
44+
uint32_t delay_half = 500000 / baudrate;
45+
// round delay_half up so that: actual_baudrate <= requested_baudrate
46+
if (500000 % baudrate != 0) {
47+
delay_half += 1;
48+
}
49+
return delay_half;
50+
}
51+
3952
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
4053
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
4154
mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)",
42-
self->baudrate, self->polarity, self->phase, self->sck, self->mosi, self->miso);
55+
baudrate_from_delay_half(self->delay_half),
56+
self->polarity, self->phase, self->sck, self->mosi, self->miso);
4357
}
4458

4559
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,
5670
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
5771

5872
if (args[ARG_baudrate].u_int != -1) {
59-
self->baudrate = args[ARG_baudrate].u_int;
73+
self->delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int);
6074
}
6175
if (args[ARG_polarity].u_int != -1) {
6276
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,
86100
mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t);
87101
self->base.type = &pyb_spi_type;
88102
// set defaults
89-
self->baudrate = 500000;
103+
self->delay_half = baudrate_to_delay_half(500000);
90104
self->polarity = 0;
91105
self->phase = 0;
92106
self->sck = 14;

extmod/machine_spi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@
3434

3535
void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
3636
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in;
37+
uint32_t delay_half = self->delay_half;
38+
3739
// only MSB transfer is implemented
38-
uint32_t delay_half = 500000 / self->baudrate + 1;
40+
3941
for (size_t i = 0; i < len; ++i) {
4042
uint8_t data_out = src[i];
4143
uint8_t data_in = 0;

extmod/machine_spi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ typedef struct _mp_machine_spi_p_t {
3737

3838
typedef struct _mp_machine_soft_spi_obj_t {
3939
mp_obj_base_t base;
40-
uint32_t baudrate;
40+
uint32_t delay_half; // microsecond delay for half SCK period
4141
uint8_t polarity;
4242
uint8_t phase;
4343
mp_hal_pin_obj_t sck;

stmhal/spi.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -944,10 +944,23 @@ STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_tab
944944

945945
/* code for soft implementation ***********************************************/
946946

947+
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
948+
return 500000 / delay_half;
949+
}
950+
951+
STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) {
952+
uint32_t delay_half = 500000 / baudrate;
953+
// round delay_half up so that: actual_baudrate <= requested_baudrate
954+
if (500000 % baudrate != 0) {
955+
delay_half += 1;
956+
}
957+
return delay_half;
958+
}
959+
947960
STATIC void machine_soft_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
948961
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
949962
mp_printf(print, "SPI(-1, baudrate=%u, polarity=%u, phase=%u, sck=%q, mosi=%q, miso=%q)",
950-
self->baudrate, self->polarity, self->phase,
963+
baudrate_from_delay_half(self->delay_half), self->polarity, self->phase,
951964
self->sck->name, self->mosi->name, self->miso->name);
952965
}
953966

@@ -957,7 +970,7 @@ STATIC mp_obj_t machine_soft_spi_make_new(mp_arg_val_t *args) {
957970
self->base.type = &machine_soft_spi_type;
958971

959972
// set parameters
960-
self->baudrate = args[ARG_NEW_baudrate].u_int;
973+
self->delay_half = baudrate_to_delay_half(args[ARG_NEW_baudrate].u_int);
961974
self->polarity = args[ARG_NEW_polarity].u_int;
962975
self->phase = args[ARG_NEW_phase].u_int;
963976
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) {
9891002

9901003
// update parameters
9911004
if (args[ARG_INIT_baudrate].u_int != -1) {
992-
self->baudrate = args[ARG_INIT_baudrate].u_int;
1005+
self->delay_half = baudrate_to_delay_half(args[ARG_INIT_baudrate].u_int);
9931006
}
9941007
if (args[ARG_INIT_polarity].u_int != -1) {
9951008
self->polarity = args[ARG_INIT_polarity].u_int;

0 commit comments

Comments
 (0)