SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
User avatar
By andreer
#238291
Hello,

For a long time I had no success getting my 320x240 Sharp Memory Display (which I have connected to my Redboard Artemis ATP) to work well. With the Adafruit GFX library, it worked just fine (albeit very slowly) with bit-banged spi, but it did not work with HW spi, using the MbedSPI class as in the included Example06_SPI.

What is perhaps unusual about this display is that it expects LSB first bit order. I was eventually able to make it work by hacking the gfx lib to reverse the bits of each byte before transmitting (0b10100011 -> 0b11000101). What I find curious is that once I had it working, changing the definition of SPI_ORDER has no effect, it keeps working. So I believe this is the cause of my problems - the SPI transfer does not seem to care about the SPI_ORDER setting, and always transmits each byte in order of most significant bit to least significant bit.

Below is a minimal-ish program (based on the SPI example, using no external libraries) that successfully drives my display (showing "static") over hw SPI whether SPI_ORDER is set to LSBFIRST or MSBFIRST - I would expect this setting to make a difference? Or do I need to set it in some other way?

Thank you,
Andreas
Code: Select all
#include <SPI.h>

#define SHARP_SCK  SPI_CLK
#define SHARP_MOSI SPI_SDO
#define SHARP_MISO NC
#define SHARP_CS   D13
#define SHARP_VDD  D12

#define SPI_FREQ 2000000
#define SPI_MODE SPI_MODE0
#define SPI_ORDER LSBFIRST

MbedSPI mySPI(NC, SHARP_MOSI, SHARP_SCK); // declare the custom MbedSPI object mySPI
extern "C" SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName sclk);

void setup() {
  Serial.begin(115200);
  while (!Serial) {}
  Serial.printf("Using SPI %d\n", spi_get_peripheral_name(SHARP_MOSI, SHARP_MISO, SHARP_SCK));

  Serial.printf("SPI_ORDER is %d\n", SPI_ORDER);

  pinMode(SHARP_CS, OUTPUT);
  digitalWrite(SHARP_CS, LOW);

  pinMode(SHARP_VDD, OUTPUT);
  digitalWrite(SHARP_VDD, HIGH);

  mySPI.begin();
}

const size_t len = 44;
uint8_t tx_buff[len];

uint8_t swap(uint8_t b) {
  b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
  b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
  b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
  return b;
}

int i = 0;
void loop() {
  int vcom = i++ % 2;

  //   fill with random data
  for (int j = 0; j < len; j++) {
    tx_buff[j] = rand();
  }
  
  // except first byte for command
  tx_buff[0] = 0x80 | (vcom << 6);

  // and last two bytes for trailer
  tx_buff[len - 2] = 0x00;
  tx_buff[len - 1] = 0x00;
  
  tx_buff[1] = swap(i);
  mySPI.beginTransaction(SPISettings(SPI_FREQ, SPI_ORDER, SPI_MODE));
  digitalWrite(SHARP_CS, HIGH);
  mySPI.transfer(&tx_buff, len);
  mySPI.endTransaction();
  digitalWrite(SHARP_CS, LOW);
}
By paulvha
#238297
SPI_ORDER is NOT used with SPI.transfer(), it is only used with SPI.transfer16(). It takes an uint16_t value.
User avatar
By andreer
#238325
Hi Paul, thank you for your reply!
paulvha wrote: Fri Jan 13, 2023 3:10 am SPI_ORDER is NOT used with SPI.transfer(), it is only used with SPI.transfer16(). It takes an uint16_t value.
This indeed seems to be the case, but I propose that it is a bug.

Likely a misunderstanding of what MSBFIRST / LSBFIRST means in this context - it should be read as bit order, not byte order. This is also what SparkFun's own tutorial on SPI says, in the section titled "Programming for SPI": https://learn.sparkfun.com/tutorials/se ... ce-spi/all

I uploaded a small SPI test program to my Arduino UNO, which alternates between transmitting with LSBFIRST and MSBFIRST. I then used a "logic analyzer" to capture the resulting waveform, and it seems to support my statement as the bits within each byte are reversed. Results using transfer16 were the same.
Capture 1.PNG
Capture 2.PNG
My UNO code:
Code: Select all
#import <SPI.h>
#define SPIFREQ 250000

const int len = 2;
uint8_t buffer[len];

void setup()
{  
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  SPI.begin();
}

void loop() {
  buffer[0] = 0xa0; buffer[1] = 0xcc;
  // 1010 0000 1100 1100

  digitalWrite(10, LOW);
  SPI.beginTransaction(SPISettings(SPIFREQ, MSBFIRST, SPI_MODE0));
  SPI.transfer(&buffer, len);
  SPI.endTransaction();  
  digitalWrite(10, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(10, HIGH);

  buffer[0] = 0xa0; buffer[1] = 0xcc;
  // 1010 0000 1100 1100
  digitalWrite(10, LOW);
  SPI.beginTransaction(SPISettings(SPIFREQ, LSBFIRST, SPI_MODE0));
  SPI.transfer(&buffer, len);
  SPI.endTransaction();
  digitalWrite(10, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(10, HIGH);
}
You do not have the required permissions to view the files attached to this post.
By paulvha
#238333
you got a point. I have checked the source code. While the Apollo3 processor can be instructed to do either LSB or MSB (BIT) first, the driver does not have code to set it. Sparkfun should fix this and this should be raised on https://github.com/sparkfun/Arduino_Apollo3 as an issue. If you need a workaround earlier, let me know, it is does not look like a difficult fix to implement.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum