My current project requires an ST powerSTEP motor driver UNO R3 shield with the Adafruit Metro RP2040 requiring SPI on the normal D10-13 pins. I am also using the AdaFruit 2.8" TFT Touch Shield in the alternate configuration with SPI on D11-13. Getting these to work turned out a little painful, as SPI on D10-13 doesn't work out of the box. I had used the ST powerSTEP motor shield in other Arduino UNO projects, and was caught by surprise when it's D10-13 SPI didn't work with the Metro RP2040.
Required is a simple hardware hack to swap pins D10 and D13 on the UNO R3 connectors. I did this with some extra headers with D10 and D13 broken out and swapped with blue wires to the Metro RP2040 pins on the back of the board.
The Arduino board files for the Metro RP2040 required enabling SPI1 since D10-13 can not be used with SPI0 on the RP2040, and swapping the D10 and D13 pin configuration to match the hardware header hack.
in rp2040/3.6.2/variants/adafruit_metro/pins_arduino.h, set:
// SPI1
#define PIN_SPI1_MISO (12u)
#define PIN_SPI1_MOSI (11u)
#define PIN_SPI1_SCK (10u)
#define PIN_SPI1_SS (13u)
#define SPI_HOWMANY (2u)
in rp2040/3.6.2/variants/generic/common.h, change:
static const uint8_t D10 = (13u); // swapped D10 and D13 at pin headers
static const uint8_t D13 = (10u); // swapped D10 and D13 at pin headers
Using TouchPaint to verify the SPI hardware and configuration hacks, required changing the initialization to SPI1.
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI1, TFT_DC, TFT_CS)
I had rewritten TouchPaint to add calibration for the touch function, since the software defined touch values worked very poorly with my board. The touch points with a small X and Y didn't pick up, leaving a good sized unusable area in that corner, and along the all the edges. Lowering the touch pressure from 300 to 100 got the full screen area touch working, but there was a several mm mis-registration between the pen contact, and the drawn pixels. I also cleaned up static defines to use the calibration values, returned hardware values, and dynamic pallet size based on an array of pallet colors.
The debug serial prints for calibration need to be moved below the two calibration calls for debugging. i just moved them into a single ifdef.
// SPDX-FileCopyrightText: 2024 John Bass, DMS Design // SPDX-License-Identifier: MIT /*************************************************** This is my re-write of the Adafruit TouchPaint example for ILI9341 Shield with TSC2007 ----> http://www.adafruit.com/products/1651 Written by by John Bass, DBA: DMS Design. MIT license, all text above must be included in any redistribution ****************************************************/ // // Interfaces and inspiration from Adafruit examples. // Initialization changed for SPI1 on D11-13 // #include <Wire.h> #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> #include <Adafruit_TSC2007.h> // Initialize display, uses hardware SPI, plus D9 & D10 #define TFT_CS D10 #define TFT_DC D9 // Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI1, TFT_DC, TFT_CS); Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI1, TFT_DC, TFT_CS); // Unlike tft, ts silently gets initialized somewhere Adafruit_TSC2007 ts; #define MINT 100 // Min Touch Pressure struct TSCal { int Dx, Dy; // Display size int Lx, Ly; // TS coordinate for Lower limits int Ux, Uy; // TS coordinate for Upper limits } ts_cal; // Size of the color selection boxes and the paintbrush size int colors[] = {ILI9341_RED, ILI9341_YELLOW, ILI9341_GREEN, ILI9341_CYAN, ILI9341_BLUE, ILI9341_MAGENTA, ILI9341_BLACK, ILI9341_WHITE}; int oldcolor, currentcolor; #define COLORS (sizeof colors/sizeof (int)) #define BOXSIZE (ts_cal.Dx/COLORS) #define PENRADIUS 3 void calibrateTS(int sx, int sy) { uint16_t x, y, z1, z2; tft.fillCircle(sx, sy, PENRADIUS, ILI9341_RED); // set calibration point while (!(ts.read_touch(&x, &y, &z1, &z2) && (z1 > MINT))); tft.fillCircle(sx, sy, PENRADIUS, ILI9341_GREEN); // signal point selected // Calibration points must be in lower and upper corners if(sx < ts_cal.Dx/2 && sy < ts_cal.Dy/2) { // Lower Corner ts_cal.Lx = x; ts_cal.Ly = y; } else if(sx > ts_cal.Dx/2 && sy > ts_cal.Dy/2) { // Upper Corner ts_cal.Ux = x; ts_cal.Uy = y; } while (ts.read_touch(&x, &y, &z1, &z2) && (z1 > MINT)); tft.fillCircle(sx, sy, PENRADIUS, ILI9341_BLACK); // clear point delay(250); } void setup(void) { #define xDEBUG #ifdef DEBUG Serial.begin(9600); while (!Serial) delay(10); Serial.print("Pallet Colors="); Serial.print(sizeof colors/sizeof (int)); Serial.print(", Dx,Dy="); Serial.print(ts_cal.Dx); Serial.print(","); Serial.println(ts_cal.Dy); Serial.print("TS MIN="); Serial.print(ts_cal.Lx); Serial.print(","); Serial.print(ts_cal.Ly); Serial.print(", MAX="); Serial.print(ts_cal.Ux); Serial.print(","); Serial.println(ts_cal.Uy); #endif tft.begin(); tft.fillScreen(ILI9341_BLACK); // give clue display is active if (!ts.begin()) { delay(100); // give host a little time to open serial port // while (1); } tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE); tft.setTextSize(2); tft.println("\n\n\n\n\n\nTouch Red Dots\nin corners\nfor Calibration"); ts_cal.Dx = tft.width(); ts_cal.Dy = tft.height(); calibrateTS(PENRADIUS, PENRADIUS); calibrateTS(ts_cal.Dx-PENRADIUS, ts_cal.Dy-PENRADIUS); tft.fillScreen(ILI9341_BLACK); // fill the color selection boxes for(currentcolor=COLORS-1; currentcolor>=0; currentcolor--) tft.fillRect(BOXSIZE*currentcolor, 0, BOXSIZE, BOXSIZE, colors[currentcolor]); currentcolor=0; tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } void loop(){ uint16_t x, y, z1, z2; if (ts.read_touch(&x, &y, &z1, &z2) && (z1 > MINT)) { // Scale touch coordinate to screen coordinate x = map(x, ts_cal.Lx, ts_cal.Ux, PENRADIUS, ts_cal.Dx-PENRADIUS); y = map(y, ts_cal.Ly, ts_cal.Uy, PENRADIUS, ts_cal.Dy-PENRADIUS); if (y < BOXSIZE) { // point is in menu area oldcolor = currentcolor; currentcolor = x / (ts_cal.Dx/COLORS); tft.fillRect(BOXSIZE*oldcolor, 0, BOXSIZE, BOXSIZE, colors[oldcolor]); tft.drawRect(BOXSIZE*currentcolor, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else { // point is in drawing area tft.fillCircle(x, y, PENRADIUS, colors[currentcolor]); } } }