SPI register read debug

Hi All,

We are using GS2972 and have to read the register values. I am attaching the datasheet here. developed code is not working with the register read. I am not sure whether my logic in code is working fine or not. It is highly appreciated if you assist me to debug on this.

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

#include <SPI.h>

  void setup()
{

  Serial.begin(9600);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  SPI.beginTransaction(SPISettings(5998800, MSBFIRST, SPI_MODE0));
  //SPI.begin();
}


void GSPI_Read( uint16_t Reg_comm=0x8001)
{
  digitalWrite(SLAVESELECT,LOW);
  delayMicroseconds(1);
  SPI.transfer((uint16_t)(Reg_comm));
  //SPI.transfer((char)(Reg_comm));
  delayMicroseconds(1); 
  uint16_t  Reg_value;
  Reg_value |= (uint16_t) SPI.transfer(0xff)<<8;
  Reg_value= SPI.transfer(0xff);
  delayMicroseconds(5);
  digitalWrite(SLAVESELECT,HIGH);
  Serial.print(Reg_value, BIN);
}
void loop(void)
{
  
}

GSPI flowchart_v0_2.pdf (40.3 KB)

GSPI Application Note.pdf (237 KB)

don't you want to use SPI.transfer16() if your Reg_comm is on 2 bytes?

Hello J-M-L,

I have tried with SPI.transfer16. but still i am not able to read register values.

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

#include <SPI.h>
  void setup()
{

  Serial.begin(9600);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  SPI.beginTransaction(SPISettings(5998800, MSBFIRST, SPI_MODE0));
  //SPI.begin();
}


void GSPI_Read( uint16_t Reg_comm=0x8001)
{
  digitalWrite(SLAVESELECT,LOW);
  delayMicroseconds(1);
  SPI.transfer16((uint16_t)(Reg_comm));
  //SPI.transfer((char)(Reg_comm));
  delayMicroseconds(1); 
  uint16_t  Reg_value;
  Reg_value = (uint16_t) SPI.transfer16(0xffff);
  //Reg_value= SPI.transfer16(0xff);
  delayMicroseconds(5);
  digitalWrite(SLAVESELECT,HIGH);
  Serial.print(Reg_value, BIN);
}
void loop(void)
{
  
}

Any help is much appreciated.

Is there any issue with code developed?

well you never call GSPI_Read... so can't get much out

Note that there is a SPI.beginTransaction() but don't call endTransaction() to allow other libraries to use the SPI bus

could you try the following code and see what the Serial console (opened at 115200 bauds) says?

#include <SPI.h>
SPISettings GS2972Settings(5998800, MSBFIRST, SPI_MODE0); // not sure where 5998800 comes from

const byte slaveSelectPin = 10;  // SS

void printlnWord(uint16_t w)
{
  for (int8_t i = 15; i >= 0; --i) Serial.write(bitRead(w, i) ? '1' : '0');
  Serial.write('\n');
}


uint16_t GSPI_Read( uint16_t regIndex = 0x8001)
{
  uint16_t regValue1 = 0xFFFF, regValue2 = 0xFFFF;
  SPI.beginTransaction(GS2972Settings);
  digitalWrite(slaveSelectPin, LOW);
  regValue1 = SPI.transfer16(regIndex);
  // delayMicroseconds(1); // assuming cost of function call will exceed the 12ns
  regValue2 = SPI.transfer16(0xFFFF);
  digitalWrite(slaveSelectPin, HIGH);
  SPI.endTransaction();

  Serial.print(F("Reg Value1 = 0b")); printlnWord(regValue1);
  Serial.print(F("Reg Value2 = 0b")); printlnWord(regValue2);

  return regValue2;
}

void setup()
{
  Serial.begin(115200);
  pinMode(slaveSelectPin, OUTPUT);
  digitalWrite(slaveSelectPin, HIGH); //disable device
  SPI.begin();
  GSPI_Read();
}

void loop(void) {}

PS/ what type of arduino are you running on and where does 5998800 comes from?

  uint16_t  Reg_value;
  Reg_value |= (uint16_t) SPI.transfer(0xff)<<8;
  Reg_value= SPI.transfer(0xff);

You are taking 16 bits of uninitialized memory, or-ing some bits into the high byte, and replacing the value with the low byte. Your result is the bottom 8 bits of the register.

What you wanted to do is:

  uint16_t  Reg_value;
  Reg_value = (uint16_t) SPI.transfer(0xff) << 8;
  Reg_value |= SPI.transfer(0xff);

@johnwasser

technically right but seems OP's component requires 16 bits messages and gets 16 bits back, so SPI.transfer() does not cut it in my opinion - hence the recommendation for SPI.transfer16()

@OP

1. Let us try to read the default content of CFG_AUD Register, which is 0001011010001100b (0x168C, P100-101 of data sheets). This is to ensure that the SPI-Host (the Arduino) is communicating well with the slave device (the GS2972). The CFG-AUD Register is located at address 0x0400 (400h).

2. The slave device has a pin named JTAG/HOST which must be pulled down to LOW to enable the GSPI Interface. I have no idea if you are using a breakout board or the bare chip. I also don't have access to the device; however, I am making an experimental set up for you based on my readings of the data sheets/application notes and my experience with SPI Protocol.

3. Codes (untested): Connect DPin-10 of UNO with JTAG/HOST Pin of GS2972 device

#include<SPI.h> //contains meanings of symbolic names of SS (SS/), MOSI, MISO, SCK etc.

void setup()
{
  Serial.begin(9600);  ////enable Serial Monitor
  SPI.begin(); ////DPin-10, 11, 12, 13  are SS (Output), MOSI (OUTPUT), MISO (Input), SCK (Output
  SPI.setClockDivider(SPI_CLOCK_DIV16);   //speed: 16MHz/16 --> 1 = MBits/sec
  digitalWrite(SS, LOW);  //GS2972 is selected
}

void loop()
{
  uint16_t y = SPI.transfer16(0x8400); //(0x1400); ////configure CFG_AUD Register for read mode; no auto inc.
  delayMicroseconds(30);    //transmission delay ~= 30 us (1 usx16 = 16 is theoretical)
  uint16_t z = SPI.transfer16(0xFFFF);  //create 16 SCK pulses to bring out 16-bit data from CFG_AUD Reg.
  delayMicroseconds(30);
  for (int i = 15; i >= 0; i--)
  {
    bool n = bitRead(z, i);  //read bit-15, 14, ..., 0
    Serial.print(n, BIN); //Serial Monitor must show: 0001011010001100 (check data sheets)
  }
  Serial.println();
  delay(2000);  //read CFG_AUD at every 2-sec interval and show its content on Serial Monitor
}

4. Upload the sketch of Step-3.
5. Press RESET Key of UNO.
6. Bring in Serial Monitor at Bd= 9600.
7. Check that Serial Monitor shows: 0001011010001100 at 2-sec interval.
8. If sketch of Step-3 does not work, try the following sketch:

#include<SPI.h> ////contains meanings of symbolic names of SS (SS/), MOSI, MISO, SCK etc.

void setup()
{
  Serial.begin(9600);  ////enable Serial Monitor
  SPI.begin(); ////DPin-10, 11, 12, 13  are SS (Output), MOSI (Output), MISO (Input), SCK (Output)
  SPI.setClockDivider(SPI_CLOCK_DIV16);   //speed: 16MHz/16 --> 1 = MBits/sec
  digitalWrite(SS, LOW);    //GS2972 is selected
}

void loop()
{
  byte m = SPI.transfer(0x84);//configure CFG_AUD Register for read mode; no auto inc.
  delayMicroseconds(15);    //transmission delay ~= 15 us (1 usx8 = 8 is theoretical)
  m = SPI.transfer(0x00);
  delayMicroseconds(15);    //transmission delay
  //-------------------------------------------------------------------------------------
  byte x = SPI.transfer(0xFF); //create 8 SCK pulses to bring out b15-b8 data bits from CFG_AUD Reg.
  delayMicroseconds(15);    //transmission delay
  byte y = SPI.transfer(0xFF); //create 8 SCK pulses to bring out b7-b0 data bits from CFG_AUD Reg.
  delayMicroseconds(15);
  //---------------------
  uint16_t z = x << 8 | y;
  for (int i = 15; i >= 0; i--)
  {
    bool n = bitRead(z, i);  //read bit-15m 14, ..., 0
    Serial.print(n, BIN); //Serial Monitor must show: 0001011010001100 (check data sheets)
  }
  Serial.println();
  delay(2000);  //read CFG_AUD at every 2-sec interval and show its content on Serial Monitor
}

@GolamMostafa and @J-M-L @johnwasser

Thanks for helping mind. But it did not work well. I am getting 0xFFFF value from all registers. Therefore i checked with logic analyzer . I am attaching the screenshot of it. (NB: marked lines in screenshot is corresponding to: D3-SS, D4-MOSI,D5-MISO, D6-SCLK).
The board is custom board of GS2972 and pulled low on JTAG/HOST line. But i am confused why we are getting 0xFFFF from GS2972. From the logic analyzer, it seems interface is proper and communicating... But the values shows something wrong.

Is there any issue on code? How can i ensure that interface is communicating properly?
Your insights and help is much appreciated.

Regards,
Ameenu

did you use the code in #3 or something else?

Hi @J-M-L,

Yes i tested with All three codes on above and register is 0x800A, 0x800B, 0x8008..etc

#include<SPI.h> //contains meanings of symbolic names of SS (SS/), MOSI, MISO, SCK etc.

void setup()
{
  Serial.begin(9600);  ////enable Serial Monitor
  SPI.begin(); ////DPin-10, 11, 12, 13  are SS (Output), MOSI (OUTPUT), MISO (Input), SCK (Output
  SPI.setClockDivider(SPI_CLOCK_DIV16);   //speed: 16MHz/16 --> 1 = MBits/sec
  digitalWrite(SS, LOW);  //GS2972 is selected
}

void loop()
{
  uint16_t y = SPI.transfer16(0x800A); ////configure Register for read mode; no auto inc.
  delayMicroseconds(30);    //transmission delay ~= 30 us (1 usx16 = 16 is theoretical)
  uint16_t z = SPI.transfer16(0xFFFF);  //create 16 SCK pulses to bring out 16-bit data 
  delayMicroseconds(30);
  for (int i = 15; i >= 0; i--)
  {
    bool n = bitRead(z, i);  //read bit-15, 14, ..., 0
    Serial.print(n, BIN); 
  }
  Serial.println();
  delay(2000);  //read at every 2-sec interval and show its content on Serial Monitor
}

I have to write 0xCB89h to register 0x00Ah and 0x0100h to register 0x00Bh. But i am not getting even default value from the register..

1. Did you try the sketch of Post#6 to read known/default vcontnet of CFG_AUD Register? Are you getting 0x168C? Which Arduino Board are you using - UNO, NANO or MEGA?

2. The address of CFG_AUD Regsiter is: 400h (Fig-1).

Figure-1:

3. When Read bit (HIGH, Fig-2) Bit is added, the command word becomes: 8400h and not 1400h which I have mistakenly put in my Post#6.


Figure-2:

4. Please, re-run the following corrected cprogram in UNO with command word 0x8400 and report the result.

#include<SPI.h> //contains meanings of symbolic names of SS (SS/), MOSI, MISO, SCK etc.

void setup()
{
  Serial.begin(9600);  ////enable Serial Monitor
  SPI.begin(); ////DPin-10, 11, 12, 13  are SS (Output), MOSI (OUTPUT), MISO (Input), SCK (Output
  SPI.setClockDivider(SPI_CLOCK_DIV16);   //speed: 16MHz/16 --> 1 = MBits/sec
  digitalWrite(SS, LOW);  //GS2972 is selected
}

void loop()
{
  uint16_t y = SPI.transfer16(0x8400); ////configure CFG_AUD Register for read mode; no auto inc.
  delayMicroseconds(30);    //transmission delay ~= 30 us (1 usx16 = 16 is theoretical)
  uint16_t z = SPI.transfer16(0xFFFF);  //create 16 SCK pulses to bring out 16-bit data from CFG_AUD Reg.
  delayMicroseconds(30);
  for (int i = 15; i >= 0; i--)
  {
    bool n = bitRead(z, i);  //read bit-15, 14, ..., 0
    Serial.print(n, BIN); //Serial Monitor must show: 0001011010001100 (check data sheets)
  }
  Serial.println();
  Serial.println(z, HEX);    //Serial Monitor should show: 168C
  delay(2000);  //read CFG_AUD at every 2-sec interval and show its content on Serial Monitor
}

5. IIf sketch of Step-4 does not work, try the following one in UNO.

#include<SPI.h> ////contains meanings of symbolic names of SS (SS/), MOSI, MISO, SCK etc.

void setup()
{
  Serial.begin(9600);  ////enable Serial Monitor
  SPI.begin(); ////DPin-10, 11, 12, 13  are SS (Output), MOSI (Output), MISO (Input), SCK (Output)
  SPI.setClockDivider(SPI_CLOCK_DIV16);   //speed: 16MHz/16 --> 1 = MBits/sec
  digitalWrite(SS, LOW);    //GS2972 is selected
}

void loop()
{
  byte m = SPI.transfer(0x84);//configure CFG_AUD Register for read mode; no auto inc.
  delayMicroseconds(15);    //transmission delay ~= 15 us (1 usx8 = 8 is theoretical)
  m = SPI.transfer(0x00);
  delayMicroseconds(15);    //transmission delay
  //-------------------------------------------------------------------------------------
  byte x = SPI.transfer(0xFF); //create 8 SCK pulses to bring out b15-b8 data bits from CFG_AUD Reg.
  delayMicroseconds(15);    //transmission delay
  byte y = SPI.transfer(0xFF); //create 8 SCK pulses to bring out b7-b0 data bits from CFG_AUD Reg.
  delayMicroseconds(15);
  //---------------------
  uint16_t z = x << 8 | y;
  for (int i = 15; i >= 0; i--)
  {
    bool n = bitRead(z, i);  //read bit-15m 14, ..., 0
    Serial.print(n, BIN); //Serial Monitor must show: 0001011010001100 (check data sheets)
  }
  Serial.println();
  Serial.println(z, HEX);   //Serial Monitor should show: 168C
  delay(2000);  //read CFG_AUD at every 2-sec interval and show its content on Serial Monitor
}

The clock idles low ... have you tried SPI_MODE1?

The signals seems to glitch ...

  • have you tried lower clock rates?
  • Are signal connections short?
  • Perhaps a series 33Ω to 47Ω resistor in the signal lines could help

Hi @GolamMostafa,

Since i am not using Audio function of GS2972, i do not need to read audio register. But i tried to read it and required registers(0x800A). I am attaching the result screenshot here.
UNO is being used to read.
I am confused why it is happening even data logic is being sent properly...

Why should OP try MODE1 (falling edge) operation of SPI Port? Data is clocked in/out og GS2972 at the rising edge of SCK (MODE0). The default mode of UNO is also MODE0.

ameenuvm:
Hi @GolamMostafa,

Since i am not using Audio function of GS2972, i do not need to read audio register. But i tried to read it and required registers(0x800A).

I have chosen to read CFG_AUD regsiter as a part of debug process; because, CFG_AUD register contains well-defined default value. Your screen shots indicate that the device is not being accessed at all.

Why should OP try MODE1 (falling edge) operation of SPI Port? Data is clocked in/out og GS2972 at the rising edge of SCK (MODE0). The default mode of UNO is also MODE0.

Looking at his logic images, data out "responds" to the falling clock edge, so I guess it was "captured" on the rising clock edge, so with the clock signal normally low, this is MODE1.

Also, I think the SPI.beginTransaction function already takes care of the SCK, MISO and MOSI pin configurations, so the setup should be simplified to prevent overriding this, something like:

void setup()
{
  Serial.begin(9600);
  pinMode(SLAVESELECT, OUTPUT); //ss
  digitalWrite(SLAVESELECT, HIGH); //disable device
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE1)); // this takes care of SCK, MISO and MOSI
}

Hi,

How can i ensure interface is communicating properly.
it seems something wrong. But stumbled on debugging..
Would you suggest any insights on that is much appreciated.

I don't have this chip; so, I can't join in in-situ trouble shooting process. What I would like to suggest are:

Are you using the following 10x10-pin stand alone Chip (Fig-1) ? If so, study the functions of every pin and then terminate them properly in direct-HIGH/pull-up HIGH, direct-LOW/pull-down LOW, Vcc, GND, NC (no connection).
GS2972Pic.png
Figure-1:

If you are using some other package like "Breakout Board" or "Evaluation Board/Kit", please post its picture along with link to manufacturer.

GS2972Pic.png

Have you checked their Datasheets and Resources Page? (click at the bottom of page) In the Design Guide there's considerable power supply coupling and filtering requirements, PCB design requirements and pin interface/filtering requirements. IMHO, their evaluation board and software would be a good starting point for your project.

Hi,

Yes. i am using 10x10 GS2972 and settings are as follows:
Set low: JTAG_HOST, STANDBY, DVB_ASI, RATE_SEL0, ANC_BLANKb, DETECT_TRS, GRP1_EN/DISb, GRP2_EN/DISb.Set high: SDO_EN/DISb, TIM_861, SMPTE_BYPASSb, RATE_SEL1, IOPROC_EN/DISb, 20BIT/10BITb.

It is custom board and working properly. But i need to change some register values to get the desired resolution of video. ie, i have to write 0xCB89h to register 0x00Ah and 0x0100h to register 0x00Bh. But now i can not even read the register.

From GSPI interface of GS2972, connected with level translator (3.3V to 5V) and connected to UNO, that is the interface. i probed every pins of level translator and it is getting clock and signals properly.
The same 0xFFFF is getting even i change to the another setup. I am confused how can i ensure the interface is proper