summaryrefslogtreecommitdiff
path: root/stmhal/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/spi.c')
-rw-r--r--stmhal/spi.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/stmhal/spi.c b/stmhal/spi.c
index bad71e87b..ba550f979 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -14,24 +14,28 @@
#include "bufhelper.h"
#include "spi.h"
-// Usage model:
-//
-// See usage model of I2C in i2c.c. SPI is very similar. Main difference is
-// parameters to init the SPI bus:
-//
-// from pyb import SPI
-// spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=1, crc=0x7)
-//
-// Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be
-// 0 or 1, and is the level the idle clock line sits at. Phase can be 1 or 2
-// for number of edges. Crc can be None for no CRC, or a polynomial specifier.
-//
-// Additional method for SPI:
-//
-// data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
-// buf = bytearray(4)
-// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
-// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
+/// \moduleref pyb
+/// \class SPI - a master-driven serial protocol
+///
+/// SPI is a serial protocol that is driven by a master. At the physical level
+/// there are 3 lines: SCK, MOSI, MISO.
+///
+/// See usage model of I2C; SPI is very similar. Main difference is
+/// parameters to init the SPI bus:
+///
+/// from pyb import SPI
+/// spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=1, crc=0x7)
+///
+/// Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be
+/// 0 or 1, and is the level the idle clock line sits at. Phase can be 1 or 2
+/// for number of edges. Crc can be None for no CRC, or a polynomial specifier.
+///
+/// Additional method for SPI:
+///
+/// data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
+/// buf = bytearray(4)
+/// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
+/// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
#if MICROPY_HW_ENABLE_SPI1
SPI_HandleTypeDef SPIHandle1 = {.Instance = NULL};
@@ -194,6 +198,12 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
}
}
+/// \method init(mode, baudrate=328125, *, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, ti=false, crc=None)
+///
+/// Initialise the SPI bus with the given parameters:
+///
+/// - `mode` must be either `SPI.MASTER` or `SPI.SLAVE`.
+/// - `baudrate` is the SCK clock rate (only sensible for a master).
STATIC const mp_arg_t pyb_spi_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 328125} },
@@ -258,6 +268,13 @@ STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, uint n_args, cons
return mp_const_none;
}
+/// \classmethod \constructor(bus, ...)
+///
+/// Construct an SPI object on the given bus. `bus` can be 1 or 2.
+/// With no additional parameters, the SPI object is created but not
+/// initialised (it has the settings from the last initialisation of
+/// the bus, if any). If extra arguments are given, the bus is initialised.
+/// See `init` for parameters of initialisation.
STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
@@ -288,6 +305,8 @@ STATIC mp_obj_t pyb_spi_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
+/// \method deinit()
+/// Turn off the SPI bus.
STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) {
pyb_spi_obj_t *self = self_in;
spi_deinit(self->spi);
@@ -295,6 +314,13 @@ STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_spi_deinit_obj, pyb_spi_deinit);
+/// \method send(send, *, timeout=5000)
+/// Send data on the bus:
+///
+/// - `send` is the data to send (an integer to send, or a buffer object).
+/// - `timeout` is the timeout in milliseconds to wait for the send.
+///
+/// Return value: `None`.
STATIC const mp_arg_t pyb_spi_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
@@ -327,6 +353,16 @@ STATIC mp_obj_t pyb_spi_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_obj, 1, pyb_spi_send);
+/// \method recv(recv, *, timeout=5000)
+///
+/// Receive data on the bus:
+///
+/// - `recv` can be an integer, which is the number of bytes to receive,
+/// or a mutable buffer, which will be filled with received bytes.
+/// - `timeout` is the timeout in milliseconds to wait for the receive.
+///
+/// Return value: if `recv` is an integer then a new buffer of the bytes received,
+/// otherwise the same buffer that was passed in to `recv`.
STATIC const mp_arg_t pyb_spi_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
@@ -363,6 +399,17 @@ STATIC mp_obj_t pyb_spi_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv);
+/// \method send_recv(send, recv=None, *, timeout=5000)
+///
+/// Send and receive data on the bus at the same time:
+///
+/// - `send` is the data to send (an integer to send, or a buffer object).
+/// - `recv` is a mutable buffer which will be filled with received bytes.
+/// It can be the same as `send`, or omitted. If omitted, a new buffer will
+/// be created.
+/// - `timeout` is the timeout in milliseconds to wait for the receive.
+///
+/// Return value: the buffer with the received bytes.
STATIC const mp_arg_t pyb_spi_send_recv_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
@@ -436,6 +483,10 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
// class constants
+ /// \constant MASTER - for initialising the bus to master mode
+ /// \constant SLAVE - for initialising the bus to slave mode
+ /// \constant MSB - set the first bit to MSB
+ /// \constant LSB - set the first bit to LSB
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLAVE), MP_OBJ_NEW_SMALL_INT(SPI_MODE_SLAVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(SPI_FIRSTBIT_MSB) },