Spark Logic

8-bit|16-bit parallell ILI9341

andreas_ferm Tue Oct 06, 2015 12:16 pm

Good day everyone, I’m all new to stm32 and have previously only done smaller projects on arduiono boards, mostly using already-finished libraries.

Now I reached a point where my programmings skills lack, so instead of optimizing my code i started to look at maple mini and thought it would be excellent to also add a “nice” GUI to my project.

I ended up ordering a chinese 3.2″ tft+touch+sd card combo, but what i didn’t know or think of beforehand was to check the connectivity needed (i just read here and saw all the included libraries for the aforementioned display controller), but all of them are using SPI. So the display came in the mail and i became aware that it didn’t have any SPI interface, (at least not for the display, only for the touch and sd card)

Are there any working options that is available to use with stm32duino? What would be my best chance of getting this to work? (i was initially thinking about going for a MEGA, but choose the maple mini clone as i was impressed with the various tft demos i’ve seen )

I’ve tried looking through “all” of the internet, but have only found small pointers, and none of the really targeted for stm32duino. (i found one post where someone had posted an utft version with support for stm32, which was based on some teensy port, but it was also done for SPI only, and i couldn’t find any ILI9341 tft ‘drivers’ for parallel communication… well there was one for an ILI9481 but i’m not sure if that can be used in direct replacement.

Anyone has a similar display and has it working with a maple mini?

Thanks!
Andreas

Replies

konczakp Thu Jul 21, 2016 8:11 pm

left one near button

stevestrong Fri Jul 22, 2016 12:05 am

Finally managed to make the touch screen work, without the display.
For this, the following pins (additionally to the plate pins) should be connected correspondingly:
Vcc(3.3V),
GND,
and – important!
LCD_RD – >tied to Vcc. This line switches correctly the direction of one of the bus transceivers (HC245) on the board, on which LCD_D0 and D1 are connected. Only if this pin is high, the pins LCD_D0 and D1 (YM,XM) can be used as analog input.

stevestrong Fri Jul 22, 2016 8:26 am

I just realized that it is possible to identify the touch plate pins by following the wires from/to the bus transceivers (U2, U3), because on one side (the side to SD card slot) they have the plate pins connected.
EDIT
Hm, I think I just had luck, there is no rule to which pin are the plate pins connected, I saw several different variants on the net.
But all of them have U3 switching the LCD_D0..D7 pins upon LCD_RD signal.
The only reliable plate detection method is still the resistance measurement, although most common is to use LCD_D6, D7. My board uses LCD_D0,D1.
The other side of the plates is usually connected to LCD_WR+CD, my board use LCD_CS+RS(CD).

cologne86 Fri Jul 22, 2016 11:29 am

stevestrong wrote:cologne86 wrote:ok, sry :)
everything is working now, i just edited and saved the wrong file (same file wrong folder) :lol:

konczakp Fri Jul 22, 2016 12:07 pm

I’ve manage to get this to work!
Here is working code for both TFT Screen and touch – read comments for settings and connections.

// @konczakp
//
// TFT settings
// in Adafruit_ILI9341_8bit_STM.h
//
// #define TFT_CNTRL GPIOA
// #define TFT_DATA GPIOB
// #define TFT_RD PA4
// #define TFT_WR PA5
// #define TFT_RS PA6
// #define TFT_CS PA7
// #define TFT_RST PA8
//
// Connection
// Port data |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |
// Pin stm32 |PB7|PB6|PB5|PB4|PB3|PB2|PB1|PB0|

// Control pins |RD |WR |RS |CS |RST|
// Pin stm32 |PA4|PA5|PA6|PA7|PA8|

#include <Adafruit_GFX.h>
#include <gfxfont.h>
#include "Adafruit_ILI9341_8bit_STM.h"

#define YP PA6 // LCD_RS
#define XM PA7 // LCD_CS
#define YM PB0 // LCD_D0
#define XP PB1 // LCD_D1

#define pressureThreshhold 20
#define NUMSAMPLES 12

Adafruit_ILI9341_8bit_STM tft = Adafruit_ILI9341_8bit_STM();

void testLines(uint16_t color)
{

int x1, y1, x2, y2,
w = tft.width(),
h = tft.height();

tft.fillScreen(ILI9341_BLACK);

x1 = 0;
y1 = h - 1;
y2 = 0;

for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);

}

void setup() {
Serial.begin (115200);

tft.begin();
tft.setRotation(1);
testLines(ILI9341_CYAN);

}

void loop()
{
getPoint_new(XP, YP, XM, YM, 300);

pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);

}

void getPoint_new(byte xp, byte yp, byte xm, byte ym, int rxplate) {

int x, y, z;
int samples[NUMSAMPLES];
byte i, valid;

gpio_dev* xp_port = digitalPinToPort(xp);
gpio_dev* yp_port = digitalPinToPort(yp);
gpio_dev* xm_port = digitalPinToPort(xm);
gpio_dev* ym_port = digitalPinToPort(ym);

byte xp_pin = digitalPinToBitMask(xp);
byte yp_pin = digitalPinToBitMask(yp);
byte xm_pin = digitalPinToBitMask(xm);
byte ym_pin = digitalPinToBitMask(ym);

valid = 1;

pinMode(yp, INPUT);
pinMode(ym, INPUT);

*portOutputRegister(yp_port) &= ~yp_pin;
*portOutputRegister(ym_port) &= ~ym_pin;

pinMode(xp, OUTPUT);
pinMode(xm, OUTPUT);

*portOutputRegister(xp_port) |= xp_pin;
*portOutputRegister(xm_port) &= ~xm_pin;

delayMicroseconds(20); // Fast ARM chips need to allow voltages to settle

for (i=0; i<NUMSAMPLES; i++) {
samples[i] = analogRead(yp);
}

insert_sort(samples, NUMSAMPLES);

x = (4096-samples[NUMSAMPLES/2]);

pinMode(xp, INPUT);
pinMode(xm, INPUT);

*portOutputRegister(xp_port) &= ~xp_pin;

pinMode(yp, OUTPUT);
*portOutputRegister(yp_port) |= yp_pin;
pinMode(ym, OUTPUT);

delayMicroseconds(20); // Fast ARM chips need to allow voltages to settle

for (i=0; i<NUMSAMPLES; i++) {
samples[i] = analogRead(xm);
}

insert_sort(samples, NUMSAMPLES);

y = (4096-samples[NUMSAMPLES/2]);

// Set X+ to ground
pinMode(xp, OUTPUT);
*portOutputRegister(xp_port) &= ~xp_pin;

// Set Y- to VCC
*portOutputRegister(ym_port) |= ym_pin;

// Hi-Z X- and Y+
*portOutputRegister(yp_port) &= ~yp_pin;
pinMode(yp, INPUT);

int z1 = analogRead(xm);
int z2 = analogRead(yp);

if (rxplate != 0) {

// now read the x
float rtouch;
rtouch = z2;
rtouch /= z1;
rtouch -= 1;
rtouch *= x;
rtouch *= rxplate;
rtouch /= 4096;
z = rtouch;

} else {

z = (1023-(z2-z1));

}

if (! valid) {
z = 0;
}

if (z > pressureThreshhold && z < 100){
Serial.print("X = "); Serial.print(x);
Serial.print("\tY = "); Serial.print(y);
Serial.print("\tPressure = "); Serial.println(z);
}

}

static void insert_sort(int array[], byte size) {
byte j;
int save;

for (int i = 1; i < size; i++) {
save = array[i];
for (j = i; j >= 1 && save < array[j - 1]; j--)
array[j] = array[j - 1];
array[j] = save;
}
}

stevestrong Fri Jul 22, 2016 12:50 pm

@konczakp
Congratulations, it looks like you have the same pin mapping as my board.
But you don’t use the SD card, right? Otherwise you would need PA4..PA7 for SPI1.

konczakp Fri Jul 22, 2016 1:03 pm

I will use the SD card too but I’m leaving it for next stage because I’ve never used more than one “module” over one SPI. I will use the SPI for something else and when everything will be working I will try to add sd card.
About this pin mapping – I think it is the same for every shield from arduino. If some one bought tft 2,4 shield for arduino then It should work. I don’t know about larger screens but it is easy to check. Instead of measuring pin impedance You can compare to this shield http://supertronik.pl/img/wyswietlacz_mega2560_3.jpg and change as it is on the other shield. Everything I did was based on Arduino code.

Btw, any one know how to assign rect aera for the touch screen to check if the btn on screen was clicked?

EDIT: an another thing … is there an option to turn off the screen and switch it on if the screen was touched ?

stevestrong Fri Jul 22, 2016 1:15 pm

konczakp wrote:About this pin mapping – I think it is the same for every shield from arduino.

stevestrong Fri Jul 22, 2016 1:30 pm

konczakp wrote: is there an option to turn off the screen and switch it on if the screen was touched ?

konczakp Fri Jul 22, 2016 1:35 pm

I meant that LCD_RS and LCD_CS is always analog and definition should be like below

YP is LCD_RS
XM is LCD_CS
YM is LCD_D0
XP is LCD_D1

cologne86 Fri Jul 22, 2016 3:45 pm

i measured my lcd and its the same ;) i also need to do some stuff on touchscreen library :) but there is some output related to position and pressure related to pressure, but the 2 samples arent precise enough (thats why pressure is often saved as 0) , so i need to change that…

i changed to pin A0-A3 and A8 for the controls, all you need to change is in line 20 of Adafruit_ILI9341_8bit_STM.cpp
TFT_CNTRL->regs->CRL = (TFT_CNTRL->regs->CRL & 0x0000FFFF) | 0x33330000;

stevestrong Fri Jul 22, 2016 5:24 pm

cologne86 wrote:is it normal behaviour for x and y values to depend on each other?

cologne86 Fri Jul 22, 2016 6:07 pm

stevestrong wrote:
No, it is not normal. I also got this behavior before I figured out the LCD_RD pin dependency.

konczakp Fri Jul 22, 2016 6:16 pm

thanks cologne86! I’ve used Your config and now I have extra SPI free :)

cologne86 Fri Jul 22, 2016 7:15 pm

you’re welcome :)
here is a simple sketch for using display and touch, you have to have working libraries somehow and change the pins if yours are different, the rest should be working
(drawing with red pen)
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// This demo code returns raw readings, public domain

#include <Adafruit_GFX.h>
#include <gfxfont.h>
#include <TouchScreen_STM.h>
#include "Adafruit_ILI9341_8bit_STM.h"
// These are the pins for the shield!
#define YP PA2 // must be an analog pin
#define XM PA3 // must be an analog pin
#define YM PB8 // can be a digital pin
#define XP PB9 // can be a digital pin
#define RD PA0

#define XMIN 500
#define XMINBLACK 320
#define XMAX 3740
#define YMIN 420
#define YMAX 3640

#define MINPRESSURE 20
#define MAXPRESSURE 1000

// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
Adafruit_ILI9341_8bit_STM tft = Adafruit_ILI9341_8bit_STM();
void setup(void) {
//Serial.begin(9600);
delay(5);
tft.begin();

//digitalWrite(RD, LOW);
tft.fillScreen(ILI9341_BLACK);
tft.setRotation(1);
delay(1000);
}

void loop(void) {

pinMode(RD,OUTPUT);
digitalWrite(RD, HIGH);
TSPoint p = ts.getPoint();
//set controlpins to output again
TFT_CNTRL->regs->CRL = (TFT_CNTRL->regs->CRL & 0xFFFF0000) | 0x00003333;

// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
int16_t x=calculateX(p.x);
int16_t y=calculateY(p.y);
//Serial.print("X = "); Serial.print(x);
//Serial.print("\tY = "); Serial.print(y);
//Serial.print("\tPressure = "); Serial.println(p.z);
tft.fillCircle(x, y, 3, ILI9341_RED);
}
}
uint16_t calculateX(uint16_t x)
{
return 320-(320*(x-XMIN))/(XMAX-XMIN);
}
uint16_t calculateY(uint16_t y)
{
return (240*(y-YMIN))/(YMAX-YMIN);
}

konczakp Fri Jul 22, 2016 7:45 pm

Can You reveal how do You calculate those pins ?

TFT_CNTRL->regs->CRL = (TFT_CNTRL->regs->CRL & 0xFFFF0000) | 0x00003333;

cologne86 Fri Jul 22, 2016 7:57 pm

konczakp wrote:Can You reveal how do You calculate those pins ?

TFT_CNTRL->regs->CRL = (TFT_CNTRL->regs->CRL & 0xFFFF0000) | 0x00003333;

konczakp Fri Jul 22, 2016 8:38 pm

Thanks!

Because both SPI are free does anyone have a working sd card sketch ?

konczakp Fri Jul 22, 2016 9:37 pm

do You know how to change this to run on SPI2 ?

Sign in to reply