From 23b74176610d033d9136381a6fb7cc2a08644117 Mon Sep 17 00:00:00 2001 From: Andrew Kay Date: Wed, 20 Feb 2019 16:10:12 +0000 Subject: [PATCH 1/9] added readbytesb, returning a bytes object rather than a list for efficiency --- README.md | 6 +++++- spidev_module.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 805a4f4..d791b98 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,11 @@ Connects to the specified SPI device, opening `/dev/spidev.` readbytes(n) -Read n bytes from SPI device. +Read n bytes from SPI device, returning a list of integers. + + readbytesb(n) + +Read n bytes from SPI device, returning an (immutable) bytes object (more efficient for larger transfers). writebytes(list of values) diff --git a/spidev_module.c b/spidev_module.c index bcb6c86..fb5cab0 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -266,6 +266,44 @@ SpiDev_readbytes(SpiDevObject *self, PyObject *args) return list; } +PyDoc_STRVAR(SpiDev_readb_doc, + "read(len) -> [values]\n\n" + "Read len bytes from SPI device.\n"); + +static PyObject * +SpiDev_readbytesb(SpiDevObject *self, PyObject *args) +{ + uint8_t rxbuf[SPIDEV_MAXPATH]; + int status, len; + PyObject *bytes; + + if (!PyArg_ParseTuple(args, "i:read", &len)) + return NULL; + + /* read at least 1 byte, no more than SPIDEV_MAXPATH */ + if (len < 1) + len = 1; + else if ((unsigned)len > sizeof(rxbuf)) + len = sizeof(rxbuf); + + memset(rxbuf, 0, sizeof rxbuf); + status = read(self->fd, &rxbuf[0], len); + + if (status < 0) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + if (status != len) { + perror("short read"); + return NULL; + } + + bytes = Py_BuildValue("y#", rxbuf, len); + return bytes; +} + + static PyObject * SpiDev_writebytes2_buffer(SpiDevObject *self, Py_buffer *buffer) { @@ -1365,6 +1403,8 @@ static PyMethodDef SpiDev_methods[] = { SpiDev_fileno_doc}, {"readbytes", (PyCFunction)SpiDev_readbytes, METH_VARARGS, SpiDev_read_doc}, + {"readbytesb", (PyCFunction)SpiDev_readbytesb, METH_VARARGS, + SpiDev_readb_doc}, {"writebytes", (PyCFunction)SpiDev_writebytes, METH_VARARGS, SpiDev_write_doc}, {"writebytes2", (PyCFunction)SpiDev_writebytes2, METH_VARARGS, From be89f45b00962124396ca7fb3ebc0bc5b1345764 Mon Sep 17 00:00:00 2001 From: Andrew Kay Date: Wed, 20 Feb 2019 16:41:40 +0000 Subject: [PATCH 2/9] refactor -- slightly neater... --- spidev_module.c | 72 +++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/spidev_module.c b/spidev_module.c index fb5cab0..121e891 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -223,16 +223,12 @@ SpiDev_writebytes(SpiDevObject *self, PyObject *args) return Py_None; } -PyDoc_STRVAR(SpiDev_read_doc, - "read(len) -> [values]\n\n" - "Read len bytes from SPI device.\n"); static PyObject * -SpiDev_readbytes(SpiDevObject *self, PyObject *args) +SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) { uint8_t rxbuf[SPIDEV_MAXPATH]; - int status, len, ii; - PyObject *list; + int status, len; if (!PyArg_ParseTuple(args, "i:read", &len)) return NULL; @@ -256,51 +252,45 @@ SpiDev_readbytes(SpiDevObject *self, PyObject *args) return NULL; } - list = PyList_New(len); + if (resultType == 0) { // list + int ii; + PyObject *list; + list = PyList_New(len); - for (ii = 0; ii < len; ii++) { - PyObject *val = Py_BuildValue("l", (long)rxbuf[ii]); - PyList_SET_ITEM(list, ii, val); - } + for (ii = 0; ii < len; ii++) { + PyObject *val = Py_BuildValue("l", (long)rxbuf[ii]); + PyList_SET_ITEM(list, ii, val); + } + + return list; + } + else { // bytes + PyObject *bytes; + bytes = Py_BuildValue("y#", rxbuf, len); + + return bytes; + } +} - return list; + +PyDoc_STRVAR(SpiDev_read_doc, + "read(len) -> [values]\n\n" + "Read len bytes from SPI device, returning a list.\n"); + +static PyObject * +SpiDev_readbytes(SpiDevObject *self, PyObject *args) +{ + return SpiDev_readbytes_generic(self, args, 0); } PyDoc_STRVAR(SpiDev_readb_doc, "read(len) -> [values]\n\n" - "Read len bytes from SPI device.\n"); + "Read len bytes from SPI device, returning a bytes object.\n"); static PyObject * SpiDev_readbytesb(SpiDevObject *self, PyObject *args) { - uint8_t rxbuf[SPIDEV_MAXPATH]; - int status, len; - PyObject *bytes; - - if (!PyArg_ParseTuple(args, "i:read", &len)) - return NULL; - - /* read at least 1 byte, no more than SPIDEV_MAXPATH */ - if (len < 1) - len = 1; - else if ((unsigned)len > sizeof(rxbuf)) - len = sizeof(rxbuf); - - memset(rxbuf, 0, sizeof rxbuf); - status = read(self->fd, &rxbuf[0], len); - - if (status < 0) { - PyErr_SetFromErrno(PyExc_IOError); - return NULL; - } - - if (status != len) { - perror("short read"); - return NULL; - } - - bytes = Py_BuildValue("y#", rxbuf, len); - return bytes; + return SpiDev_readbytes_generic(self, args, 1); } From b33bae8590fdd866c50a4cc79c4520e757d01fe0 Mon Sep 17 00:00:00 2001 From: Andrew Kay Date: Thu, 21 Feb 2019 15:28:09 +0000 Subject: [PATCH 3/9] bidirectional transfer experiment using bytearrays --- spidev_module.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ test.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 test.py diff --git a/spidev_module.c b/spidev_module.c index 121e891..9748d6c 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -889,6 +889,50 @@ SpiDev_xfer3(SpiDevObject *self, PyObject *args) return rx_tuple; } +PyDoc_STRVAR(SpiDev_bidibuffer_doc, "bidibuffer(buffer) -> buffer\njust a test for now\n"); +static PyObject * SpiDev_bidibuffer(PyObject* self, PyObject* args) +{ + //if (!PyArg_ParseTuple(args, "O|IHB:xfer", &obj, &speed_hz, &delay_usecs, &bits_per_word)) + + //char *buf; + Py_buffer pybuf; + Py_ssize_t count; + //PyObject * result; + int i; + int val = 100; + + if (!PyArg_ParseTuple(args, "y*|i", &pybuf, &val)) + { + return NULL; + } + if (!PyBuffer_IsContiguous(&pybuf, 'A')) + { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.bidibuffer: buffer is not contiguous"); + return NULL; + } + count = pybuf.len; + printf("count: %d, buff: %lx, val: %d\n", pybuf.len, (unsigned long)pybuf.buf, val); + char* buf = pybuf.buf; + + for(i=0;i Date: Thu, 21 Feb 2019 16:59:34 +0000 Subject: [PATCH 4/9] added readbuffer: reads data into existing bytearray --- spidev_module.c | 108 ++++++++++++++++++++++-------------------------- test.py | 63 +++++++++++----------------- 2 files changed, 75 insertions(+), 96 deletions(-) diff --git a/spidev_module.c b/spidev_module.c index 9748d6c..8c9d943 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -227,19 +227,37 @@ SpiDev_writebytes(SpiDevObject *self, PyObject *args) static PyObject * SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) { - uint8_t rxbuf[SPIDEV_MAXPATH]; + static uint8_t stackbuf[SPIDEV_MAXPATH]; int status, len; + Py_buffer pybuff; + uint8_t* rxbuf = stackbuf; + + if (resultType == 2) { //existing bytearray + if (!PyArg_ParseTuple(args, "y*", &pybuff)) + return NULL; + if (!PyBuffer_IsContiguous(&pybuff, 'A')) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must be contiguous"); + return NULL; + } + len = pybuff.len; + rxbuf = pybuff.buf; + if (len < 1) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must not be empty"); + return NULL; + } + } + else { + if (!PyArg_ParseTuple(args, "i:read", &len)) + return NULL; + + /* read at least 1 byte, no more than SPIDEV_MAXPATH */ + if (len < 1) + len = 1; + else if ((unsigned)len > sizeof(stackbuf)) + len = sizeof(stackbuf); + memset(rxbuf, 0, sizeof(stackbuf)); + } - if (!PyArg_ParseTuple(args, "i:read", &len)) - return NULL; - - /* read at least 1 byte, no more than SPIDEV_MAXPATH */ - if (len < 1) - len = 1; - else if ((unsigned)len > sizeof(rxbuf)) - len = sizeof(rxbuf); - - memset(rxbuf, 0, sizeof rxbuf); status = read(self->fd, &rxbuf[0], len); if (status < 0) { @@ -248,7 +266,8 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) } if (status != len) { - perror("short read"); + printf("Short Read: %d/%d bytes\n", status, len); + PyErr_SetString(PyExc_IOError, "SpiDev.readbuffer: I/O error: short read."); return NULL; } @@ -264,12 +283,18 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) return list; } - else { // bytes + else if (resultType == 1) { // bytes PyObject *bytes; bytes = Py_BuildValue("y#", rxbuf, len); - return bytes; } + else if (resultType == 2) { // bytearray + Py_RETURN_NONE; + } + else { // unknown type + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: internal problem. Type was not 0, 1 or 2. Weird."); + return NULL; + } } @@ -293,6 +318,16 @@ SpiDev_readbytesb(SpiDevObject *self, PyObject *args) return SpiDev_readbytes_generic(self, args, 1); } +PyDoc_STRVAR(SpiDev_readbuffer_doc, + "read(bytearray) -> [values]\n\n" + "Read bytes from SPI device, filling the supplied byte array.\n"); + +static PyObject * +SpiDev_readbuffer(SpiDevObject *self, PyObject *args) +{ + return SpiDev_readbytes_generic(self, args, 2); +} + static PyObject * SpiDev_writebytes2_buffer(SpiDevObject *self, Py_buffer *buffer) @@ -889,49 +924,6 @@ SpiDev_xfer3(SpiDevObject *self, PyObject *args) return rx_tuple; } -PyDoc_STRVAR(SpiDev_bidibuffer_doc, "bidibuffer(buffer) -> buffer\njust a test for now\n"); -static PyObject * SpiDev_bidibuffer(PyObject* self, PyObject* args) -{ - //if (!PyArg_ParseTuple(args, "O|IHB:xfer", &obj, &speed_hz, &delay_usecs, &bits_per_word)) - - //char *buf; - Py_buffer pybuf; - Py_ssize_t count; - //PyObject * result; - int i; - int val = 100; - - if (!PyArg_ParseTuple(args, "y*|i", &pybuf, &val)) - { - return NULL; - } - if (!PyBuffer_IsContiguous(&pybuf, 'A')) - { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.bidibuffer: buffer is not contiguous"); - return NULL; - } - count = pybuf.len; - printf("count: %d, buff: %lx, val: %d\n", pybuf.len, (unsigned long)pybuf.buf, val); - char* buf = pybuf.buf; - - for(i=0;i Date: Fri, 22 Feb 2019 09:52:57 +0000 Subject: [PATCH 5/9] readbuffer: reads SPI bytes into an existing bytearray at a given offset. --- README.md | 6 ++++++ spidev_module.c | 28 +++++++++++++++++++++------- test.py | 19 ++++++++++++++++++- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d791b98..018ca50 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,12 @@ Read n bytes from SPI device, returning a list of integers. Read n bytes from SPI device, returning an (immutable) bytes object (more efficient for larger transfers). + readbuffer(buffer [, length [, offset]]) + +Read length bytes from SPI device into an existing bytearray object at the given offest. +If length is not specified or 0, reads to the end of the buffer. +If offset is not specified, default is 0. + writebytes(list of values) Writes a list of values to SPI device. diff --git a/spidev_module.c b/spidev_module.c index 8c9d943..9f4b9f8 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -228,23 +228,37 @@ static PyObject * SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) { static uint8_t stackbuf[SPIDEV_MAXPATH]; - int status, len; + int status, len = 0; Py_buffer pybuff; uint8_t* rxbuf = stackbuf; if (resultType == 2) { //existing bytearray - if (!PyArg_ParseTuple(args, "y*", &pybuff)) + int offset = 0; + if (!PyArg_ParseTuple(args, "y*|II", &pybuff, &len, &offset)) return NULL; if (!PyBuffer_IsContiguous(&pybuff, 'A')) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must be contiguous"); + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must be contiguous."); return NULL; } - len = pybuff.len; - rxbuf = pybuff.buf; - if (len < 1) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must not be empty"); + if (pybuff.len < 1) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must not be empty."); return NULL; } + if (len < 0) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: length must be positive."); + return NULL; + } + if (offset < 0) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset must be positive."); + return NULL; + } + if (offset + len >= pybuff.len) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset+length would exceed buffer."); + return NULL; + } + if (len == 0) + len = pybuff.len - offset; + rxbuf = pybuff.buf + offset; } else { if (!PyArg_ParseTuple(args, "i:read", &len)) diff --git a/test.py b/test.py index 2b5d82a..5b076c4 100644 --- a/test.py +++ b/test.py @@ -28,4 +28,21 @@ def readbuffer(): spi.readbuffer(buffer) spi.close() -testspi() \ No newline at end of file + def buffertests(self): + spi=spidev.SpiDev() + spi.open(0, 0) + buffer = bytearray(range(20)) + print(buffer) + spi.readbuffer(buffer, 5) + print(buffer) + spi.readbuffer(buffer, 5, 10) + print(buffer) + spi.readbuffer(buffer, 0, 15) + print(buffer) + + buffer = bytearray(range(20)) + print(buffer) + spi.readbuffer(buffer) + print(buffer) + +testspi().buffertests() \ No newline at end of file From 34b73057bf405fd0592dd7980a8e5183e0b9025b Mon Sep 17 00:00:00 2001 From: aardvarkkrill Date: Fri, 22 Feb 2019 10:28:49 +0000 Subject: [PATCH 6/9] converted magic numbers to #defines. --- spidev_module.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/spidev_module.c b/spidev_module.c index 9f4b9f8..b409f9b 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -224,6 +224,10 @@ SpiDev_writebytes(SpiDevObject *self, PyObject *args) } +#define READBYTES_GENERIC_RESULTTYPE_LIST 0 +#define READBYTES_GENERIC_RESULTTYPE_BYTES 1 +#define READBYTES_GENERIC_RESULTTYPE_BYTEARRAY 2 + static PyObject * SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) { @@ -232,7 +236,7 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) Py_buffer pybuff; uint8_t* rxbuf = stackbuf; - if (resultType == 2) { //existing bytearray + if (resultType == READBYTES_GENERIC_RESULTTYPE_BYTEARRAY) { //existing bytearray int offset = 0; if (!PyArg_ParseTuple(args, "y*|II", &pybuff, &len, &offset)) return NULL; @@ -285,7 +289,7 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) return NULL; } - if (resultType == 0) { // list + if (resultType == READBYTES_GENERIC_RESULTTYPE_LIST) { // list int ii; PyObject *list; list = PyList_New(len); @@ -297,12 +301,12 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) return list; } - else if (resultType == 1) { // bytes + else if (resultType == READBYTES_GENERIC_RESULTTYPE_BYTES) { // bytes PyObject *bytes; bytes = Py_BuildValue("y#", rxbuf, len); return bytes; } - else if (resultType == 2) { // bytearray + else if (resultType == READBYTES_GENERIC_RESULTTYPE_BYTEARRAY) { // bytearray Py_RETURN_NONE; } else { // unknown type From 04ecac88297c078ab316d8077644ab824971da31 Mon Sep 17 00:00:00 2001 From: aardvarkkrill Date: Fri, 22 Feb 2019 14:28:17 +0000 Subject: [PATCH 7/9] refactoring and tidying up --- spidev_module.c | 145 +++++++++++++++++++++++++++--------------------- test.py | 14 +++-- 2 files changed, 90 insertions(+), 69 deletions(-) diff --git a/spidev_module.c b/spidev_module.c index b409f9b..2455047 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -224,70 +224,56 @@ SpiDev_writebytes(SpiDevObject *self, PyObject *args) } -#define READBYTES_GENERIC_RESULTTYPE_LIST 0 -#define READBYTES_GENERIC_RESULTTYPE_BYTES 1 -#define READBYTES_GENERIC_RESULTTYPE_BYTEARRAY 2 - -static PyObject * -SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) +/* return true on success */ +static int +SpiDev_read_lowlevel(SpiDevObject *self, uint8_t *buf, int buflen, int lenreq) { - static uint8_t stackbuf[SPIDEV_MAXPATH]; - int status, len = 0; - Py_buffer pybuff; - uint8_t* rxbuf = stackbuf; - - if (resultType == READBYTES_GENERIC_RESULTTYPE_BYTEARRAY) { //existing bytearray - int offset = 0; - if (!PyArg_ParseTuple(args, "y*|II", &pybuff, &len, &offset)) - return NULL; - if (!PyBuffer_IsContiguous(&pybuff, 'A')) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must be contiguous."); - return NULL; - } - if (pybuff.len < 1) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must not be empty."); - return NULL; - } - if (len < 0) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: length must be positive."); - return NULL; - } - if (offset < 0) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset must be positive."); - return NULL; - } - if (offset + len >= pybuff.len) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset+length would exceed buffer."); - return NULL; - } - if (len == 0) - len = pybuff.len - offset; - rxbuf = pybuff.buf + offset; - } - else { - if (!PyArg_ParseTuple(args, "i:read", &len)) - return NULL; - - /* read at least 1 byte, no more than SPIDEV_MAXPATH */ - if (len < 1) - len = 1; - else if ((unsigned)len > sizeof(stackbuf)) - len = sizeof(stackbuf); - memset(rxbuf, 0, sizeof(stackbuf)); - } - - status = read(self->fd, &rxbuf[0], len); + int status; + + /* read at least 1 byte, no more than SPIDEV_MAXPATH */ + if (lenreq < 1) + lenreq = 1; + else if ((unsigned)lenreq > sizeof(buflen)) + lenreq = buflen; + memset(buf, 0, buflen); + +//#define SPIDEV_READ_LOWLEVEL_TESTING +#ifdef SPIDEV_READ_LOWLEVEL_TESTING + { status = lenreq; for (unsigned i = 0; i < lenreq; i++) buf[i] = 64 + i; } +#else + status = read(self->fd, &buf[0], lenreq); +#endif if (status < 0) { PyErr_SetFromErrno(PyExc_IOError); - return NULL; + return 0; // fail } - if (status != len) { - printf("Short Read: %d/%d bytes\n", status, len); + if (status != lenreq) { + printf("Short Read: %d/%d bytes\n", status, lenreq); PyErr_SetString(PyExc_IOError, "SpiDev.readbuffer: I/O error: short read."); - return NULL; + return 0; // fail } + return 1; // succeed +} + + +#define READBYTES_GENERIC_RESULTTYPE_LIST 0 +#define READBYTES_GENERIC_RESULTTYPE_BYTES 1 + +static PyObject * +SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) +{ + static uint8_t rxbuf[SPIDEV_MAXPATH]; + int len = 0; + + if (!PyArg_ParseTuple(args, "i:read", &len)) + return NULL; + + // get the bytes here + if (!SpiDev_read_lowlevel(self, rxbuf, sizeof(rxbuf), len)) { + return NULL; + } if (resultType == READBYTES_GENERIC_RESULTTYPE_LIST) { // list int ii; @@ -306,16 +292,14 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) bytes = Py_BuildValue("y#", rxbuf, len); return bytes; } - else if (resultType == READBYTES_GENERIC_RESULTTYPE_BYTEARRAY) { // bytearray - Py_RETURN_NONE; - } else { // unknown type - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: internal problem. Type was not 0, 1 or 2. Weird."); + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: internal problem in readbytes_generic."); return NULL; } } + PyDoc_STRVAR(SpiDev_read_doc, "read(len) -> [values]\n\n" "Read len bytes from SPI device, returning a list.\n"); @@ -323,7 +307,7 @@ PyDoc_STRVAR(SpiDev_read_doc, static PyObject * SpiDev_readbytes(SpiDevObject *self, PyObject *args) { - return SpiDev_readbytes_generic(self, args, 0); + return SpiDev_readbytes_generic(self, args, READBYTES_GENERIC_RESULTTYPE_LIST); } PyDoc_STRVAR(SpiDev_readb_doc, @@ -333,17 +317,50 @@ PyDoc_STRVAR(SpiDev_readb_doc, static PyObject * SpiDev_readbytesb(SpiDevObject *self, PyObject *args) { - return SpiDev_readbytes_generic(self, args, 1); + return SpiDev_readbytes_generic(self, args, READBYTES_GENERIC_RESULTTYPE_BYTES); } + PyDoc_STRVAR(SpiDev_readbuffer_doc, - "read(bytearray) -> [values]\n\n" + "read(bytearray [, length [, offset]]) -> [values]\n\n" "Read bytes from SPI device, filling the supplied byte array.\n"); static PyObject * SpiDev_readbuffer(SpiDevObject *self, PyObject *args) { - return SpiDev_readbytes_generic(self, args, 2); + Py_buffer pybuff; + int offset = 0, len = 0; + + if (!PyArg_ParseTuple(args, "y*|II", &pybuff, &len, &offset)) + return NULL; + if (!PyBuffer_IsContiguous(&pybuff, 'A')) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must be contiguous."); + return NULL; + } + if (pybuff.len < 1) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must not be empty."); + return NULL; + } + if (len < 0) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: length must be positive."); + return NULL; + } + if (offset < 0 || offset >= pybuff.len - 1) { // NB must be space for at least one byte + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset out of range."); + return NULL; + } + if (offset + len > pybuff.len) { + PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset+length would overflow buffer."); + return NULL; + } + + if (len == 0) + len = pybuff.len - offset; + + if (!SpiDev_read_lowlevel(self, pybuff.buf + offset, len, len)) + return NULL; + + Py_RETURN_NONE; } diff --git a/test.py b/test.py index 5b076c4..40721fd 100644 --- a/test.py +++ b/test.py @@ -9,13 +9,16 @@ class testspi (object): def __init__(self): spi=spidev.SpiDev() spi.open(0, 0) - print("devspi readbytes", spi.readbytes(50)) - spibytes = spi.readbytesb(50) - npbytes = numpy.frombuffer(spibytes, dtype=numpy.int16) - print("devspi readbytesb", npbytes) bytes = 1000 - buffer = bytearray(1000) count = 1000 + + buffer = bytearray(1000) + print("devspi readbytes", spi.readbytes(10)) + print("devspi readbytes", numpy.array(spi.readbytes(10), dtype=numpy.int16)) + print("devspi readbytesb", numpy.frombuffer(spi.readbytesb(10), dtype=numpy.int16)) + spi.readbuffer(buffer, 10); + print("devspi readbuffer", numpy.frombuffer(buffer[:10], dtype=numpy.int16)) + def read(): spi.readbytes(bytes) def readb(): spi.readbytesb(bytes) def readbuffer(): spi.readbuffer(buffer) @@ -25,6 +28,7 @@ def readbuffer(): spi.readbuffer(buffer) print('bytes: total dur %f; secs/byte=%f; bytes/sec=%f' % (duration, duration/(bytes*count), (bytes*count)/duration)) duration = timeit.timeit(readbuffer, number=count) print('bytes: total dur %f; secs/byte=%f; bytes/sec=%f' % (duration, duration/(bytes*count), (bytes*count)/duration)) + spi.close() From 61fc57cac4eace096fa1dae959ff1bbde1a3980f Mon Sep 17 00:00:00 2001 From: aardvarkkrill Date: Fri, 22 Feb 2019 14:34:13 +0000 Subject: [PATCH 8/9] removed pybuffer and test.py (separation of branches) --- README.md | 6 ------ spidev_module.c | 51 ------------------------------------------------ test.py | 52 ------------------------------------------------- 3 files changed, 109 deletions(-) delete mode 100644 test.py diff --git a/README.md b/README.md index 018ca50..d791b98 100644 --- a/README.md +++ b/README.md @@ -56,12 +56,6 @@ Read n bytes from SPI device, returning a list of integers. Read n bytes from SPI device, returning an (immutable) bytes object (more efficient for larger transfers). - readbuffer(buffer [, length [, offset]]) - -Read length bytes from SPI device into an existing bytearray object at the given offest. -If length is not specified or 0, reads to the end of the buffer. -If offset is not specified, default is 0. - writebytes(list of values) Writes a list of values to SPI device. diff --git a/spidev_module.c b/spidev_module.c index 2455047..936e5a6 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -237,12 +237,7 @@ SpiDev_read_lowlevel(SpiDevObject *self, uint8_t *buf, int buflen, int lenreq) lenreq = buflen; memset(buf, 0, buflen); -//#define SPIDEV_READ_LOWLEVEL_TESTING -#ifdef SPIDEV_READ_LOWLEVEL_TESTING - { status = lenreq; for (unsigned i = 0; i < lenreq; i++) buf[i] = 64 + i; } -#else status = read(self->fd, &buf[0], lenreq); -#endif if (status < 0) { PyErr_SetFromErrno(PyExc_IOError); @@ -298,8 +293,6 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) } } - - PyDoc_STRVAR(SpiDev_read_doc, "read(len) -> [values]\n\n" "Read len bytes from SPI device, returning a list.\n"); @@ -321,49 +314,6 @@ SpiDev_readbytesb(SpiDevObject *self, PyObject *args) } -PyDoc_STRVAR(SpiDev_readbuffer_doc, - "read(bytearray [, length [, offset]]) -> [values]\n\n" - "Read bytes from SPI device, filling the supplied byte array.\n"); - -static PyObject * -SpiDev_readbuffer(SpiDevObject *self, PyObject *args) -{ - Py_buffer pybuff; - int offset = 0, len = 0; - - if (!PyArg_ParseTuple(args, "y*|II", &pybuff, &len, &offset)) - return NULL; - if (!PyBuffer_IsContiguous(&pybuff, 'A')) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must be contiguous."); - return NULL; - } - if (pybuff.len < 1) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: buffer must not be empty."); - return NULL; - } - if (len < 0) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: length must be positive."); - return NULL; - } - if (offset < 0 || offset >= pybuff.len - 1) { // NB must be space for at least one byte - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset out of range."); - return NULL; - } - if (offset + len > pybuff.len) { - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: offset+length would overflow buffer."); - return NULL; - } - - if (len == 0) - len = pybuff.len - offset; - - if (!SpiDev_read_lowlevel(self, pybuff.buf + offset, len, len)) - return NULL; - - Py_RETURN_NONE; -} - - static PyObject * SpiDev_writebytes2_buffer(SpiDevObject *self, Py_buffer *buffer) { @@ -1476,7 +1426,6 @@ static PyMethodDef SpiDev_methods[] = { SpiDev_xfer2_doc}, {"xfer3", (PyCFunction)SpiDev_xfer3, METH_VARARGS, SpiDev_xfer3_doc}, - {"readbuffer", (PyCFunction)SpiDev_readbuffer, METH_VARARGS, SpiDev_readbuffer_doc}, {"__enter__", (PyCFunction)SpiDev_enter, METH_VARARGS, NULL}, {"__exit__", (PyCFunction)SpiDev_exit, METH_VARARGS, diff --git a/test.py b/test.py deleted file mode 100644 index 40721fd..0000000 --- a/test.py +++ /dev/null @@ -1,52 +0,0 @@ -import sys -sys.path = ['.'] + sys.path - -# https://pypi.org/project/spidev/ -import spidev -import numpy -import timeit -class testspi (object): - def __init__(self): - spi=spidev.SpiDev() - spi.open(0, 0) - bytes = 1000 - count = 1000 - - buffer = bytearray(1000) - print("devspi readbytes", spi.readbytes(10)) - print("devspi readbytes", numpy.array(spi.readbytes(10), dtype=numpy.int16)) - print("devspi readbytesb", numpy.frombuffer(spi.readbytesb(10), dtype=numpy.int16)) - spi.readbuffer(buffer, 10); - print("devspi readbuffer", numpy.frombuffer(buffer[:10], dtype=numpy.int16)) - - def read(): spi.readbytes(bytes) - def readb(): spi.readbytesb(bytes) - def readbuffer(): spi.readbuffer(buffer) - duration = timeit.timeit(read, number=count) - print('list: total dur %f; secs/byte=%f; bytes/sec=%f' % (duration, duration/(bytes*count), (bytes*count)/duration)) - duration = timeit.timeit(readb, number=count) - print('bytes: total dur %f; secs/byte=%f; bytes/sec=%f' % (duration, duration/(bytes*count), (bytes*count)/duration)) - duration = timeit.timeit(readbuffer, number=count) - print('bytes: total dur %f; secs/byte=%f; bytes/sec=%f' % (duration, duration/(bytes*count), (bytes*count)/duration)) - - spi.close() - - - def buffertests(self): - spi=spidev.SpiDev() - spi.open(0, 0) - buffer = bytearray(range(20)) - print(buffer) - spi.readbuffer(buffer, 5) - print(buffer) - spi.readbuffer(buffer, 5, 10) - print(buffer) - spi.readbuffer(buffer, 0, 15) - print(buffer) - - buffer = bytearray(range(20)) - print(buffer) - spi.readbuffer(buffer) - print(buffer) - -testspi().buffertests() \ No newline at end of file From e54b8744caf5cfdbf5dc14b73c4a62d551eb1356 Mon Sep 17 00:00:00 2001 From: aardvarkkrill Date: Fri, 22 Feb 2019 14:37:51 +0000 Subject: [PATCH 9/9] tweak messages and doc strings --- spidev_module.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spidev_module.c b/spidev_module.c index 936e5a6..e1504b3 100644 --- a/spidev_module.c +++ b/spidev_module.c @@ -246,7 +246,7 @@ SpiDev_read_lowlevel(SpiDevObject *self, uint8_t *buf, int buflen, int lenreq) if (status != lenreq) { printf("Short Read: %d/%d bytes\n", status, lenreq); - PyErr_SetString(PyExc_IOError, "SpiDev.readbuffer: I/O error: short read."); + PyErr_SetString(PyExc_IOError, "SpiDev.read: I/O error: short read."); return 0; // fail } return 1; // succeed @@ -288,7 +288,7 @@ SpiDev_readbytes_generic(SpiDevObject *self, PyObject *args, int resultType) return bytes; } else { // unknown type - PyErr_SetString(PyExc_RuntimeError, "SpiDev.readbuffer: internal problem in readbytes_generic."); + PyErr_SetString(PyExc_RuntimeError, "SpiDev.read: internal problem in readbytes_generic."); return NULL; } } @@ -304,8 +304,8 @@ SpiDev_readbytes(SpiDevObject *self, PyObject *args) } PyDoc_STRVAR(SpiDev_readb_doc, - "read(len) -> [values]\n\n" - "Read len bytes from SPI device, returning a bytes object.\n"); + "read(len) -> bytes(len)\n\n" + "Read len bytes from SPI device, returning a bytes object of length len.\n"); static PyObject * SpiDev_readbytesb(SpiDevObject *self, PyObject *args)