Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SPI strange behaviour
15-02-2017, 03:55 PM, (This post was last modified: 15-02-2017, 04:32 PM by KarloK.)
#1
SPI strange behaviour
Hey there,

A colleague of mine and me are trying to port a library (you can find it right here). The basic idea seems to work since we see sometimes the correct behaviour of the display.

But: The correct behaviour happens randomly. We have recognized the following parameters that indicate us the behave state of the display:
  • Green LED: Connected to UEXT CS Pin - indicating the state of the CS
  • Yellow LED: Indicator for the position inside the code (please see the code below)
  • Display behaviour
There are a couple of scenarios that we receognized: 
  • After the setup the green LED remains HIGH and the display nor the yellow LED do anything.
  • The display is ON and stays white, the yellow and green LED behave as expected
  • The display shows any strange behaviour in terms of colours and shapes, green and yellow LED behave as expected
  • Directly after the setup, green LED stays HIGH and the display does nothing
  • After a while, the green (and the yellow one) stay HIGH and the display freezes
We have double- and triplechecked the settings of the register (on display side) and we have tried the code with the Arduino- behaving as expected.

When we try to use the Pinguino, it does not work. We expect that there is a misstake inside our SPI usage. 

When you look at the following code, do you have any idea what is wrong with our code or SPI usage?:

Code:
/*-----------------------------------------------------
Author:  --<>
Date: 2017-02-14
Description:

-----------------------------------------------------*/
// Definitions
//Excluded: All constants due to reading purposes

//PINs
#define CS 32
#define RST 5
#define MOSI 11
#define MISO 12
#define CLK 13
#define WIDTH 800
#define HEIGHT 480

boolean begin();
void    displayOn(boolean on);
void    GPIOX(boolean on);
void    PWM1config(boolean on, uint8_t clock);
void    PWM1out(uint8_t p);
void    fillScreen(uint16_t color);
void rectHelper(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color, boolean filled);
boolean waitPoll(uint8_t regname, uint8_t waitflag);
void PLLinit();
void  writeReg(uint8_t reg, uint8_t val);
void  writeData(uint8_t d);
void  writeCommand(uint8_t d);
uint8_t  readReg(uint8_t reg);
uint8_t  readData();
uint8_t  readStatus();
void initialize();

void setup() {

 /* Initialise the display using 'RA8875_800x480' */
 begin();

 displayOn(true);
 GPIOX(true);      // Enable TFT - display enable tied to GPIOX
 PWM1config(true, RA8875_PWM_CLK_DIV1024); // PWM output for backlight
 PWM1out(255);
 //fillScreen(RA8875_RED);
 pinMode(30, OUTPUT);
}

void loop() {
   // put your main code here, to run repeatedly:
   fillScreen(RA8875_RED);
   digitalWrite(30, HIGH);
   delay(3000);
   fillScreen(RA8875_BLUE);
   digitalWrite(30, LOW);
   delay(3000);
   
}

void fillScreen(uint16_t color)
{  
 rectHelper(0, 0, WIDTH-1, HEIGHT-1, color, true);
}

void rectHelper(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color, boolean filled)
{
 /* Set X */
 writeCommand(0x91);
 writeData(x);
 writeCommand(0x92);
 writeData(x >> 8);
 
 /* Set Y */
 writeCommand(0x93);
 writeData(y);
 writeCommand(0x94);      
 writeData(y >> 8);
 
 /* Set X1 */
 writeCommand(0x95);
 writeData(w);
 writeCommand(0x96);
 writeData((w) >> 8);
 
 /* Set Y1 */
 writeCommand(0x97);
 writeData(h);
 writeCommand(0x98);
 writeData((h) >> 8);

 /* Set Color */
 writeCommand(0x63);
 writeData((color & 0xf800) >> 11);
 writeCommand(0x64);
 writeData((color & 0x07e0) >> 5);
 writeCommand(0x65);
 writeData((color & 0x001f));

 /* Draw! */
 writeCommand(RA8875_DCR);
 if (filled)
 {
   writeData(0xB0);
 }
 else
 {
   writeData(0x90);
 }
 
 /* Wait for the command to finish */
 waitPoll(RA8875_DCR, RA8875_DCR_LINESQUTRI_STATUS);
}

boolean waitPoll(uint8_t regname, uint8_t waitflag) {
 /* Wait for the command to finish */
 while (1)
 {
   uint8_t temp = readReg(regname);
   if (!(temp & waitflag))
     return true;
 }  
 return false; // MEMEFIX: yeah i know, unreached! - add timeout?
}


boolean begin() {

 pinMode(CS, OUTPUT);
 pinMode(RST, OUTPUT);
 
 digitalWrite(CS, HIGH);
 digitalWrite(RST, LOW);
 delay(100);
 digitalWrite(RST, LOW);
 delay(100);
 digitalWrite(RST, HIGH);
 delay(100);
 // TO Adjust SPI and other functions
 // Pinguino Variant
 SPI.init();
 SPI.setClock(SPI2, 4000000);
// SPI.setClockDivider(SPI2,SPI_PBCLOCK_DIV128);
 SPI.setDataMode(SPI2,SPI_MODE0);
 SPI.begin(SPI2);
 
 if (readReg(0) != 0x75) {
   return false;
 }
 
  initialize();

SPI.setClock(SPI2, 17500000);

  return true;
}

void PWM1out(uint8_t p) {
 writeReg(RA8875_P1DCR, p);
}

void PWM1config(boolean on, uint8_t clock) {
 if (on) {
   writeReg(RA8875_P1CR, RA8875_P1CR_ENABLE | (clock & 0xF));
 } else {
   writeReg(RA8875_P1CR, RA8875_P1CR_DISABLE | (clock & 0xF));
 }
}

void GPIOX(boolean on) {
 if (on)
   writeReg(RA8875_GPIOX, 1);
 else
   writeReg(RA8875_GPIOX, 0);
}

void displayOn(boolean on)
{
if (on)
  writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPON);
else
  writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPOFF);
}

void PLLinit() {
   writeReg(RA8875_PLLC1, RA8875_PLLC1_PLLDIV1 + 10);
   delay(1);
   writeReg(RA8875_PLLC2, RA8875_PLLC2_DIV4);
   delay(1);
}

void  writeReg(uint8_t reg, uint8_t val)
{
 writeCommand(reg);
 writeData(val);
}

void  writeData(uint8_t d)
{
 digitalWrite(CS, LOW);
 // TODO the SPI functions have to be checked
 SPI.transfer(SPI2,RA8875_DATAWRITE);
 SPI.transfer(SPI2,d);
 digitalWrite(CS, HIGH);
}

void  writeCommand(uint8_t d)
{
 digitalWrite(CS, LOW);
 // TODO the SPI functions have to be checked
 SPI.transfer(SPI2,RA8875_CMDWRITE);
 SPI.transfer(SPI2,d);
 digitalWrite(CS, HIGH);
}

uint8_t  readReg(uint8_t reg)
{
 writeCommand(reg);
 return readData();
}

uint8_t  readData()
{
 digitalWrite(CS, LOW);
 // TODO check SPI
 SPI.transfer(SPI2,RA8875_DATAREAD);
 uint8_t x = SPI.transfer(SPI2,0x0);
 digitalWrite(CS, HIGH);
 return x;
}

uint8_t  readStatus()
{
 digitalWrite(CS, LOW);
 // TODO Check SPI
 SPI.transfer(SPI2,RA8875_CMDREAD);
 uint8_t x = SPI.transfer(SPI2,0x0);
 digitalWrite(CS, HIGH);
 return x;
}

void initialize() {
 PLLinit();
 writeReg(RA8875_SYSR, RA8875_SYSR_16BPP | RA8875_SYSR_MCU8);

 /* Timing values */
 uint8_t pixclk;
 uint8_t hsync_start;
 uint8_t hsync_pw;
 uint8_t hsync_finetune;
 uint8_t hsync_nondisp;
 uint8_t vsync_pw;
 uint16_t vsync_nondisp;
 uint16_t vsync_start;

 /* Set the correct values for the display being used */  

   pixclk          = RA8875_PCSR_PDATL | RA8875_PCSR_2CLK;
   hsync_nondisp   = 26;
   hsync_start     = 32;
   hsync_pw        = 96;
   hsync_finetune  = 0;
   vsync_nondisp   = 32;
   vsync_start     = 23;
   vsync_pw        = 2;

 writeReg(RA8875_PCSR, pixclk);
 delay(1);
 
 /* Horizontal settings registers */
 writeReg(RA8875_HDWR, (WIDTH/ 8) - 1);                          // H width: (HDWR + 1) * 8 = 480
 writeReg(RA8875_HNDFTR, RA8875_HNDFTR_DE_HIGH + hsync_finetune);
 writeReg(RA8875_HNDR, (hsync_nondisp - hsync_finetune - 2)/8);    // H non-display: HNDR * 8 + HNDFTR + 2 = 10
 writeReg(RA8875_HSTR, hsync_start/8 - 1);                         // Hsync start: (HSTR + 1)*8
 writeReg(RA8875_HPWR, RA8875_HPWR_LOW + (hsync_pw/8 - 1));        // HSync pulse width = (HPWR+1) * 8
 
 /* Vertical settings registers */
 writeReg(RA8875_VDHR0, (uint16_t)(HEIGHT- 1) & 0xFF);
 writeReg(RA8875_VDHR1, (uint16_t)(HEIGHT- 1) >> 8);
 writeReg(RA8875_VNDR0, vsync_nondisp-1);                          // V non-display period = VNDR + 1
 writeReg(RA8875_VNDR1, vsync_nondisp >> 8);
 writeReg(RA8875_VSTR0, vsync_start-1);                            // Vsync start position = VSTR + 1
 writeReg(RA8875_VSTR1, vsync_start >> 8);
 writeReg(RA8875_VPWR, RA8875_VPWR_LOW + vsync_pw - 1);            // Vsync pulse width = VPWR + 1
 
 /* Set active window X */
 writeReg(RA8875_HSAW0, 0);                                        // horizontal start point
 writeReg(RA8875_HSAW1, 0);
 writeReg(RA8875_HEAW0, (uint16_t)(WIDTH- 1) & 0xFF);            // horizontal end point
 writeReg(RA8875_HEAW1, (uint16_t)(WIDTH- 1) >> 8);
 
 /* Set active window Y */
 writeReg(RA8875_VSAW0, 0);                                        // vertical start point
 writeReg(RA8875_VSAW1, 0);  
 writeReg(RA8875_VEAW0, (uint16_t)(HEIGHT- 1) & 0xFF);           // horizontal end point
 writeReg(RA8875_VEAW1, (uint16_t)(HEIGHT- 1) >> 8);
 
 /* ToDo: Setup touch panel? */
 
 /* Clear the entire window */
 writeReg(RA8875_MCLR, RA8875_MCLR_START | RA8875_MCLR_FULL);
 delay(500);
}
//EDIT: We know, that we have to decrease the speed of SPI during the initialize/setup phase for setting all registers initially (currently, we have the best results using 5MHz). Later, we have to increase the speed to ~20MHz (maximum approx. 22MHz, based on information from the internet, currently 18MHz since we get the best results with a value of 18MHz).

We are using both Pinguino IDE v11, and we get both the same non-deterministic behaviour.
Reply
17-02-2017, 06:10 PM,
#2
RE: SPI strange behaviour
Is it an option to try with Pinguino v12 ?
I fixed a lot of issues in the latest version (15-02-2017) and I think it works better than v11.
It is easier to complain than it is to do, but it is better to do than it is to complain.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)