Spi clock on FX30s glitching with Renfell IOT card

I’m working currently working with a spi screen using the FX30S and mangOH IOT Card P/N: 0107-10-R1.1 The spi screen is the NHD-0216CW

Things seem to not be working due to glitches in the clock signal (See below). I believe this is causing sent bytes to be wrongly interpreted as a similar code on Arduino reliably does the job.

Here’s my code for the FX30; logread shows success and no errors

#include "legato.h"
#include "interfaces.h"
#include <time.h>
#include <errno.h>    

le_spi_DeviceHandleRef_t spiHandle;
void toggle();

unsigned char text1[] = {"TANKTRONIKS"};
unsigned char text2[] = {"DEVIL TEST"};

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

int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}

void command(unsigned char c) {
  uint8_t write_buffer_tx[1];
  le_result_t res;
  write_buffer_tx[0] = 0xF8;
  res = le_spi_WriteHD(spiHandle, write_buffer_tx, NUM_ARRAY_MEMBERS(write_buffer_tx));
  LE_FATAL_IF(res != LE_OK, "le_spi_WriteHD 0x1F error=%s", LE_RESULT_TXT(res));

  write_buffer_tx[0] = reverseBits((c & 0x0F));
  res = le_spi_WriteHD(spiHandle, write_buffer_tx, NUM_ARRAY_MEMBERS(write_buffer_tx));
  LE_FATAL_IF(res != LE_OK, "le_spi_WriteHD 0x1F1 error=%s", LE_RESULT_TXT(res));

  write_buffer_tx[0] = reverseBits(((c >> 4) & 0x0F));
  res = le_spi_WriteHD(spiHandle, write_buffer_tx, NUM_ARRAY_MEMBERS(write_buffer_tx));
  LE_FATAL_IF(res != LE_OK, "le_spi_WriteHD 0x1F2 error=%s", LE_RESULT_TXT(res));

}

void data(unsigned char d) {

  uint8_t write_buffer_tx[1];
  le_result_t res;
  write_buffer_tx[0] = 0xFA;
  res = le_spi_WriteHD(spiHandle, write_buffer_tx, NUM_ARRAY_MEMBERS(write_buffer_tx));
  LE_FATAL_IF(res != LE_OK, "le_spi_WriteHD 0x1F error=%s", LE_RESULT_TXT(res));

  write_buffer_tx[0] = reverseBits((d & 0x0F));
  res = le_spi_WriteHD(spiHandle, write_buffer_tx, NUM_ARRAY_MEMBERS(write_buffer_tx));
  LE_FATAL_IF(res != LE_OK, "le_spi_WriteHD 0x1F1 error=%s", LE_RESULT_TXT(res));

  write_buffer_tx[0] = reverseBits(((d >> 4) & 0x0F));
  res = le_spi_WriteHD(spiHandle, write_buffer_tx, NUM_ARRAY_MEMBERS(write_buffer_tx));
  LE_FATAL_IF(res != LE_OK, "le_spi_WriteHD 0x1F2 error=%s", LE_RESULT_TXT(res));  
}

void output() {
  int i;
  command(0x01);  // Clear display
  msleep(2);
  for(i = 0; i < 11; i++) {
    data(text1[i]);
  }

  command(0xA0);
  for(i = 0; i < 10; i++) {
    data(text2[i]);
  }
}

COMPONENT_INIT
{
  msleep(20);
  LE_INFO("LCD Component");
  le_gpioPin48_SetPushPullOutput(LE_GPIOPIN48_ACTIVE_HIGH, true);
  le_gpioPin42_SetPushPullOutput(LE_GPIOPIN42_ACTIVE_LOW, true);
  msleep(20);

  le_gpioPin48_SetPushPullOutput(LE_GPIOPIN48_ACTIVE_LOW, true);
  le_gpioPin42_SetPushPullOutput(LE_GPIOPIN42_ACTIVE_HIGH, true);
  msleep(20);
 
  LE_INFO("CONFIGURING SPI");

  le_result_t res;
  res = le_spi_Open("spidev1.0", &spiHandle);
  LE_FATAL_IF(res != LE_OK, "le_spi_Open failed with result=%s", LE_RESULT_TXT(res));
  if(res == LE_OK){
    LE_INFO("Success");
  }  

  le_spi_Configure(spiHandle, 3, 8, 960000, 0);

  LE_INFO("Beginning LCD configuration");
  command(0x2A);  //function set (extended command set)
  command(0x71);  //function selection A, disable internal Vdd regulator
  data(0x00);
  command(0x28);  //function set (fundamental command set)
  command(0x08);  //display off, cursor off, blink off
  command(0x2A);  //function set (extended command set)
  command(0x79);  //OLED command set enabled
  command(0xD5);  //set display clock divide ratio/oscillator frequency
  command(0x70);  //set display clock divide ratio/oscillator frequency
  command(0x78);  //OLED command set disabled
  command(0x09);  //extended function set (4-lines)
  command(0x06);  //COM SEG direction
  command(0x72);  //function selection B
  data(0x00);     //ROM CGRAM selection
  command(0x2A);  //function set (extended command set)
  command(0x79);  //OLED command set enabled
  command(0xDA);  //set SEG pins hardware configuration
  command(0x10);  //set SEG pins
  command(0xDC);  //function selection C
  command(0x00);  //function selection C
  command(0x81);  //set contrast control
  command(0x7F);  //set contrast control
  command(0xD9);  //set phase length
  command(0xF1);  //set phase length
  command(0xDB);  //set VCOMH deselect level
  command(0x40);  //set VCOMH deselect level
  command(0x78);  //OLED command set disabled
  command(0x28);  //function set (fundamental command set)
  command(0x01);  //clear display
  command(0x80);  //set DDRAM address to 0x00
  command(0x0C);  //display ON
  msleep(100);
  output();
  msleep(2000);
  LE_INFO("END");
  le_spi_Close(spiHandle);

}

Here’s my arduino code:

#include <Wire.h>
#include <SPI.h>

int CS = 10;
int RES = 9;

unsigned char text1[] = {"TANKTRONIKSº"};
unsigned char text2[] = {"DEVIL TEST"};

#define MY_SPI_MODE SPI_MODE3

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

void command(unsigned char c) {
  digitalWrite(CS, LOW);
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, MY_SPI_MODE));
  SPI.transfer(0xF8);  // Command mode transfer prefix
  SPI.transfer(reverseBits(c & 0x0F));  // Transfer lower nibble
  SPI.transfer(reverseBits((c >> 4) & 0x0F));  // Transfer upper nibble
  SPI.endTransaction();
  digitalWrite(CS, HIGH);
}

void data(unsigned char d) {
  digitalWrite(CS, LOW);
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, MY_SPI_MODE));
  SPI.transfer(0xFA);  // Data mode transfer prefix
  SPI.transfer(reverseBits(d & 0x0F));  // Transfer lower nibble
  SPI.transfer(reverseBits((d >> 4) & 0x0F));  // Transfer upper nibble
  SPI.endTransaction();
  digitalWrite(CS, HIGH);
}


void output() {
  int i;
  command(0x01);  // Clear display
  delay(2);
  for(i = 0; i < 11; i++) {
    data(text1[i]);
  }

  command(0xA0);
  for(i = 0; i < 10; i++) {
    data(text2[i]);
  }
}

void setup() {
  pinMode(RES, OUTPUT);
  pinMode(CS, OUTPUT);
  digitalWrite(RES, HIGH);
  digitalWrite(CS, HIGH);
  delay(20);
  SPI.begin();

  // Initialize display
  command(0x2A);  // function set (extended command set)
  command(0x71);  // function selection A, disable internal Vdd regulator
  data(0x00);
  command(0x28);  // function set (fundamental command set)
  command(0x08);  // display off, cursor off, blink off
  command(0x2A);  // function set (extended command set)
  command(0x79);  // OLED command set enabled
  command(0xD5);  // set display clock divide ratio/oscillator frequency
  command(0x70);  // set display clock divide ratio/oscillator frequency
  command(0x78);  // OLED command set disabled
  command(0x09);  // extended function set (4-lines)
  command(0x06);  // COM SEG direction
  command(0x72);  // function selection B
  data(0x00);     // ROM CGRAM selection
  command(0x2A);  // function set (extended command set)
  command(0x79);  // OLED command set enabled
  command(0xDA);  // set SEG pins hardware configuration
  command(0x10);  // set SEG pins
  command(0xDC);  // function selection C
  command(0x00);  // function selection C
  command(0x81);  // set contrast control
  command(0x7F);  // set contrast control
  command(0xD9);  // set phase length
  command(0xF1);  // set phase length
  command(0xDB);  // set VCOMH deselect level
  command(0x40);  // set VCOMH deselect level
  command(0x78);  // OLED command set disabled
  command(0x28);  // function set (fundamental command set)
  command(0x01);  // clear display
  command(0x80);  // set DDRAM address to 0x00
  command(0x0C);  // display ON
  delay(100);
  output();
}

void loop() {
  
  
}

Here is the glitch


As you can see the clock is period is smaller where noted, this happens randomly

Thanks

Which fiirmware are you using?

Have you tried in mangoh board?

If you run to code without the iot card, do you still see the glitch?

Excuse my ignorance but I don’t know what to answer, I assume the FX30S has the latest version and I just plugged the iot card as soon as I received it

You can type ati3 and ati8 in AT command port to check firmware version

aattii33
Manufacturer: Sierra Wireless, Incorporated
Model: FX30S(WP7702)
Revision: SWI9X06Y_02.36.08.09 c094f4 jenkins 2022/06/24 03:14:28
IMEI: 354723090956201
IMEI SV: 8
FSN: AT325475140410
+GCAP: +CGSM

OK
aattii88
Legato Ver: 21.05.0.54b96444_0a6e18078edde5151619cb964564694d_modified
Yocto Ver: SWI9X06Y_03.00.13.00 2022-12-28_08:23:43
OS Ver: Linux version 4.14.253 (oe-user@oe-host) ( gcc version 9.3.0 (GCC), GNU ld (GNU Binutils) 2.34.0.20200220) #1 PREEMPT Wed Dec 28 07:40:21 UTC 2022
LK Ver: 1.3.0_1aea4d8ec8
RootFS Ver: SWI9X06Y_03.00.13.00 2022-12-28_08:23:43
UserFS Ver: unknown
MCU Ver: 002.015

OK

Have you tried in mangoh board?

If you run to code without the iot card, do you still see the glitch?

I don’t understand. I got the IoT board to give the FX30S SPI capabilities. Is there any other way I can try?

If you run to code without the iot card, do you still see the glitch?

The iot card is the one which has the spi master. If I’d run the code without the iot card no signal would come out…

Even there is no client, i remember spi master can still has signal