I am working on a project that requires SPI communication with IT8951 (ePaper driver). And not only sending data but reading as well.
I found some examples for Arduino and I made it work using arduino-core. However, I need to write it in pure esp-idf, using (spi_master) library. And I can't make it work.
Is there any SPI expert that would help me, or at least give a hint on how to write working code for bi-directional SPI transfer?
Here is the working arduino based code:
Code: Select all
#include <arduino.h>
#include <SPI.h>
extern "C"
{
#include <stdio.h>
#include <driver/gpio.h>
#define PIN_MISO 12 // data in
#define PIN_MOSI 13 // data out
#define PIN_SCK 18 // clock
#define PIN_CS 5 // chip select
#define PIN_RESET 23 // PIN_RESET
#define PIN_HRDY 25 // busy
#define IT8951_TCON_REG_WR 0x0011
typedef struct
{
uint16_t usPanelW;
uint16_t usPanelH;
uint16_t usImgBufAddrL;
uint16_t usImgBufAddrH;
uint16_t usFWVersion[8]; // 16 Bytes String
uint16_t usLUTVersion[8]; // 16 Bytes String
} IT8951DevInfo;
IT8951DevInfo gstI80DevInfo;
void init()
{
// arduino
pinMode(PIN_SCK, OUTPUT);
pinMode(PIN_CS, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_HRDY, INPUT);
SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, PIN_CS);
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
}
void IT8951WaitForReady()
{
uint8_t ulData = digitalRead(PIN_HRDY);
while (ulData == 0)
{
ulData = digitalRead(PIN_HRDY);
}
}
void IT8951WriteCmdCode(uint16_t usCmdCode)
{
// Set Preamble for Write Command
uint16_t wPreamble = 0x6000;
IT8951WaitForReady();
digitalWrite(PIN_CS, LOW);
SPI.transfer(wPreamble >> 8);
SPI.transfer(wPreamble);
IT8951WaitForReady();
SPI.transfer(usCmdCode >> 8);
SPI.transfer(usCmdCode);
digitalWrite(PIN_CS, HIGH);
}
void IT8951WriteData(uint16_t usData)
{
// Set Preamble for Write Data
uint16_t wPreamble = 0x0000;
IT8951WaitForReady();
digitalWrite(PIN_CS, LOW);
SPI.transfer(wPreamble >> 8);
SPI.transfer(wPreamble);
IT8951WaitForReady();
SPI.transfer(usData >> 8);
SPI.transfer(usData);
digitalWrite(PIN_CS, HIGH);
}
void IT8951ReadNData(uint16_t *pwBuf, uint32_t ulSizeWordCnt)
{
uint32_t i;
uint16_t wPreamble = 0x1000;
IT8951WaitForReady();
digitalWrite(PIN_CS, LOW);
SPI.transfer(wPreamble >> 8);
SPI.transfer(wPreamble);
IT8951WaitForReady();
pwBuf[0] = SPI.transfer(0x00); // dummy
pwBuf[0] = SPI.transfer(0x00); // dummy
IT8951WaitForReady();
for (i = 0; i < ulSizeWordCnt; i++)
{
pwBuf[i] = SPI.transfer(0x00) << 8;
pwBuf[i] |= SPI.transfer(0x00);
}
digitalWrite(PIN_CS, HIGH);
}
void GetIT8951SystemInfo(void *pBuf)
{
uint16_t *pusWord = (uint16_t *)pBuf;
IT8951DevInfo *pstDevInfo;
digitalWrite(PIN_CS, HIGH);
digitalWrite(PIN_RESET, LOW);
vTaskDelay(1000 / portTICK_PERIOD_MS);
digitalWrite(PIN_RESET, HIGH);
IT8951WriteCmdCode(0x0302);
IT8951ReadNData(pusWord, sizeof(IT8951DevInfo) / 2); // Polling PIN_HRDY for each words(2-bytes) if possible
digitalWrite(PIN_CS, LOW);
pstDevInfo = (IT8951DevInfo *)pBuf;
printf("Panel(W,H) = (%d,%d)\r\n",
pstDevInfo->usPanelW, pstDevInfo->usPanelH);
printf("Image Buffer Address = %X\r\n",
pstDevInfo->usImgBufAddrL | (pstDevInfo->usImgBufAddrH << 16));
printf("FW Version = %s\r\n", (uint8_t *)pstDevInfo->usFWVersion);
printf("LUT Version = %s\r\n", (uint8_t *)pstDevInfo->usLUTVersion);
}
int app_main(void)
{
init();
GetIT8951SystemInfo(&gstI80DevInfo);
return 0;
}
}