8 Bit TFT Library Issue
-
- Posts: 505
- Joined: Fri Dec 27, 2019 4:53 pm
- Location: Munich, Germany
- Contact:
Re: 8 Bit TFT Library Issue
I am not sure that the TFT library is wrong, I rather suspect the core, something at the initialization it may go wrong if you enable USB serial but you do not use it.
But I cannot help you there due to not available knowledge, sorry.
But I cannot help you there due to not available knowledge, sorry.
Re: 8 Bit TFT Library Issue
I did not check all the code anyway did you enabled all the required GPIO clock ?
-
- Posts: 12
- Joined: Thu Apr 30, 2020 8:35 pm
Re: 8 Bit TFT Library Issue
Ahh! That makes much more sense now. I didn't enable the GPIOA / GPIOB clocks in the APB2ENR register anywhere in my code, causing the display not to init properly. When Serial is enabled, it must init APB2 (also used by USART1) somewhere else. Thanks for the help guys! I modified my the reset function to init APB2 for GPIOA and GPIOB according to the following table from the datasheet and it now works as intended:fpiSTM wrote: Mon Aug 24, 2020 8:51 am I did not check all the code anyway did you enabled all the required GPIO clock ?

Modified reset:
Code: Select all
void Adafruit_TFTLCD_8bit_STM32::reset(void)
{
RCC->APB2ENR |= 0b1100; //set bits 3 and 4 for GPIOA and GPIOB
pinMode(TFT_RD, OUTPUT);
pinMode(TFT_WR, OUTPUT);
pinMode(TFT_RS, OUTPUT);
pinMode(TFT_CS, OUTPUT);
CS_IDLE; // Set all control bits to HIGH (idle)
CD_DATA; // Signals are ACTIVE LOW
WR_IDLE;
RD_IDLE;
//set up 8 bit parallel port to write mode.
setWriteDir();
// toggle RST low to reset
if (TFT_RST > 0) {
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, HIGH);
delay(100);
digitalWrite(TFT_RST, LOW);
delay(100);
digitalWrite(TFT_RST, HIGH);
delay(100);
}
}
Re: 8 Bit TFT Library Issue
Well pinMode set the clock of the GPIO pin port.
As it calls this function to set the GPIO port clock:
https://github.com/stm32duino/Arduino_C ... c#L67-L152
As it calls this function to set the GPIO port clock:
https://github.com/stm32duino/Arduino_C ... c#L67-L152
-
- Posts: 12
- Joined: Thu Apr 30, 2020 8:35 pm
Re: 8 Bit TFT Library Issue
Thanks for the help on this guys!
Here's the final version of my ILI9486 library for STM32duino.
https://github.com/mkengineering/STM32_ILI9486_8_bit
I also ported over some popular examples for the Adafruit TFTs.
Here's the final version of my ILI9486 library for STM32duino.
https://github.com/mkengineering/STM32_ILI9486_8_bit
I also ported over some popular examples for the Adafruit TFTs.
Re: 8 Bit TFT Library Issue
I like your efficient programming style. Efficient usage of resources, avoidance of the bloatware, and proper level of documentation and naming conventions are hall marks of long term experience. Well done 

-
- Posts: 12
- Joined: Thu Apr 30, 2020 8:35 pm
Re: 8 Bit TFT Library Issue
Hello Everyone,
Recently I started messing with a Robotdyn STM32F303 board for a project which I intended to use with my display library. Though, I seem to be having some issues with the macro definitions again
. The STM32F303 seems to be quite different with regard to gpio access. As a results, I had to change the setCntrlDir, setReadDir, setWriteDir and write8 definitions.
Additionally, for this project, I intended to use the upper 8 pins (PA8-PA15) for the data lines of the display in order to preserve the analog inputs on PA0-PA7 for other uses. This conflicts with the swd pins (PA13, PA14) of the st link for programming. Based on the reference manual for the STM32F303, I'm able to assign an alternate function to these pins after programming by using the AFR register.

I decided to just assign PA13/PA14 to AF2 and ended up with the following code.
Header:
C++ file (unmodified from the STM32F103 version):
While this compiles fine, I end up with the dreaded white screen on the display. I have used the onboard LED to determine that the sketch completes "tft.begin()" and the fillscreen, but the display must not be getting properly initialized.
Is it possible to repurpose the SWD pins using this method? Am I missing something in my gpio setup?
Recently I started messing with a Robotdyn STM32F303 board for a project which I intended to use with my display library. Though, I seem to be having some issues with the macro definitions again

Additionally, for this project, I intended to use the upper 8 pins (PA8-PA15) for the data lines of the display in order to preserve the analog inputs on PA0-PA7 for other uses. This conflicts with the swd pins (PA13, PA14) of the st link for programming. Based on the reference manual for the STM32F303, I'm able to assign an alternate function to these pins after programming by using the AFR register.

I decided to just assign PA13/PA14 to AF2 and ended up with the following code.
Header:
Code: Select all
// Graphics library by ladyada/adafruit with init code from Rossum
// MIT license
// ported to STM32duino ST Core by MKE
//modified for STM32F303
/*****************************************************************************/
// Wiring Settings
/*****************************************************************************/
// By default, the library is designed to use:
// PA0:PA7 -> DB0:DB7
// PB5 -> RESET
// PB6 -> CS
// PB7 -> RS/DC
// PB8 -> WR
// PB9 -> RD
// To deviate from these settings, you must modify:
// 1. "Data and Control Port / Pin Definitions"
// a. Data and Control Ports
// b. Bit Masks for Control Pins
// 2. "Macro Definitions"
// a. setCntrlDir()
// b. setWriteDir()
// c. setReadDir()
// d. write8()
// Note: the control pins can be any 5 pins from a single register (Example: PB5, PB6, PB7, PB8, PB9, etc...)
// Note: the data pins must be 8 CONSECUTIVE pins from a single register (Example: PA0:PA7, PA8:PA15, etc...)
#ifndef _STM32_ILI9486_8_BIT_H_
#define _STM32_ILI9486_8_BIT_H_
#include "Arduino.h"
#include <Adafruit_GFX.h>
/*****************************************************************************/
// Data and Control Port / Pin Definitions
/*****************************************************************************/
// Example: PB5-> PORT = GPIOB, MASK = GPIO_PIN_5
// Data and Control Ports
#define TFT_DATA_PORT GPIOA
#define TFT_CNTRL_PORT GPIOB
// Masks for Control Pins
#define TFT_RD_MASK GPIO_PIN_15
#define TFT_WR_MASK GPIO_PIN_14
#define TFT_RS_MASK GPIO_PIN_13
#define TFT_CS_MASK GPIO_PIN_12
#define TFT_RST_MASK GPIO_PIN_11
/*****************************************************************************/
// TFT Register Names
/*****************************************************************************/
#define ILI9486_SOFTRESET 0x01
#define ILI9486_SLEEPIN 0x10
#define ILI9486_SLEEPOUT 0x11
#define ILI9486_NORMALDISP 0x13
#define ILI9486_INVERTOFF 0x20
#define ILI9486_INVERTON 0x21
#define ILI9486_GAMMASET 0x26
#define ILI9486_DISPLAYOFF 0x28
#define ILI9486_DISPLAYON 0x29
#define ILI9486_COLADDRSET 0x2A
#define ILI9486_PAGEADDRSET 0x2B
#define ILI9486_MEMORYWRITE 0x2C
#define ILI9486_PIXELFORMAT 0x3A
#define ILI9486_FRAMECONTROL 0xB1
#define ILI9486_DISPLAYFUNC 0xB6
#define ILI9486_ENTRYMODE 0xB7
#define ILI9486_POWERCONTROL1 0xC0
#define ILI9486_POWERCONTROL2 0xC1
#define ILI9486_VCOMCONTROL1 0xC5
#define ILI9486_VCOMCONTROL2 0xC7
#define ILI9486_MEMCONTROL 0x36
#define ILI9486_MADCTL 0x36
#define ILI9486_MADCTL_MY 0x80
#define ILI9486_MADCTL_MX 0x40
#define ILI9486_MADCTL_MV 0x20
#define ILI9486_MADCTL_ML 0x10
#define ILI9486_MADCTL_RGB 0x00
#define ILI9486_MADCTL_BGR 0x08
#define ILI9486_MADCTL_MH 0x04
/*****************************************************************************/
// TFT Size
/*****************************************************************************/
#define TFTWIDTH 320
#define TFTHEIGHT 480
#define TFTLCD_DELAY 0xFF
#define TFTLCD_DELAY8 0xFF
#define Color565 color565
/*****************************************************************************/
// Color Definitions
/*****************************************************************************/
#define BLACK 0x0000
#define NAVY 0x000F
#define DARKGREEN 0x03E0
#define DARKCYAN 0x03EF
#define MAROON 0x7800
#define PURPLE 0x780F
#define OLIVE 0x7BE0
#define LIGHTGREY 0xC618
#define GRAY 0x5AEB
#define DARKGREY 0x7BEF
#define BLUE 0x001F
#define GREEN 0x07E0
#define CYAN 0x07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define ORANGE 0xFD20
#define GREENYELLOW 0xAFE5
#define PINK 0xF81F
/*****************************************************************************/
// Macro Definitions
/*****************************************************************************/
#define RD_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_RD_MASK; }
#define RD_IDLE { TFT_CNTRL_PORT->BSRR = TFT_RD_MASK; }
#define WR_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_WR_MASK; }
#define WR_IDLE { TFT_CNTRL_PORT->BSRR = TFT_WR_MASK; }
#define WR_STROBE { WR_ACTIVE; WR_IDLE; }
#define CD_COMMAND { TFT_CNTRL_PORT->BRR = TFT_RS_MASK; }
#define CD_DATA { TFT_CNTRL_PORT->BSRR = TFT_RS_MASK; }
#define CS_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_CS_MASK; }
#define CS_IDLE { TFT_CNTRL_PORT->BSRR = TFT_CS_MASK; }
#define CS_ACTIVE_CD_COMMAND { TFT_CNTRL_PORT->BRR = (TFT_CS_MASK|TFT_RS_MASK); }
#define RST_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_RST_MASK; }
#define RST_IDLE { TFT_CNTRL_PORT->BSRR = TFT_RST_MASK; }
#define RST_TOGGLE { RST_IDLE; RST_ACTIVE; RST_IDLE; }
extern uint8_t read8_(void);
#define read8(x) ( x = read8_() )
// set control pins (PB11-PB15) to output mode and enable ahb clock for gpiob
#define setCntrlDir() { RCC->AHBENR |= (0b0100 << 16); TFT_CNTRL_PORT->MODER = 0x55400000; TFT_CNTRL_PORT->OSPEEDR = 0xFFC00000; TFT_CNTRL_PORT->OTYPER = 0x00000000; }
// set the data pins (PA8-PA15) to input mode and enable ahb clock for gpioa
#define setReadDir() { RCC->AHBENR |= (0b0010 << 16); TFT_DATA_PORT->AFR[1] = 0x2200000; TFT_DATA_PORT->PUPDR = 0x00000000; TFT_DATA_PORT->MODER = 0x00000000; }
// set the data pins (PA8-PA15) to output mode and enable ahb clock for gpioa
#define setWriteDir() { RCC->AHBENR |= (0b0010 << 16); TFT_DATA_PORT->AFR[1] = 0x2200000; TFT_DATA_PORT->OTYPER = 0x00000000; TFT_DATA_PORT->PUPDR = 0x00000000; TFT_DATA_PORT->OSPEEDR = 0xFFFF0000; TFT_DATA_PORT->MODER = 0x55550000; }
// set pins to output the 8 bit value
#define write8(c) { TFT_DATA_PORT->BSRR = (uint32_t)(0xFF000000 + (((c)&0xFF) << 8)); WR_STROBE; }
/*****************************************************************************/
#define swap(a, b) { int16_t t = a; a = b; b = t; }
/*****************************************************************************/
class STM32_ILI9486_8_bit : public Adafruit_GFX {
public:
STM32_ILI9486_8_bit(void);
void begin(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void drawFastHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color);
void drawFastVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t c);
void fillScreen(uint16_t color);
void reset(void);
void setRegisters8(uint8_t *ptr, uint8_t n);
void setRegisters16(uint16_t *ptr, uint8_t n);
void setRotation(uint8_t x);
// These methods are public in order for BMP examples to work:
void setAddrWindow(int16_t x1, int16_t y1, int16_t x2, int16_t y2);
void invertDisplay(boolean i),
pushColors(uint16_t *data, int16_t len, boolean first),
drawBitmap(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t * bitmap);
uint16_t readPixel(int16_t x, int16_t y), readID(void);
/*****************************************************************************/
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
// color coding on bits:
// high byte sill be sent first
// bit nr: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
// color/bit: R5 R4 R3 R2 R1 | G5 G4 G3 G2 G1 G0 | B5 B4 B3 B2 B1
// R0=R5 B0=B5
/*****************************************************************************/
uint16_t inline color565(uint8_t r, uint8_t g, uint8_t b) { return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); }
private:
void init(), flood(uint16_t color, uint32_t len);
uint8_t driver;
};
extern uint16_t readReg(uint8_t r);
extern uint32_t readReg32(uint8_t r);
extern void writeCommand(uint16_t c);
extern void writeRegister8(uint16_t a, uint8_t d);
extern void writeRegister16(uint16_t a, uint16_t d);
extern void writeRegister24(uint16_t a, uint32_t d);
extern void writeRegister32(uint16_t a, uint32_t d);
extern void writeRegisterPair(uint16_t aH, uint16_t aL, uint16_t d);
extern STM32_ILI9486_8_bit tft;
#endif
Code: Select all
// Graphics library by ladyada/adafruit with init code from Rossum
// MIT license
// ported to STM32duino ST Core by MKE
#include "STM32_ILI9486_8_bit.h"
static const uint8_t ILI9486_regValues_ada[] PROGMEM = {
//from mcufriend lib
0xC0, 2, 0x0d, 0x0d, //Power Control 1 [0E 0E]
0xC1, 2, 0x43, 0x00, //Power Control 2 [43 00]
0xC2, 1, 0x00, //Power Control 3 [33]
0xC5, 4, 0x00, 0x48, 0x00, 0x48, //VCOM Control 1 [00 40 00 40]
0xB4, 1, 0x00, //Inversion Control [00]
0xB6, 3, 0x02, 0x02, 0x3B, // Display Function Control [02 02 3B]
0xE0, 15, 0x0F, 0x21, 0x1C, 0x0B, 0x0E, 0x08, 0x49, 0x98, 0x38, 0x09, 0x11, 0x03, 0x14, 0x10, 0x00, //Positive Gamma Correction
0xE1, 15, 0x0F, 0x2F, 0x2B, 0x0C, 0x0E, 0x06, 0x47, 0x76, 0x37, 0x07, 0x11, 0x04, 0x23, 0x1E, 0x00, //Negative Gamma Correction
};
/*****************************************************************************/
static void WriteCmdParamN(uint16_t cmd, int8_t N, const uint8_t * block)
{
writeCommand(cmd);
while (N-- > 0) {
uint8_t u8 = *block++;
CD_DATA;
write8(u8);
}
CS_IDLE;
}
/*****************************************************************************/
static void init_table(const uint8_t *table, int16_t size)
{
while (size > 0) {
uint8_t cmd = *table++;
uint8_t len = *table++;
if (cmd == TFTLCD_DELAY8) {
delay(len);
len = 0;
} else {
WriteCmdParamN(cmd, len, table);
table += len;
}
size -= len + 2;
}
}
const uint8_t reset_off[] PROGMEM = {
0x01, 0, //Soft Reset
TFTLCD_DELAY8, 150, // .kbv will power up with ONLY reset, sleep out, display on
0x28, 0, //Display Off
0x3A, 1, 0x55, //Pixel read=565, write=565.
};
const uint8_t wake_on[] PROGMEM = {
0x11, 0, //Sleep Out
TFTLCD_DELAY8, 150,
0x29, 0, //Display On
// //additional settings
ILI9486_INVERTOFF, 0, // invert off
0x36, 1, 0x48, //Memory Access
0xB0, 1, 0x40, //RGB Signal [40] RCM=2
};
/*****************************************************************************/
// Constructor
/*****************************************************************************/
STM32_ILI9486_8_bit :: STM32_ILI9486_8_bit(void)
: Adafruit_GFX(TFTWIDTH, TFTHEIGHT)
{
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::begin(void)
{
reset();
init_table(reset_off, sizeof(reset_off));
init_table(ILI9486_regValues_ada, sizeof(ILI9486_regValues_ada));
init_table(wake_on, sizeof(wake_on));
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::reset(void)
{
setCntrlDir();
CS_IDLE; // Set all control bits to HIGH (idle)
CD_DATA; // Signals are ACTIVE LOW
WR_IDLE;
RD_IDLE;
setWriteDir();
RST_TOGGLE;
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::setAddrWindow(int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
writeRegister32(ILI9486_COLADDRSET, ((uint32_t)(x1<<16) | x2)); // HX8357D uses same registers!
writeRegister32(ILI9486_PAGEADDRSET, ((uint32_t)(y1<<16) | y2)); // HX8357D uses same registers!
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::flood(uint16_t color, uint32_t len)
{
uint16_t blocks;
uint8_t i, hi = color >> 8, lo = color;
CS_ACTIVE_CD_COMMAND;
writeCommand(ILI9486_MEMORYWRITE);
CD_DATA;
write8(hi);
write8(lo);
len--;
blocks = (uint16_t)(len / 64); // 64 pixels/block
if(hi == lo) {
// High and low bytes are identical. Leave prior data
// on the port(s) and just toggle the write strobe.
while(blocks--) {
i = 16; // 64 pixels/block / 4 pixels/pass
do {
WR_STROBE; WR_STROBE; WR_STROBE; WR_STROBE; // 2 bytes/pixel
WR_STROBE; WR_STROBE; WR_STROBE; WR_STROBE; // x 4 pixels
} while(--i);
}
// Fill any remaining pixels (1 to 64)
i = len & 63;
while (i--) {
WR_STROBE; WR_STROBE;
}
} else {
while(blocks--) {
i = 16; // 64 pixels/block / 4 pixels/pass
do {
write8(hi); write8(lo); write8(hi); write8(lo);
write8(hi); write8(lo); write8(hi); write8(lo);
} while(--i);
}
i = len & 63;
while (i--) { // write here the remaining data
write8(hi); write8(lo);
}
}
CS_IDLE;
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::drawFastHLine(int16_t x, int16_t y, int16_t length, uint16_t color)
{
int16_t x2;
// Initial off-screen clipping
if((length <= 0 ) ||
(y < 0 ) || ( y >= _height) ||
(x >= _width) || ((x2 = (x+length-1)) < 0 )) return;
if(x < 0) { // Clip left
length += x;
x = 0;
}
if(x2 >= _width) { // Clip right
x2 = _width - 1;
length = x2 - x + 1;
}
setAddrWindow(x, y, x2, y);
flood(color, length);
writeRegisterPair(0x04, 0x05, TFTWIDTH - 1);
writeRegisterPair(0x08, 0x09, TFTHEIGHT - 1);
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::drawFastVLine(int16_t x, int16_t y, int16_t length, uint16_t color)
{
int16_t y2;
// Initial off-screen clipping
if((length <= 0 ) ||
(x < 0 ) || ( x >= _width) ||
(y >= _height) || ((y2 = (y+length-1)) < 0 )) return;
if(y < 0) { // Clip top
length += y;
y = 0;
}
if(y2 >= _height) { // Clip bottom
y2 = _height - 1;
length = y2 - y + 1;
}
setAddrWindow(x, y, x, y2);
flood(color, length);
writeRegisterPair(0x04, 0x05, TFTWIDTH - 1);
writeRegisterPair(0x08, 0x09, TFTHEIGHT - 1);
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::fillRect(int16_t x1, int16_t y1, int16_t w, int16_t h, uint16_t fillcolor)
{
int16_t x2, y2;
// Initial off-screen clipping
if( (w <= 0 ) || (h <= 0 ) ||
(x1 >= _width) || (y1 >= _height) ||
((x2 = x1+w-1) < 0 ) || ((y2 = y1+h-1) < 0 )) return;
if(x1 < 0) { // Clip left
w += x1;
x1 = 0;
}
if(y1 < 0) { // Clip top
h += y1;
y1 = 0;
}
if(x2 >= _width) { // Clip right
x2 = _width - 1;
w = x2 - x1 + 1;
}
if(y2 >= _height) { // Clip bottom
y2 = _height - 1;
h = y2 - y1 + 1;
}
setAddrWindow(x1, y1, x2, y2);
flood(fillcolor, (uint32_t)w * (uint32_t)h);
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::fillScreen(uint16_t color)
{
setAddrWindow(0, 0, _width - 1, _height - 1);
flood(color, (long)TFTWIDTH * (long)TFTHEIGHT);
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::drawPixel(int16_t x, int16_t y, uint16_t color)
{
// Clip
if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;
setAddrWindow(x, y, x+1, y+1);
writeRegister16(0x2C, color);
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::drawBitmap(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t * bitmap)
{
if ( x>=0 && (x+w)<_width && y>=0 && (y+h)<=_height ) {
// all pixel visible, do it in the fast way
setAddrWindow(x,y,x+w-1,y+h-1);
pushColors((uint16_t*)bitmap, w*h, true);
} else {
// some pixels outside visible area, do it in the classical way to disable off-screen points
int16_t i, j;
uint16_t * colorP = (uint16_t*)bitmap;
for(j=0; j<h; j++) {
for(i=0; i<w; i++ ) {
drawPixel(x+i, y+j, *colorP++);
}
}
}
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::pushColors(uint16_t *data, int16_t len, boolean first)
{
uint16_t color;
uint8_t hi, lo;
CS_ACTIVE;
if(first == true) { // Issue GRAM write command only on first call
CD_COMMAND;
write8(0x2C);
}
CD_DATA;
while(len--) {
color = *data++;
hi = color >> 8; // Don't simplify or merge these
lo = color; // lines, there's macro shenanigans
write8(hi); // going on.
write8(lo);
}
CS_IDLE;
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::invertDisplay(boolean i)
{
writeCommand( i ? ILI9486_INVERTON : ILI9486_INVERTOFF);
CS_IDLE;
}
/*****************************************************************************/
void STM32_ILI9486_8_bit::setRotation(uint8_t x)
{
// Call parent rotation func first -- sets up rotation flags, etc.
Adafruit_GFX::setRotation(x);
// Then perform hardware-specific rotation operations...
uint16_t t;
switch (rotation) {
case 1:
t = ILI9486_MADCTL_MX | ILI9486_MADCTL_MY | ILI9486_MADCTL_MV | ILI9486_MADCTL_BGR;
break;
case 2:
t = ILI9486_MADCTL_MX | ILI9486_MADCTL_BGR;
break;
case 3:
t = ILI9486_MADCTL_MV | ILI9486_MADCTL_BGR;
break;
case 0:
default:
t = ILI9486_MADCTL_MY | ILI9486_MADCTL_BGR;
break;
}
writeRegister8(ILI9486_MADCTL, t ); // MADCTL
// For 9341, init default full-screen address window:
//setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here
}
/*****************************************************************************/
uint8_t read8_(void)
{
RD_ACTIVE;
delayMicroseconds(10);
uint8_t temp = (TFT_DATA_PORT->IDR & 0x00FF);
delayMicroseconds(10);
RD_IDLE;
delayMicroseconds(10);
return temp;
}
/*****************************************************************************/
inline void writeCommand(uint16_t c)
{
CS_ACTIVE_CD_COMMAND;
write8(c>>8);
write8(c);
}
/*****************************************************************************/
uint16_t STM32_ILI9486_8_bit::readPixel(int16_t x, int16_t y)
{
if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return 0;
return 0;
}
/*****************************************************************************/
uint16_t STM32_ILI9486_8_bit::readID(void)
{
uint16_t id = readReg32(0xD3);
return id;
}
/*****************************************************************************/
uint32_t readReg32(uint8_t r)
{
uint32_t id;
uint8_t x;
// try reading register #4
writeCommand(r);
setReadDir(); // Set up LCD data port(s) for READ operations
CD_DATA;
delayMicroseconds(50);
read8(x);
id = x; // Do not merge or otherwise simplify
id <<= 8; // these lines. It's an unfortunate
read8(x);
id |= x; // shenanigans that are going on.
id <<= 8; // these lines. It's an unfortunate
read8(x);
id |= x; // shenanigans that are going on.
id <<= 8; // these lines. It's an unfortunate
read8(x);
id |= x; // shenanigans that are going on.
CS_IDLE;
setWriteDir(); // Restore LCD data port(s) to WRITE configuration
return id;
}
/*****************************************************************************/
uint16_t readReg(uint8_t r)
{
uint16_t id;
uint8_t x;
writeCommand(r);
setReadDir(); // Set up LCD data port(s) for READ operations
CD_DATA;
delayMicroseconds(10);
read8(x);
id = x; // Do not merge or otherwise simplify
id <<= 8; // these lines. It's an unfortunate
read8(x);
id |= x; // shenanigans that are going on.
CS_IDLE;
setWriteDir(); // Restore LCD data port(s) to WRITE configuration
return id;
}
/*****************************************************************************/
void writeRegister8(uint16_t a, uint8_t d)
{
writeCommand(a);
CD_DATA;
write8(d);
CS_IDLE;
}
/*****************************************************************************/
void writeRegister16(uint16_t a, uint16_t d)
{
writeCommand(a);
CD_DATA;
write8(d>>8);
write8(d);
CS_IDLE;
}
/*****************************************************************************/
void writeRegisterPair(uint16_t aH, uint16_t aL, uint16_t d)
{
writeRegister8(aH, d>>8);
writeRegister8(aL, d);
}
/*****************************************************************************/
void writeRegister24(uint16_t r, uint32_t d)
{
writeCommand(r); // includes CS_ACTIVE
CD_DATA;
write8(d >> 16);
write8(d >> 8);
write8(d);
CS_IDLE;
}
/*****************************************************************************/
void writeRegister32(uint16_t r, uint32_t d)
{
writeCommand(r);
CD_DATA;
write8(d >> 24);
write8(d >> 16);
write8(d >> 8);
write8(d);
CS_IDLE;
}
//STM32_ILI9486_8_bit tft;
Is it possible to repurpose the SWD pins using this method? Am I missing something in my gpio setup?
-
- Posts: 12
- Joined: Thu Apr 30, 2020 8:35 pm
Re: 8 Bit TFT Library Issue
I think I need more sleep...
I just realized I had been updating the header file without it saving to my arduino folder.
It works now! I removed the AFR configuration as well as some of the other setup as it seems to work fine without it.
Here is my revised header file:

Should I worry about adding the alternate function definitions back in? I assume as I'm not using the serial wire debugging interface it doesn't affect the pins after it starts running my code.
I just realized I had been updating the header file without it saving to my arduino folder.
It works now! I removed the AFR configuration as well as some of the other setup as it seems to work fine without it.
Here is my revised header file:
Code: Select all
// Graphics library by ladyada/adafruit with init code from Rossum
// MIT license
// ported to STM32duino ST Core by MKE
//modified for STM32F303
/*****************************************************************************/
// Wiring Settings
/*****************************************************************************/
// By default, the library is designed to use:
// PA0:PA7 -> DB0:DB7
// PB5 -> RESET
// PB6 -> CS
// PB7 -> RS/DC
// PB8 -> WR
// PB9 -> RD
// To deviate from these settings, you must modify:
// 1. "Data and Control Port / Pin Definitions"
// a. Data and Control Ports
// b. Bit Masks for Control Pins
// 2. "Macro Definitions"
// a. setCntrlDir()
// b. setWriteDir()
// c. setReadDir()
// d. write8()
// Note: the control pins can be any 5 pins from a single register (Example: PB5, PB6, PB7, PB8, PB9, etc...)
// Note: the data pins must be 8 CONSECUTIVE pins from a single register (Example: PA0:PA7, PA8:PA15, etc...)
#ifndef _STM32_ILI9486_8_BIT_H_
#define _STM32_ILI9486_8_BIT_H_
#include "Arduino.h"
#include <Adafruit_GFX.h>
/*****************************************************************************/
// Data and Control Port / Pin Definitions
/*****************************************************************************/
// Example: PB5-> PORT = GPIOB, MASK = GPIO_PIN_5
// Data and Control Ports
#define TFT_DATA_PORT GPIOA
#define TFT_CNTRL_PORT GPIOB
// Masks for Control Pins
#define TFT_RD_MASK GPIO_PIN_15
#define TFT_WR_MASK GPIO_PIN_14
#define TFT_RS_MASK GPIO_PIN_13
#define TFT_CS_MASK GPIO_PIN_12
#define TFT_RST_MASK GPIO_PIN_11
/*****************************************************************************/
// TFT Register Names
/*****************************************************************************/
#define ILI9486_SOFTRESET 0x01
#define ILI9486_SLEEPIN 0x10
#define ILI9486_SLEEPOUT 0x11
#define ILI9486_NORMALDISP 0x13
#define ILI9486_INVERTOFF 0x20
#define ILI9486_INVERTON 0x21
#define ILI9486_GAMMASET 0x26
#define ILI9486_DISPLAYOFF 0x28
#define ILI9486_DISPLAYON 0x29
#define ILI9486_COLADDRSET 0x2A
#define ILI9486_PAGEADDRSET 0x2B
#define ILI9486_MEMORYWRITE 0x2C
#define ILI9486_PIXELFORMAT 0x3A
#define ILI9486_FRAMECONTROL 0xB1
#define ILI9486_DISPLAYFUNC 0xB6
#define ILI9486_ENTRYMODE 0xB7
#define ILI9486_POWERCONTROL1 0xC0
#define ILI9486_POWERCONTROL2 0xC1
#define ILI9486_VCOMCONTROL1 0xC5
#define ILI9486_VCOMCONTROL2 0xC7
#define ILI9486_MEMCONTROL 0x36
#define ILI9486_MADCTL 0x36
#define ILI9486_MADCTL_MY 0x80
#define ILI9486_MADCTL_MX 0x40
#define ILI9486_MADCTL_MV 0x20
#define ILI9486_MADCTL_ML 0x10
#define ILI9486_MADCTL_RGB 0x00
#define ILI9486_MADCTL_BGR 0x08
#define ILI9486_MADCTL_MH 0x04
/*****************************************************************************/
// TFT Size
/*****************************************************************************/
#define TFTWIDTH 320
#define TFTHEIGHT 480
#define TFTLCD_DELAY 0xFF
#define TFTLCD_DELAY8 0xFF
#define Color565 color565
/*****************************************************************************/
// Color Definitions
/*****************************************************************************/
#define BLACK 0x0000
#define NAVY 0x000F
#define DARKGREEN 0x03E0
#define DARKCYAN 0x03EF
#define MAROON 0x7800
#define PURPLE 0x780F
#define OLIVE 0x7BE0
#define LIGHTGREY 0xC618
#define GRAY 0x5AEB
#define DARKGREY 0x7BEF
#define BLUE 0x001F
#define GREEN 0x07E0
#define CYAN 0x07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define ORANGE 0xFD20
#define GREENYELLOW 0xAFE5
#define PINK 0xF81F
/*****************************************************************************/
// Macro Definitions
/*****************************************************************************/
#define RD_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_RD_MASK; }
#define RD_IDLE { TFT_CNTRL_PORT->BSRR = TFT_RD_MASK; }
#define WR_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_WR_MASK; }
#define WR_IDLE { TFT_CNTRL_PORT->BSRR = TFT_WR_MASK; }
#define WR_STROBE { WR_ACTIVE; WR_IDLE; }
#define CD_COMMAND { TFT_CNTRL_PORT->BRR = TFT_RS_MASK; }
#define CD_DATA { TFT_CNTRL_PORT->BSRR = TFT_RS_MASK; }
#define CS_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_CS_MASK; }
#define CS_IDLE { TFT_CNTRL_PORT->BSRR = TFT_CS_MASK; }
#define CS_ACTIVE_CD_COMMAND { TFT_CNTRL_PORT->BRR = (TFT_CS_MASK|TFT_RS_MASK); }
#define RST_ACTIVE { TFT_CNTRL_PORT->BRR = TFT_RST_MASK; }
#define RST_IDLE { TFT_CNTRL_PORT->BSRR = TFT_RST_MASK; }
#define RST_TOGGLE { RST_IDLE; RST_ACTIVE; RST_IDLE; }
extern uint8_t read8_(void);
#define read8(x) ( x = read8_() )
// set control pins (PB11-PB15) to output mode and enable ahb clock for gpiob
#define setCntrlDir() { RCC->AHBENR |= (0b0100 << 16); TFT_CNTRL_PORT->OSPEEDR = 0xFFC00000; TFT_CNTRL_PORT->MODER = 0x55400000; }
// set the data pins (PA8-PA15) to input mode and enable ahb clock for gpioa
#define setReadDir() { RCC->AHBENR |= (0b0010 << 16); TFT_DATA_PORT->MODER = 0x00000000; }
// set the data pins (PA8-PA15) to output mode and enable ahb clock for gpioa
#define setWriteDir() { RCC->AHBENR |= (0b0010 << 16); TFT_DATA_PORT->OSPEEDR = 0xFFFF0000; TFT_DATA_PORT->MODER = 0x55550000; }
// set pins to output the 8 bit value
#define write8(c) { TFT_DATA_PORT->BSRR = (uint32_t)(0xFF000000 + (((c)&0xFF) << 8)); WR_STROBE; }
/*****************************************************************************/
#define swap(a, b) { int16_t t = a; a = b; b = t; }
/*****************************************************************************/
class STM32_ILI9486_8_bit : public Adafruit_GFX {
public:
STM32_ILI9486_8_bit(void);
void begin(void);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void drawFastHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color);
void drawFastVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t c);
void fillScreen(uint16_t color);
void reset(void);
void setRegisters8(uint8_t *ptr, uint8_t n);
void setRegisters16(uint16_t *ptr, uint8_t n);
void setRotation(uint8_t x);
// These methods are public in order for BMP examples to work:
void setAddrWindow(int16_t x1, int16_t y1, int16_t x2, int16_t y2);
void invertDisplay(boolean i),
pushColors(uint16_t *data, int16_t len, boolean first),
drawBitmap(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t * bitmap);
uint16_t readPixel(int16_t x, int16_t y), readID(void);
/*****************************************************************************/
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
// color coding on bits:
// high byte sill be sent first
// bit nr: 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
// color/bit: R5 R4 R3 R2 R1 | G5 G4 G3 G2 G1 G0 | B5 B4 B3 B2 B1
// R0=R5 B0=B5
/*****************************************************************************/
uint16_t inline color565(uint8_t r, uint8_t g, uint8_t b) { return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); }
private:
void init(), flood(uint16_t color, uint32_t len);
uint8_t driver;
};
extern uint16_t readReg(uint8_t r);
extern uint32_t readReg32(uint8_t r);
extern void writeCommand(uint16_t c);
extern void writeRegister8(uint16_t a, uint8_t d);
extern void writeRegister16(uint16_t a, uint16_t d);
extern void writeRegister24(uint16_t a, uint32_t d);
extern void writeRegister32(uint16_t a, uint32_t d);
extern void writeRegisterPair(uint16_t aH, uint16_t aL, uint16_t d);
extern STM32_ILI9486_8_bit tft;
#endif

Should I worry about adding the alternate function definitions back in? I assume as I'm not using the serial wire debugging interface it doesn't affect the pins after it starts running my code.