cc3200: New SPI API.
This commit is contained in:
parent
624cdeacc4
commit
aba75e1233
@ -43,28 +43,11 @@
|
||||
#include "pybspi.h"
|
||||
#include "mpexception.h"
|
||||
#include "pybsleep.h"
|
||||
#include "pybpin.h"
|
||||
#include "pins.h"
|
||||
|
||||
/// \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=2000000, bits=8, polarity=0, phase=0, cs_polarity=SPI.ACTIVE_LOW)
|
||||
///
|
||||
/// Only required parameter is the baudrate, in Hz. polarity and phase may be 0 or 1.
|
||||
/// Bit accepts 8, 16, 32. Chip select values are ACTIVE_LOW and ACTIVE_HIGH
|
||||
///
|
||||
/// 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
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE TYPES
|
||||
@ -73,10 +56,6 @@ typedef struct _pyb_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint baudrate;
|
||||
uint config;
|
||||
vstr_t tx_vstr;
|
||||
vstr_t rx_vstr;
|
||||
uint tx_index;
|
||||
uint rx_index;
|
||||
byte polarity;
|
||||
byte phase;
|
||||
byte submode;
|
||||
@ -86,13 +65,15 @@ typedef struct _pyb_spi_obj_t {
|
||||
/******************************************************************************
|
||||
DEFINE CONSTANTS
|
||||
******************************************************************************/
|
||||
#define PYBSPI_DEF_BAUDRATE 1000000 // 1MHz
|
||||
#define PYBSPI_FIRST_BIT_MSB 0
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PRIVATE DATA
|
||||
******************************************************************************/
|
||||
STATIC pyb_spi_obj_t pyb_spi_obj = {.baudrate = 0};
|
||||
|
||||
STATIC const mp_obj_t pyb_spi_def_pin[3] = {&pin_GP14, &pin_GP16, &pin_GP30};
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
@ -112,8 +93,7 @@ STATIC void pybspi_init (const pyb_spi_obj_t *self) {
|
||||
}
|
||||
|
||||
STATIC void pybspi_tx (pyb_spi_obj_t *self, const void *data) {
|
||||
uint32_t txdata = 0xFFFFFFFF;
|
||||
if (data) {
|
||||
uint32_t txdata;
|
||||
switch (self->wlen) {
|
||||
case 1:
|
||||
txdata = (uint8_t)(*(char *)data);
|
||||
@ -127,7 +107,6 @@ STATIC void pybspi_tx (pyb_spi_obj_t *self, const void *data) {
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
MAP_SPIDataPut (GSPI_BASE, txdata);
|
||||
}
|
||||
|
||||
@ -151,11 +130,14 @@ STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len) {
|
||||
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
|
||||
if (!self->baudrate) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
|
||||
}
|
||||
// send and receive the data
|
||||
MAP_SPICSEnable(GSPI_BASE);
|
||||
for (int i = 0; i < len / self->wlen; i += self->wlen) {
|
||||
pybspi_tx(self, txdata ? (const void *)&txdata[i] : NULL);
|
||||
for (int i = 0; i < len; i += self->wlen) {
|
||||
pybspi_tx(self, txdata ? (const void *)&txdata[i] : txchar);
|
||||
pybspi_rx(self, rxdata ? (void *)&rxdata[i] : NULL);
|
||||
}
|
||||
MAP_SPICSDisable(GSPI_BASE);
|
||||
@ -166,40 +148,15 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
|
||||
/******************************************************************************/
|
||||
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_spi_obj_t *self = self_in;
|
||||
|
||||
if (self->baudrate > 0) {
|
||||
mp_printf(print, "<SPI1, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, cs_polarity=%q>",
|
||||
self->baudrate, (self->wlen * 8), self->polarity, self->phase,
|
||||
(self->config & SPI_CS_ACTIVELOW) ? MP_QSTR_ACTIVE_LOW : MP_QSTR_ACTIVE_HIGH);
|
||||
mp_printf(print, "SPI(0, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
|
||||
self->baudrate, (self->wlen * 8), self->polarity, self->phase);
|
||||
} else {
|
||||
mp_print_str(print, "<SPI1>");
|
||||
mp_print_str(print, "SPI(0)");
|
||||
}
|
||||
}
|
||||
|
||||
/// \method init(mode, *, baudrate=1000000, bits=8, polarity=0, phase=0, cs_polarity=SPI.ACTIVE_LOW)
|
||||
///
|
||||
/// Initialise the SPI bus with the given parameters:
|
||||
///
|
||||
/// - `mode` must be MASTER.
|
||||
/// - `baudrate` is the SCK clock rate.
|
||||
/// - `bits` is the transfer width size (8, 16, 32).
|
||||
/// - `polarity` (0, 1).
|
||||
/// - `phase` (0, 1).
|
||||
/// - `cs_polarity` can be ACTIVE_LOW or ACTIVE_HIGH.
|
||||
static const mp_arg_t pybspi_init_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
|
||||
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_DEF_BAUDRATE} },
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_cs_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_CS_ACTIVELOW} },
|
||||
};
|
||||
|
||||
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
// parse args
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(pybspi_init_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pybspi_init_args), pybspi_init_args, args);
|
||||
|
||||
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_arg_val_t *args) {
|
||||
// verify that mode is master
|
||||
if (args[0].u_int != SPI_MODE_MASTER) {
|
||||
goto invalid_args;
|
||||
@ -227,19 +184,36 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
uint cs = args[5].u_int;
|
||||
if (cs != SPI_CS_ACTIVELOW && cs != SPI_CS_ACTIVEHIGH) {
|
||||
uint firstbit = args[5].u_int;
|
||||
if (firstbit != PYBSPI_FIRST_BIT_MSB) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
// build the configuration
|
||||
self->baudrate = args[1].u_int;
|
||||
self->wlen = args[2].u_int >> 3;
|
||||
self->config = bits | cs | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
|
||||
self->config = bits | SPI_CS_ACTIVELOW | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
|
||||
self->polarity = polarity;
|
||||
self->phase = phase;
|
||||
self->submode = (polarity << 1) | phase;
|
||||
|
||||
// assign the pins
|
||||
mp_obj_t pins_o = args[6].u_obj;
|
||||
if (pins_o != mp_const_none) {
|
||||
mp_obj_t *pins;
|
||||
mp_uint_t n_pins = 3;
|
||||
if (pins_o == MP_OBJ_NULL) {
|
||||
// use the default pins
|
||||
pins = (mp_obj_t *)pyb_spi_def_pin;
|
||||
} else {
|
||||
mp_obj_get_array(pins_o, &n_pins, &pins);
|
||||
if (n_pins != 3) {
|
||||
goto invalid_args;
|
||||
}
|
||||
}
|
||||
pin_assign_pins_af (pins, n_pins, PIN_TYPE_STD_PU, PIN_FN_SPI, 0);
|
||||
}
|
||||
|
||||
// init the bus
|
||||
pybspi_init((const pyb_spi_obj_t *)self);
|
||||
|
||||
@ -252,32 +226,43 @@ invalid_args:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
|
||||
/// \classmethod \constructor(bus, ...)
|
||||
///
|
||||
/// Construct an SPI object with the given baudrate. Bus can only be 1.
|
||||
/// With no extra 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, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
static const mp_arg_t pyb_spi_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = SPI_MODE_MASTER} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1MHz
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_FIRST_BIT_MSB} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args)];
|
||||
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_spi_init_args, args);
|
||||
|
||||
// check the peripheral id
|
||||
if (args[0].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
}
|
||||
|
||||
// setup the object
|
||||
pyb_spi_obj_t *self = &pyb_spi_obj;
|
||||
self->base.type = &pyb_spi_type;
|
||||
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// start the peripheral
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_spi_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
}
|
||||
pyb_spi_init_helper(self, &args[1]);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_spi_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
STATIC mp_obj_t pyb_spi_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
// parse args
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args) - 1];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_spi_init_args[1], args);
|
||||
return pyb_spi_init_helper(pos_args[0], args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
|
||||
|
||||
@ -295,152 +280,112 @@ 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 (a byte to send, or a buffer object).
|
||||
/// - `timeout` is the timeout in milliseconds to wait for the send.
|
||||
///
|
||||
STATIC mp_obj_t pyb_spi_send (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
|
||||
};
|
||||
|
||||
STATIC mp_obj_t pyb_spi_write (mp_obj_t self_in, mp_obj_t buf) {
|
||||
// parse args
|
||||
pyb_spi_obj_t *self = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
pyb_spi_obj_t *self = self_in;
|
||||
|
||||
// get the buffer to send from
|
||||
mp_buffer_info_t bufinfo;
|
||||
uint8_t data[1];
|
||||
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
|
||||
pyb_buf_get_for_send(buf, &bufinfo, data);
|
||||
|
||||
// just send
|
||||
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len);
|
||||
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len, NULL);
|
||||
|
||||
return mp_const_none;
|
||||
// return the number of bytes written
|
||||
return mp_obj_new_int(bufinfo.len);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_obj, 1, pyb_spi_send);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
|
||||
|
||||
/// \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: if `recv` is an integer then a new buffer of the bytes received,
|
||||
/// otherwise the same buffer that was passed in to `recv`.
|
||||
STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
STATIC mp_obj_t pyb_spi_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
|
||||
{ MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
pyb_spi_obj_t *self = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
|
||||
|
||||
// get the buffer to receive into
|
||||
vstr_t vstr;
|
||||
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
|
||||
pyb_buf_get_for_recv(args[0].u_obj, &vstr);
|
||||
|
||||
// just receive
|
||||
pybspi_transfer(self, NULL, vstr.buf, vstr.len);
|
||||
uint32_t write = args[1].u_int;
|
||||
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
|
||||
|
||||
// return the received data
|
||||
if (o_ret != MP_OBJ_NULL) {
|
||||
return o_ret;
|
||||
} else {
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read);
|
||||
|
||||
/// \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 transaction to complete.
|
||||
///
|
||||
/// Return: the buffer with the received bytes.
|
||||
STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
STATIC mp_obj_t pyb_spi_readinto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
|
||||
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
pyb_spi_obj_t *self = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get buffers to send from/receive to
|
||||
mp_buffer_info_t bufinfo_send;
|
||||
uint8_t data_send[1];
|
||||
mp_buffer_info_t bufinfo_recv;
|
||||
vstr_t vstr_recv;
|
||||
mp_obj_t o_ret;
|
||||
|
||||
if (args[0].u_obj == args[1].u_obj) {
|
||||
// same object for sending and receiving, it must be a r/w buffer
|
||||
mp_get_buffer_raise(args[0].u_obj, &bufinfo_send, MP_BUFFER_RW);
|
||||
bufinfo_recv = bufinfo_send;
|
||||
o_ret = args[0].u_obj;
|
||||
} else {
|
||||
// get the buffer to send from
|
||||
pyb_buf_get_for_send(args[0].u_obj, &bufinfo_send, data_send);
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
|
||||
|
||||
// get the buffer to receive into
|
||||
if (args[1].u_obj == mp_const_none) {
|
||||
// only the send was argument given, so create a fresh buffer of the send length
|
||||
vstr_init_len(&vstr_recv, bufinfo_send.len);
|
||||
bufinfo_recv.len = vstr_recv.len;
|
||||
bufinfo_recv.buf = vstr_recv.buf;
|
||||
o_ret = MP_OBJ_NULL;
|
||||
} else {
|
||||
// recv argument given
|
||||
mp_get_buffer_raise(args[1].u_obj, &bufinfo_recv, MP_BUFFER_WRITE);
|
||||
if (bufinfo_recv.len != bufinfo_send.len) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
vstr_t vstr;
|
||||
pyb_buf_get_for_recv(args[0].u_obj, &vstr);
|
||||
|
||||
// just receive
|
||||
uint32_t write = args[1].u_int;
|
||||
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
|
||||
|
||||
// return the number of bytes received
|
||||
return mp_obj_new_int(vstr.len);
|
||||
}
|
||||
o_ret = args[1].u_obj;
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_readinto_obj, 1, pyb_spi_readinto);
|
||||
|
||||
STATIC mp_obj_t pyb_spi_write_readinto (mp_obj_t self, mp_obj_t writebuf, mp_obj_t readbuf) {
|
||||
// get buffers to write from/read to
|
||||
mp_buffer_info_t bufinfo_write;
|
||||
uint8_t data_send[1];
|
||||
mp_buffer_info_t bufinfo_read;
|
||||
|
||||
if (writebuf == readbuf) {
|
||||
// same object for writing and reading, it must be a r/w buffer
|
||||
mp_get_buffer_raise(writebuf, &bufinfo_write, MP_BUFFER_RW);
|
||||
bufinfo_read = bufinfo_write;
|
||||
} else {
|
||||
// get the buffer to write from
|
||||
pyb_buf_get_for_send(writebuf, &bufinfo_write, data_send);
|
||||
|
||||
// get the read buffer
|
||||
mp_get_buffer_raise(readbuf, &bufinfo_read, MP_BUFFER_WRITE);
|
||||
if (bufinfo_read.len != bufinfo_write.len) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
}
|
||||
|
||||
// send and receive
|
||||
pybspi_transfer(self, (const char *)bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
|
||||
pybspi_transfer(self, (const char *)bufinfo_write.buf, bufinfo_read.buf, bufinfo_write.len, NULL);
|
||||
|
||||
// return the received data
|
||||
if (o_ret != MP_OBJ_NULL) {
|
||||
return o_ret;
|
||||
} else {
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv);
|
||||
// return the number of transferred bytes
|
||||
return mp_obj_new_int(bufinfo_write.len);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto);
|
||||
|
||||
STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_spi_init_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_spi_deinit_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_spi_send_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_spi_recv_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_spi_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_spi_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&pyb_spi_readinto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&pyb_spi_write_readinto_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_LOW), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVELOW) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_HIGH), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVEHIGH) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(PYBSPI_FIRST_BIT_MSB) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
|
||||
|
@ -454,7 +454,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
|
||||
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_uart_init_args, args);
|
||||
|
||||
// work out the uart id
|
||||
uint8_t uart_id;
|
||||
uint uart_id;
|
||||
if (args[0].u_obj == mp_const_none) {
|
||||
if (args[5].u_obj != MP_OBJ_NULL) {
|
||||
mp_obj_t *pins;
|
||||
@ -474,7 +474,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
|
||||
uart_id = mp_obj_get_int(args[0].u_obj);
|
||||
}
|
||||
|
||||
if (uart_id < PYB_UART_0 || uart_id > PYB_UART_1) {
|
||||
if (uart_id > PYB_UART_1) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
}
|
||||
|
||||
|
@ -339,21 +339,24 @@ Q(RTC_WAKE)
|
||||
|
||||
// for SPI class
|
||||
Q(SPI)
|
||||
Q(id)
|
||||
Q(mode)
|
||||
Q(baudrate)
|
||||
Q(bits)
|
||||
Q(polarity)
|
||||
Q(phase)
|
||||
Q(cs_polarity)
|
||||
Q(firstbit)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(send)
|
||||
Q(recv)
|
||||
Q(send_recv)
|
||||
Q(timeout)
|
||||
Q(write)
|
||||
Q(read)
|
||||
Q(readinto)
|
||||
Q(write_readinto)
|
||||
Q(nbytes)
|
||||
Q(write)
|
||||
Q(buf)
|
||||
Q(MASTER)
|
||||
Q(ACTIVE_LOW)
|
||||
Q(ACTIVE_HIGH)
|
||||
Q(MSB)
|
||||
|
||||
// for Timer class
|
||||
Q(Timer)
|
||||
|
@ -19,18 +19,6 @@ there are 3 lines: SCK, MOSI, MISO.
|
||||
to sample data on the first or second clock edge respectively. Crc can be
|
||||
None for no CRC, or a polynomial specifier.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
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=1000000, polarity=0, phase=0, cs_polarity=SPI.ACTIVE_LOW)
|
||||
|
||||
Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
|
||||
1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
|
||||
sample data on the first or second clock edge respectively.
|
||||
|
||||
Additional methods for SPI::
|
||||
|
||||
data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
|
||||
@ -38,6 +26,17 @@ Additional methods for SPI::
|
||||
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
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
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=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
|
||||
Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
|
||||
1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
|
||||
sample data on the first or second clock edge respectively.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
@ -105,7 +104,7 @@ Methods
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: spi.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, nss=SPI.ACTIVE_LOW)
|
||||
.. method:: spi.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO))
|
||||
|
||||
Initialise the SPI bus with the given parameters:
|
||||
|
||||
@ -115,11 +114,32 @@ Methods
|
||||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
|
||||
respectively.
|
||||
- ``bits`` is the width of each transfer, accepted values are 8, 16 and 32.
|
||||
- ``cs_polarity`` can be ``SPI.ACTIVE_LOW`` or ``SPI.ACTIVE_HIGH``.
|
||||
- ``firstbit`` can be ``SPI.MSB`` only.
|
||||
- ``pins`` is an optional tupple with the pins to assign to the SPI bus.
|
||||
|
||||
Note that the SPI clock frequency will not always be the requested baudrate.
|
||||
Printing the SPI object will show you the computed baudrate and the chosen
|
||||
prescaler.
|
||||
.. method:: spi.write(buf)
|
||||
|
||||
Write the data contained in ``buf``.
|
||||
Returns the number of bytes written.
|
||||
|
||||
.. method:: spi.read(nbytes, *, write=0x00)
|
||||
|
||||
Read the ``nbytes`` while writing the data specified by ``write``.
|
||||
Return the number of bytes read.
|
||||
|
||||
.. method:: spi.readinto(buf, *, write=0x00)
|
||||
|
||||
Read into the buffer specified by ``buf`` while writing the data specified by
|
||||
``write``.
|
||||
Return the number of bytes read.
|
||||
|
||||
.. method:: spi.write_readinto(write_buf, read_buf)
|
||||
|
||||
Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the
|
||||
same length.
|
||||
Returns the number of bytes written
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. method:: spi.recv(recv, \*, timeout=5000)
|
||||
|
||||
@ -174,7 +194,6 @@ Constants
|
||||
|
||||
for initialising the SPI bus to master
|
||||
|
||||
.. data:: SPI.ACTIVE_LOW
|
||||
.. data:: SPI.ACTIVE_HIGH
|
||||
.. data:: SPI.MSB
|
||||
|
||||
selects the polarity of the NSS pin
|
||||
set the first bit to be the most significant bit
|
||||
|
149
tests/wipy/spi.py
Normal file
149
tests/wipy/spi.py
Normal file
@ -0,0 +1,149 @@
|
||||
'''
|
||||
SPI test for the CC3200 based boards.
|
||||
'''
|
||||
|
||||
from pyb import SPI
|
||||
from pyb import Pin
|
||||
import os
|
||||
import pyb
|
||||
|
||||
machine = os.uname().machine
|
||||
if 'LaunchPad' in machine:
|
||||
spi_pins = ('GP14', 'GP16', 'GP30')
|
||||
elif 'WiPy' in machine:
|
||||
spi_pins = ('GP14', 'GP16', 'GP30')
|
||||
else:
|
||||
raise Exception('Board not supported!')
|
||||
|
||||
spi = SPI(0, SPI.MASTER, baudrate=2000000, polarity=0, phase=0, firstbit=SPI.MSB, pins=spi_pins)
|
||||
print(spi)
|
||||
spi = SPI(baudrate=5000000)
|
||||
print(spi)
|
||||
spi = SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0)
|
||||
print(spi)
|
||||
spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=1)
|
||||
print(spi)
|
||||
spi = SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0)
|
||||
print(spi)
|
||||
spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=1, phase=1)
|
||||
print(spi)
|
||||
spi.init(baudrate=20000000, polarity=0, phase=0)
|
||||
print(spi)
|
||||
spi=SPI()
|
||||
print(spi)
|
||||
SPI(mode=SPI.MASTER)
|
||||
SPI(mode=SPI.MASTER, pins=spi_pins)
|
||||
SPI(id=0, mode=SPI.MASTER, polarity=0, phase=0, pins=('GP14', 'GP16', 'GP15'))
|
||||
SPI(0, SPI.MASTER, polarity=0, phase=0, pins=('GP31', 'GP16', 'GP15'))
|
||||
|
||||
spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=0, pins=spi_pins)
|
||||
print(spi.write('123456') == 6)
|
||||
buffer_r = bytearray(10)
|
||||
print(spi.readinto(buffer_r) == 10)
|
||||
print(spi.readinto(buffer_r, write=0x55) == 10)
|
||||
read = spi.read(10)
|
||||
print(len(read) == 10)
|
||||
read = spi.read(10, write=0xFF)
|
||||
print(len(read) == 10)
|
||||
buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
|
||||
print(spi.write_readinto(buffer_w, buffer_r) == 10)
|
||||
print(buffer_w == buffer_r)
|
||||
|
||||
# test all polaritiy and phase combinations
|
||||
spi.init(polarity=1, phase=0, pins=None)
|
||||
buffer_r = bytearray(10)
|
||||
spi.write_readinto(buffer_w, buffer_r)
|
||||
print(buffer_w == buffer_r)
|
||||
|
||||
spi.init(polarity=1, phase=1, pins=None)
|
||||
buffer_r = bytearray(10)
|
||||
spi.write_readinto(buffer_w, buffer_r)
|
||||
print(buffer_w == buffer_r)
|
||||
|
||||
spi.init(polarity=0, phase=1, pins=None)
|
||||
buffer_r = bytearray(10)
|
||||
spi.write_readinto(buffer_w, buffer_r)
|
||||
print(buffer_w == buffer_r)
|
||||
|
||||
# test 16 and 32 bit transfers
|
||||
buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2])
|
||||
buffer_r = bytearray(12)
|
||||
spi.init(SPI.MASTER, baudrate=10000000, bits=16, polarity=0, phase=0, pins=None)
|
||||
print(spi.write_readinto(buffer_w, buffer_r) == 12)
|
||||
print(buffer_w == buffer_r)
|
||||
|
||||
buffer_r = bytearray(12)
|
||||
spi.init(SPI.MASTER, baudrate=10000000, bits=32, polarity=0, phase=0, pins=None)
|
||||
print(spi.write_readinto(buffer_w, buffer_r) == 12)
|
||||
print(buffer_w == buffer_r)
|
||||
|
||||
# check for memory leaks...
|
||||
for i in range (0, 1000):
|
||||
spi = SPI(0, SPI.MASTER, baudrate=1000000)
|
||||
|
||||
# test deinit
|
||||
spi = SPI(0, SPI.MASTER, baudrate=1000000)
|
||||
spi.deinit()
|
||||
print(spi)
|
||||
|
||||
spi = SPI(0, SPI.MASTER, baudrate=1000000)
|
||||
# next ones must fail
|
||||
try:
|
||||
spi = SPI(0, 10, baudrate=10000000, polarity=0, phase=0)
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi = SPI(0, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=2)
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi = SPI(1, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=1)
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0)
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0, firstbit=2)
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0, pins=('GP1', 'GP2'))
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=0, phase=0, bits=9)
|
||||
except:
|
||||
print("Exception")
|
||||
|
||||
spi.deinit()
|
||||
try:
|
||||
spi.read(15)
|
||||
except Exception:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi.spi.readinto(buffer_r)
|
||||
except Exception:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi.spi.write('abc')
|
||||
except Exception:
|
||||
print("Exception")
|
||||
|
||||
try:
|
||||
spi.write_readinto(buffer_w, buffer_r)
|
||||
except Exception:
|
||||
print("Exception")
|
||||
|
||||
# reinitialization must work
|
||||
spi.init(baudrate=500000)
|
||||
print(spi)
|
35
tests/wipy/spi.py.exp
Normal file
35
tests/wipy/spi.py.exp
Normal file
@ -0,0 +1,35 @@
|
||||
SPI(0, SPI.MASTER, baudrate=2000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=5000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=10000000, bits=8, polarity=0, phase=1, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=10000000, bits=8, polarity=1, phase=1, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=20000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
SPI(0, SPI.MASTER, baudrate=1000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
True
|
||||
SPI(0)
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
Exception
|
||||
SPI(0, SPI.MASTER, baudrate=500000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
|
Loading…
Reference in New Issue
Block a user