Go Down

Topic: Using SERCOM within a library (Read 468 times) previous topic - next topic

revolt_randy

Hi all,

Thought I had this figured out once, but ust can't get it to work again.

What I am trying to do is use SERCOM from within a library to set up a second SPI port on a Zero clone. I am trying to set up this second SPI to handle a touchscreen on a display. I am using the XPT2046_Touchscreen library found here: https://github.com/PaulStoffregen/XPT2046_Touchscreen

Here's the Zero sketch that I am using:

Code: [Select]

#include <XPT2046_Touchscreen.h>

#define CS_PIN  7
// MOSI=11, MISO=12, SCK=13

XPT2046_Touchscreen ts(CS_PIN);
//#define TIRQ_PIN  2
//XPT2046_Touchscreen ts(CS_PIN);  // Param 2 - NULL - No interrupts
//XPT2046_Touchscreen ts(CS_PIN, 255);  // Param 2 - 255 - No interrupts
//XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);  // Param 2 - Touch IRQ Pin - interrupt enabled polling

void setup() {
  SerialUSB.begin(9600);
 
  ts.begin();
 
  ts.setRotation(1);
  while (!SerialUSB || (millis() <= 5000));

  SerialUSB.println("TouchTest - started.\n");
}

void loop() {
  if (ts.touched()) {
    TS_Point p = ts.getPoint();
    SerialUSB.print("Pressure = ");
    SerialUSB.print(p.z);
    SerialUSB.print(", x = ");
    SerialUSB.print(p.x);
    SerialUSB.print(", y = ");
    SerialUSB.print(p.y);
    delay(20);
    SerialUSB.println();
  }
  delay(100);
}



Here's where I am trying to define the SPI port at in the 2046XPT_touchscreen.cpp file at:

Code: [Select]

#include "XPT2046_Touchscreen.h"
#include "wiring_private.h" // pinPeripheral() function

#include <SPI.h>

SPIClass tsSPI (&sercom1, 12, 13, 11, SPI_PAD_0_SCK_1, SERCOM_RX_PAD_3);


#define Z_THRESHOLD     400
#define Z_THRESHOLD_INT 75
#define MSEC_THRESHOLD  3
#define SPI_SETTING     SPISettings(2000000, MSBFIRST, SPI_MODE0)

static XPT2046_Touchscreen *isrPinptr;
void isrPin(void);

bool XPT2046_Touchscreen::begin()
{




tsSPI.begin();
// Assign pins 11, 12, 13 to SERCOM functionality
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(12, PIO_SERCOM);
pinPeripheral(13, PIO_SERCOM);

pinMode(csPin, OUTPUT);
digitalWrite(csPin, HIGH);
if (255 != tirqPin) {
pinMode( tirqPin, INPUT );
attachInterrupt(digitalPinToInterrupt(tirqPin), isrPin, FALLING);
isrPinptr = this;
}
return true;
}


I am attaching my sketch and the library files as I am using them currently.

Could someone enlighten me as to where I am going wrong?

Thanks,
Randy

MartinL

#1
Jul 05, 2020, 05:14 pm Last Edit: Jul 05, 2020, 05:15 pm by MartinL
Hi Randy,

The code for the additional SPI looks good. I compared it against the Adafruit tutorial code: https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/creating-a-new-spi. This contains the same example code that you're using.

Swapping out SPI for your own SPI object, plus the additional pinPeripheral() functions in the library, should allow it to work with the new SPI port.

You mention you're using a Zero clone. Are digital pins D11, D12 and D13 using port pins PA16, PA19 and PA17 repectively?

revolt_randy

#2
Jul 05, 2020, 05:31 pm Last Edit: Jul 05, 2020, 05:33 pm by revolt_randy
Hi MartinL,

Thanks for your reply. Yes, the zero clone is using the correct digital pins to port pins. In fact, I have just solved my problem, and feel a bit stupid....

It was a simple typo, or a find & replace gone bad....

From XPT2046_Touchscreen.cpp -

Code: [Select]

void XPT2046_Touchscreen_Zero::update()
{
int16_t data[6];

if (!isrWake) return;
uint32_t now = millis();
if (now - msraw < MSEC_THRESHOLD) return;

tsSPI.beginTransaction(SPI_SETTING);
digitalWrite(csPin, LOW);
tsSPI.transfer(0xB1 /* Z1 */);
int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3;
int z = z1 + 4095;
int16_t z2 = SPI.transfer16(0x91 /* X */) >> 3;
z -= z2;
if (z >= Z_THRESHOLD) {
tsSPI.transfer16(0x91 /* X */);  // dummy X measure, 1st is always noisy
data[0] = tsSPI.transfer16(0xD1 /* Y */) >> 3;
data[1] = tsSPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements
data[2] = tsSPI.transfer16(0xD1 /* Y */) >> 3;
data[3] = tsSPI.transfer16(0x91 /* X */) >> 3;
}
else data[0] = data[1] = data[2] = data[3] = 0; // Compiler warns these values may be used unset on early exit.
data[4] = tsSPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down
data[5] = tsSPI.transfer16(0) >> 3;
digitalWrite(csPin, HIGH);
tsSPI.endTransaction();
//Serial.printf("z=%d  ::  z1=%d,  z2=%d  ", z, z1, z2);
if (z < 0) z = 0;
if (z < Z_THRESHOLD) { // if ( !touched ) {
// Serial.println();
zraw = 0;
if (z < Z_THRESHOLD_INT) { // if ( !touched ) {
if (255 != tirqPin) isrWake = false;
}
return;
}


After - tsSPI.transfer(0xB1 /* Z1 */);
the next two SPI calls used 'SPI', not my new 'tsSPI', so the data was going to the wrong SPI port.

I don't know how I missed that, and now feel stoopid....

Thank you very mush for your time!

Randy

Go Up