Skip to content

BUG: The SPI library does not handle HW CS for other bit lengths than 8. #2820

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tclarsson opened this issue Jan 2, 2017 · 3 comments
Open
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.

Comments

@tclarsson
Copy link

BUG: The SPI library does not handle HW SC for other bit lengths than 8.
For example: There is a bug in the routine "transfer16".

Hardware: WEMOS ESP8266

If one uses transfer16 for 16 bit SPI transfer using HW CS, the SS/CS pin goes high after each 8 bit transfer. the 16bit word is therefore transferred as 2 x 8 bit bytes.

For the below to work:
SPI.setHwCs(true); //Use (automatic) HW SS/CS (GPIO 15 , D8)
SPI.setBitOrder(MSBFIRST);
SPI.transfer16(0x1234);

I had to write my own alternative "_transfer16" routine:

uint16_t _bs(uint16_t data) {
return(((data&0xFF)<<8)|((data>>8)&0xFF));
}

void _setDataBits(uint16_t bits) {
const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
bits--;
SPI1U1 = ((SPI1U1 & mask) | ((bits << SPILMOSI) | (bits << SPILMISO)));
}

uint16_t _transfer16(uint16_t data) {
if(!(SPI1C & (SPICWBO | SPICRBO))) data=_bs(data);
while(SPI1CMD & SPIBUSY) {}
_setDataBits(16);
SPI1W0 = data;
SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {}
data=SPI1W0;
if(!(SPI1C & (SPICWBO | SPICRBO))) data=_bs(data);
return (data);
}

@tclarsson tclarsson changed the title BUG: The SPI library does not handle HW SC for other bit lengths than 8. BUG: The SPI library does not handle HW CS for other bit lengths than 8. Jan 2, 2017
@devyte
Copy link
Collaborator

devyte commented Oct 4, 2017

@tclarsson is this issue still valid in latest git?

@devyte devyte added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Oct 4, 2017
@UlliBien
Copy link

The bug is still there (Arduino/ESP8266, version 2.5.2). write16() does it correctly. I am not familiar with github and unfortunately can not make the change myself.

Change code to:
uint16_t SPIClass::transfer16(uint16_t data) {
while (SPI1CMD & SPIBUSY) {}
// Set to 16Bits transfer
setDataBits(16);
// Change byte order for MSBFIRST
if (!(SPI1C & (SPICWBO | SPICRBO))){
// MSBFIRST Byte first
SPI1W0 = (data >> 8) | (data << 8);
}
else {
// LSBFIRST Byte first
SPI1W0 = data;
}
// Start the transmission
SPI1CMD |= SPIBUSY;
// Wait for transmission to complete
while (SPI1CMD & SPIBUSY) {}
data = SPI1W0;
// Change byte order for MSBFIRST
if (!(SPI1C & (SPICWBO | SPICRBO)))
return (data >> 8) | (data << 8);
else
return data;
}

@thangktran
Copy link
Contributor

@UlliBien I'll be working on this issue

thangktran added a commit to thangktran/Arduino that referenced this issue Aug 21, 2019
to handle other bit lengths rather than 8.
Thanks to @UlliBien for the fix suggestion.

Fixes: esp8266#2820
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
waiting for feedback Waiting on additional info. If it's not received, the issue may be closed.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants