doceme / py-spidev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leading binary zero's when reading data are returned as missing bits

edharman opened this issue · comments

This may be naivety on my part - I'm a hacker not a programmer, however I have an issue when reading data from MCP23S17 GPIO expanders that are devices that are physically divided into two 8 bit banks -BankA and BankB. I could read each bank individually and from the returned data deduce if the leading (MSB?) was not set by the length of the result (the SPI library truncates leading zero's in the returned data), however for speed I want to read both Banks in one spi transfer but have a problem in that this would not allow me to accurately determine leading zero's in each banks results in this situation -
Assuming read operation is BankA MSB->LSB and following the same for BankB, if I read both in one transaction and MSB of both are zero I end up with 14 bits and no method of deducing where to '0' bit-stuff back to the expected 16 bits.
When I look at the MSO output I see that on the MOSI line the data is returned accurately - that is with leading zero's present, however the SPIdev library truncates the leading zero's.

Here is the code I am using to demonstrate the problem, and a capture of the output of the digital scope on the SPI bus -

Code to reproduce issue -
#include <stdio.h>
#include <stdlib.h>

#include <pigpio.h>

//INPUT COMMAND WORD AND REGISTER WRITE OPERATION

#define READ 0x40
#define WRITE 0x41
#define PIN 21

//DEVICE CONFIGURATION AND REGISTER MAPS
#define GPIOA 0x12 // GPIO-A
#define GPIOB 0x13 // GPIO-B

uint32_t data_to_send, data_to_receive;
char snd_buffA[2] = {0x41,GPIOA};
char snd_buffB[2] = {0x41,GPIOB};
unsigned char bytes[4];
unsigned long n = 3490971649;

void bin(unsigned n)
{
/* step 1 */
if (n > 1)
bin(n/2);

/* step 2 */
printf("%d", n % 2); 

}

int main(int argc, char *argv[])
{
gpioInitialise(); //Initialise pigpio.h
spiOpen(0,10000000,0);

spiXfer(0, snd_buffA, (char *)(&data_to_receive), 6);
bin(data_to_receive);

}
Output on the cmd line is -
1111111111111111000000000000000011111111111111110000000000000000
111111111111111000000000000000011111111011111110000000000000000
111111110111111100000000000000001111111111111110000000000000000
11111110111111100000000000000001111111011111110000000000000000

Example output from my MSO -i.e if both leading bits read are zero I cannot reconstruct the true reading -

Buffer No. Packet Start Time (s) End Time (s) Data      
32 1 1.02E-06 4.55E-06 00000000 00000000 01111111 01111111
32 2 8.67E-05 9.02E-05 00000000 00000000 01111111 01111111

I appreciate I could resolve this by reading each of the devices banks registers individually however the overhead of doing this time-wise is significant ~100u-secs for two reads, whereas only about 5u-secs for a single read operation.
Happy to accept a workaround if it fixes this for me - and I deduce from the lack of reports regarding this 'feature' that it is a rare use-case, but as said I'm in no way a C expert and am unable to hack a workaround myself.

I think you're commenting on the wrong project. I think you're looking for pigpio.

I think this is a generic issue, I just used the pigpio library as a simple way of demonstrating the issue. I have more experience using python utils to read these GPIO's which don't use pigpio and they exhibit the same issue, that is returned data from a 8/16 bit register read contains less bits than expected if the leading bits are zero's.
In all cases I can see at the bus level that the correct number of bits are returned to the SPI driver, including any leading 0's

Based on your description of the behavior, this is not the place to raise the issue. If it's not specific to py-spidev or pigpio, perhaps you should reach out to the maintainers of the SPI kernel driver for the chipset you're using.