2nd hardware SPI for display

Hi,
I'm using the default hardware SPI for a RFM95 and connected a ST7735 display to my SAMD21 using Adafruits GFX library and software SPI. Unfortunatly via software SPI the refresh rate of the display is quite slow.

My display is attached to PA04, PA06, PA07, PA10, PA11 which should be SERCOM0 and also usable as hardware SPI.

How can I use the Adafruit GFX library with a second harware SPI on a SAMD21?

Is there a way to use 2 HW SPIs?

  Adafruit_ST7735 display = Adafruit_ST7735(TFT_CS, TFT_DC, PIN_TFT_SDA, PIN_TFT_SCK, TFT_RST);

Why do you need another SPI? All devices can share the same spi resource by using different CS pin.

Hi, for maximum speed and I wanted a sperate SPI for the wireless module as this is a critical part

Adafruit have an excellent tutorial on configuring the SAMD21 with additional hardware SPI, I2C and Serial ports: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/overview.

Thank you,
I'm trying to understand the tutorial but may have some language barrieres.. and therefore some follow-up questions.
Question#1
As far as I understood I need to define a new SPI, correct?
What I'm not 100% sure where I need to do this?
Do I need to modifiy SPI.cpp and add it there?

SPIClass SPI2 (&PERIPH_SPI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI, PAD_SPI_TX, PAD_SPI_RX);

and additional macros in variant.h or do I need to put that in my main sketch?

Question#2:
After creating a new SPI I need to modify the graphics library Adafruit_GFX.h, Adafruit_ST7735.h somehow I guess? Same question, do I need to modify andd add the SPI2 directly into those files or in my main sketch?
So far as I understood there are only two option yet, You can select the default SPI or a software one. So somehow I have to tell the library that there is now also a 2nd hardware SPI

//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
Adafruit_ST7735 tft = Adafruit_ST7735(PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_MOSI, PIN_TFT_SCLK, PIN_TFT_RST);

Thanks :slight_smile:


That's how my display is connected right now to the SAMD21G

#define PIN_TFT_DCA0 17    //PA04 pin9   SERCOM0/PAD[0]
#define PIN_TFT_MOSI 8      //PA06 pin11 SERCOM0/PAD[2]
#define PIN_TFT_SCLK 9       //PA07 pin12 SERCOM0/PAD[3
#define PIN_TFT_CS 1           //PA10 pin15
#define PIN_TFT_RST 0         //PA11 pin16

Adafruit_ST7735 tft = Adafruit_ST7735(PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_MOSI, PIN_TFT_SCLK, PIN_TFT_RST);

Hi @timtailors

If the ST7735 library doesn't have the option to pass an SPIClass pointer (or reference) in either the library's class constructor or initialisation function such as begin(), then you'll need to modify it.

It'll also require any calls to the standard SPI object within the library's functions, to be replaced with an SPIClass pointer as well, for example:

From this:

SPI.transfer(data);

to something like this (with SPIClass* spi):

spi->transfer(data);

Hi,

I tested the followong code and there appears no error so I suspect that it could work. However I only got a white screen so far.

#define PIN_TFT_DCA0 17    //PA04 pin9   SERCOM0/PAD[0]
#define PIN_TFT_MOSI 8      //PA06 pin11 SERCOM0/PAD[2]
#define PIN_TFT_SCLK 9       //PA07 pin12 SERCOM0/PAD[3
#define PIN_TFT_CS 1           //PA10 pin15
#define PIN_TFT_RST 0         //PA11 pin16

SPIClass mySPI (&sercom0, -1, PIN_TFT_SCLK, PIN_TFT_MOSI, SPI_PAD_0_SCK_3, SERCOM_RX_PAD_0); //miso,clk, mosi

Adafruit_ST7735 tft = Adafruit_ST7735(&mySPI, PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_RST); //-Just used for setup

void setup() {
    mySPI.begin();
....

is my SPIClass declaration correct?

Thanks! :slight_smile:

Hi @timtailors

No, SPI_PAD_0_SCK_3 indicates that MOSI is on pad 0 and SCK on pad 3, while SERCOM_RX_PAD_0 indicates that MISO is on pad 0. MOSI and MISO can't both be on pad 0.

Also, the definition for the SPIClass constructor is:

SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx)

The second parameter is a uint8_t, so can't be specified as -1. In this case it would be easier to choose an unused dummy MISO pin.

@timtailors I believe the SPIClass should be:

SPIClass mySPI (&sercom0, PIN_TFT_MISO, PIN_TFT_SCLK, PIN_TFT_MOSI, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0); //miso,clk, mosi

HI thanks for your suggestion. I got it what you mean, quite confusing this SERCOM thing even if I read the tutorial several times now.

However I tested the code but unfortuntaly without success. I connected my small Logic analyzer to get an understanding what's happening on the wires.
I compared the "working" version with the soft SPI and the hardware SPI:

software SPI
Adafruit_ST7735 tft = Adafruit_ST7735(PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_MOSI, PIN_TFT_SCLK, PIN_TFT_RST);
softSPI


hardware SPI

SPIClass mySPI (&sercom0, 6, PIN_TFT_SCLK, PIN_TFT_MOSI, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0); //miso,clk, mosi
Adafruit_ST7735 tft = Adafruit_ST7735(&mySPI, PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_RST);

hwSPI

So some activity is there but still some is missing,

This is the test sketch:

/*
ST7735 SAMD21 Test
*/
#include <Arduino.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define PIN_TFT_DCA0 17 //PA04 pin9  ch0
#define PIN_TFT_MOSI 8  //PA06 pin11 ch1
#define PIN_TFT_SCLK 9  //PA07 pin12 ch2
#define PIN_TFT_CS 1    //PA10 pin15 ch3
#define PIN_TFT_RST 0   //PA11 pin16 ch4
#define PIN_TFT_EN 38   //PA13 pin22 EXTINT[13]
#define PIN_TEST_LED 6  //PA20 pin29 ch5

SPIClass mySPI (&sercom0, 6, PIN_TFT_SCLK, PIN_TFT_MOSI, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0); //miso,clk, mosi
       
//Adafruit_ST7735 tft = Adafruit_ST7735(PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_MOSI, PIN_TFT_SCLK, PIN_TFT_RST); //working but it's soft SPI only
Adafruit_ST7735 tft = Adafruit_ST7735(&mySPI, PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_RST); //-Just used for setup


void setup() {
  delay(1000);
  mySPI.begin();
  pinMode(PIN_TFT_EN, OUTPUT); digitalWrite(PIN_TFT_EN, HIGH); //screen power enable

  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.setRotation(1);
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_YELLOW);
  tft.println("Hello World!");
}





void loop() {
  pinMode(PIN_TEST_LED, OUTPUT); digitalWrite(PIN_TEST_LED, HIGH);
  delay(200);
  pinMode(PIN_TEST_LED, OUTPUT); digitalWrite(PIN_TEST_LED, LOW);
  delay(200);
  

}

edit
i may missed the pinPeripheral section


It seems to work :smiley: At least it's refreshing faster than with soft SPI. Still there is a "black screen" between the refreshes and not as smoothles like a SSD1306 OLED but much better than before
Your're a genius, thanks Martin!! :smiley:

/*
ST7735 SAMD21 Test
*/
#include <Arduino.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
#include "wiring_private.h" // pinPeripheral() function

#define PIN_TFT_DCA0 17 //PA04 pin9  SERCOM0/PAD[0] ch0
#define PIN_TFT_MOSI 8  //PA06 pin11 SERCOM0/PAD[2] ch1
#define PIN_TFT_SCLK 9  //PA07 pin12 SERCOM0/PAD[3 ch2
#define PIN_TFT_CS 1    //PA10 pin15 ch3
#define PIN_TFT_RST 0   //PA11 pin16 ch4
#define PIN_TFT_EN 38   //PA13 pin22 EXTINT[13]
#define PIN_TEST_LED 6  //PA20 pin29

SPIClass mySPI (&sercom0, 6, PIN_TFT_SCLK, PIN_TFT_MOSI, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0); //miso,clk, mosi
       
//Adafruit_ST7735 tft = Adafruit_ST7735(PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_MOSI, PIN_TFT_SCLK, PIN_TFT_RST); //working but it's soft SPI only
Adafruit_ST7735 tft = Adafruit_ST7735(&mySPI, PIN_TFT_CS, PIN_TFT_DCA0, PIN_TFT_RST); //-Just used for setup


void setup() {
  pinMode(PIN_TFT_EN, OUTPUT); digitalWrite(PIN_TFT_EN, HIGH); //screen power enable
  delay(1000);
  mySPI.begin();
  
  // Assign pins  to SERCOM functionality
  pinPeripheral(PIN_TFT_DCA0, PIO_SERCOM_ALT);
  pinPeripheral(PIN_TFT_MOSI, PIO_SERCOM_ALT);
  pinPeripheral(PIN_TFT_SCLK, PIO_SERCOM_ALT);
  
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.setRotation(1);
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_YELLOW);
  tft.println("Hello World!");
}





uint8_t i=0;
void loop() {

  pinMode(PIN_TEST_LED, OUTPUT); digitalWrite(PIN_TEST_LED, HIGH);
  delay(200);
  pinMode(PIN_TEST_LED, OUTPUT); digitalWrite(PIN_TEST_LED, LOW);
  delay(200);
  
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_YELLOW);
  tft.println("Hello World!"); tft.println(i++);
}

@timtailors Glad to hear that you got it working.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.