Commit b932b2dd authored by Damien George's avatar Damien George
Browse files

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.
parent 9f1e395c
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment