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

mrburnette Tue Oct 06, 2015 12:25 pm

Start by searching this forum for Pig-o-Scope…
The entire forum is indexed by Google, so you can form a query as:
pig scope site:stm32duino.com

andreas_ferm Tue Oct 06, 2015 7:07 pm

Thanks for the quick answer Ray,

I believe i have scratched through most of this forum (although I might’ve missed out in some hidden thread). I’ve also visited and examined your projects page as well (which i think was one of the factors that made me want to give the maple mini a ‘go’)

Either way, all the info i’ve found for ILI9341 are with SPI connectivity, which i guess my module lacks (post-sales service from chinese vendors leaves quite a bit to ask for imho). I saw there was an Adafruit library for AVR which had support for SPI and 8bit parallell for ILI9341, but i’m not yet comfortable in the low level details of the stm32 boards to port this).

Wifey’s todo-list and 2 toddlers tends to kill of most of my time as well, so I was hoping that others more low-level-nerdy than me would’ve already taken a look at this. :)

andreas_ferm Tue Oct 06, 2015 9:39 pm

Got tired of waiting for a reply from seller and tried pried the screen away from the pcb, and from the markings it seems to be an SSD1289, so now back to the drawing board to see what is possible with this new information… :)

zmemw16 Tue Oct 06, 2015 9:53 pm

i thought i’d posted my first reply, seems it got lost; below is precis of it

pics of back, any identication text, link to the seller/desciption would all be helpful
i suggested a google with ili9341 and pdf, substitute ssd1289 – returns shed loads of links

the chips mode is set by 4 pins same with ssd1289 and i suspect the silk screen might be a one size fits all types/models. as you’ve opened it you might be able to see what its set up for (avo/multimeter resistance pin to ground ) and go from there
next is assume spi and try to read from a register (id-code1/2/3) and see if it makes sense.
you might need to send some values to reset it first.
also the id registers vary from driver to driver:-)
my starting point is the using spi sketch, about to go that route for some of my displays

stephen

andreas_ferm Tue Oct 06, 2015 10:19 pm

The screen i bought was this : http://www.aliexpress.com/item/Free-shi … 24430.html

and it looks exactly like this one http://www.sainsmart.com/sainsmart-3-2- … er-reviews but when looking at the back of the pcb my board uses a TSC2046 as a touch screen controller (but that is for later, first step is to actually being able to display something useful on the screen)

On the ‘ribbon’ that connected the display to the pcb it is written T32-1289 V21

I doubt that this display uses spi , of all the 40pins the pcb has, the ones that would point to spi are for the sd-card reader(SD_CLK, SD_DIN etc..) and touch (T_CS, T_CLK etc..) and i guess the DB0-15 and CS, REST, RD, WR, RS are for the actual display in parallel mode?

mrburnette Tue Oct 06, 2015 11:47 pm

andreas_ferm wrote:
<…>
I doubt that this display uses spi , of all the 40pins the pcb has, the ones that would point to spi are for the sd-card reader(SD_CLK, SD_DIN etc..) and touch (T_CS, T_CLK etc..) and i guess the DB0-15 and CS, REST, RD, WR, RS are for the actual display in parallel mode?

zmemw16 Wed Oct 07, 2015 12:52 am

i googled ‘T32-1289 V21 tft lcd 3.2’

http://www.wayengineer.com/32-tft-lcd-w … hRl9Orjsgs
at the bottom is a link to a pdf of the display specification, this is before the pcb gets attached.

p12 details the interface as an 8080 parallel type – 16bit data, rd/wr/cs/rs controls & 2.8v power

https://www.raspberrypi.org/forums/view … p?p=307273 yields

http://static.electrodragon.com/wp-cont … play-3.jpg
does this match yours?

ok, its raspberry, but the1rytttttttttttttttt the cat just exercised across the keyboard, she’s peeved she got locked out and it rained.
anyway there’s a circuit in there which might be of interest; 4040 & 3x 4094 to give a spi interface

TSC2046 is likely the TI version of xpt2046 and probably a drop-in replacement
stephen

martinayotte Wed Oct 07, 2015 2:18 am

Several chipset have been discussed here …
But let say that I’ve recently ordered an LCD 8 bit Parallel : http://www.ebay.ca/itm/141647130960
I didn’t found library compatible as is, but find pieces of code put together, so here is a part of my sketch using this LCD on my Netduio2Plus :

uint8_t LCD_RST = PC4;
uint8_t LCD_CS = PC3;
uint8_t LCD_RS = PC2;
uint8_t LCD_WR = PC1;
uint8_t LCD_RD = PC0;
uint8_t DPINS[] = {PC7, PC6, PA3, PA2, PB12, PB8, PB9, PA1, PA0, PA6};

#define Black 0x0000
#define White 0xFFFF
#define Red 0xF800
#define Green 0x07E0
#define Blue 0x102E
#define Cyan 0x07FF
#define Magenta 0xF81F
#define Navy 0x000F
#define DarkGreen 0x03E0
#define Purple 0x780F
#define Olive 0x7BE0
#define DarkGrey 0x7BEF
#define DarkCyan 0x001F
#define Yellow 0xFFE0
#define Orange 0xFD20

uint16 indexed_color[] = { Black, White, Red, Green, Blue, Cyan, Magenta, Navy, DarkGreen, Purple, Olive, DarkGrey, DarkCyan, Yellow, Orange};

#define background Black

void LCD_Init() {
pinMode(LCD_RST, OUTPUT);
pinMode(LCD_CS, OUTPUT);
pinMode(LCD_RS, OUTPUT);
pinMode(LCD_WR, OUTPUT);
pinMode(LCD_RD, OUTPUT);
for (uint8_t i = 2; i <= 9; i++)
pinMode(DPINS[i], OUTPUT);
digitalWrite(LCD_CS, HIGH);
digitalWrite(LCD_RS, HIGH);
digitalWrite(LCD_WR, HIGH);
digitalWrite(LCD_RD, HIGH);
digitalWrite(LCD_RST, HIGH);
delay(5);
digitalWrite(LCD_RST, LOW);
delay(15);
digitalWrite(LCD_RST, HIGH);
delay(15);
digitalWrite(LCD_CS, LOW);
lcd_cmd(0xE9);
lcd_data(0x20);
lcd_cmd(0x11); // Exit Sleep
delay(100);
lcd_cmd(0xD1);
lcd_data(0x00);
lcd_data(0x71);
lcd_data(0x19);
lcd_cmd(0xD0);
lcd_data(0x07);
lcd_data(0x01);
lcd_data(0x08);
lcd_cmd(0x36);
lcd_data(0x19); // lcd_data(0x48);
lcd_cmd(0x3A); // Set_pixel_format
lcd_data(0x05); // color setings, 05h - 16bit pixel, 11h - 3bit pixel
lcd_cmd(0xC1);
lcd_data(0x10);
lcd_data(0x10);
lcd_data(0x02);
lcd_data(0x02);
lcd_cmd(0xC0); // Set Default Gamma
lcd_data(0x00);
lcd_data(0x35);
lcd_data(0x00);
lcd_data(0x00);
lcd_data(0x01);
lcd_data(0x02);
lcd_cmd(0xC5); // Set Frame Rate
lcd_data(0x04); // 72Hz
lcd_cmd(0xD2); // Power Settings
lcd_data(0x01);
lcd_data(0x44);
lcd_cmd(0xC8); //Set Gamma
lcd_data(0x04);
lcd_data(0x67);
lcd_data(0x35);
lcd_data(0x04);
lcd_data(0x08);
lcd_data(0x06);
lcd_data(0x24);
lcd_data(0x01);
lcd_data(0x37);
lcd_data(0x40);
lcd_data(0x03);
lcd_data(0x10);
lcd_data(0x08);
lcd_data(0x80);
lcd_data(0x00);
lcd_cmd(0x2A); // Set_column_address 320px
lcd_data(0x00);
lcd_data(0x00);
lcd_data(0x00);
lcd_data(0xEF);
lcd_cmd(0x2B); // Set_page_address 480px
lcd_data(0x00);
lcd_data(0x00);
lcd_data(0x01);
lcd_data(0x3F);
// lcd_data(0x8F);
lcd_cmd(0x29); //display on
lcd_cmd(0x2C); //display on
digitalWrite(LCD_CS, HIGH);
}

void lcd_write_bus(uint8_t val) {
unsigned char i, temp, data;
data = val;
for (i = 2; i <= 9; i++)
pinMode(DPINS[i], OUTPUT);
for (i = 8; i <= 9; i++) {
temp = (data & 0x01);
if (temp)
digitalWrite(DPINS[i], HIGH);
else
digitalWrite(DPINS[i], LOW);
data = data >> 1;
}
for (i = 2; i <= 7;i++) {
temp = (data & 0x01);
if (temp)
digitalWrite(DPINS[i], HIGH);
else
digitalWrite(DPINS[i], LOW);
data = data >> 1;
}
digitalWrite(LCD_WR, LOW);
digitalWrite(LCD_WR, HIGH);
}

void lcd_cmd(uint8_t cmd) {
digitalWrite(LCD_RS, LOW);
lcd_write_bus(cmd);
}

void lcd_data(uint8_t data) {
digitalWrite(LCD_RS, HIGH);
lcd_write_bus(data);
}

void lcd_cmd_data(uint8_t cmd, uint8_t data) {
lcd_cmd(cmd);
lcd_data(data);
}

void SetWindows(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) {
lcd_cmd(0x2a); // Set_column_address 4 parameters
lcd_data(x1 >> 8);
lcd_data(x1);
lcd_data(x2 >> 8);
lcd_data(x2);
lcd_cmd(0x2b); // Set_page_address 4 parameters
lcd_data(y1 >> 8);
lcd_data(y1);
lcd_data(y2 >> 8);
lcd_data(y2);
lcd_cmd(0x2c); // Write_memory_start
}

void LCD_Clear(unsigned int j)
{
unsigned int x, y;
lcd_cmd(0x02c); // write_memory_start
digitalWrite(LCD_RS, HIGH);
digitalWrite(LCD_CS, LOW);
SetWindows(0, 0, 319, 479); // 479, 319);
for (x = 0; x < 480; x++)
for (y = 0; y < 320; y++) {
lcd_data(j >> 8);
lcd_data(j);
}
digitalWrite(LCD_CS, HIGH);
}

void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) {
unsigned int i, j;
lcd_cmd(0x02c); //write_memory_start
digitalWrite(LCD_RS, HIGH);
digitalWrite(LCD_CS, LOW);
l = l + x;
SetWindows(x, y, l, y);
j = l * 2;
for (i = 1; i <= j; i++) {
lcd_data(c >> 8);
lcd_data(c);
}
digitalWrite(LCD_CS, HIGH);
}

void V_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) {
unsigned int i,j;
lcd_cmd(0x02c); //write_memory_start
digitalWrite(LCD_RS, HIGH);
digitalWrite(LCD_CS, LOW);
l = l + y;
SetWindows(x, y, x, l);
j = l * 2;
for (i = 1; i <= j; i++) {
lcd_data(c >> 8);
lcd_data(c);
}
digitalWrite(LCD_CS, HIGH);
}

void Rect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int c) {
H_line(x , y , w, c);
H_line(x , y+h, w, c);
V_line(x , y , h, c);
V_line(x+w, y , h, c);
}

void FillRect(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int c) {
unsigned int i;
for (i = 0; i < h; i++) {
H_line(x , y , w, c);
H_line(x , y+i, w, c);
}
}

#define fontXSizeSmal 8
#define fontYSizeSmal 12
#define fontXSizeBig 16
#define fontYSizeBig 16
#define fontXSizeNum 32
#define fontYSizeNum 50

#define fontdatatype const uint8_t
#define fontdatatype16 const uint16_t

// Font Size : 8x12 1140 bytes

fontdatatype smallFont[1140] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <Space>
0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, // !
0x00, 0x28, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // "
0x00, 0x00, 0x28, 0x28, 0xFC, 0x28, 0x50, 0xFC, 0x50, 0x50, 0x00, 0x00, // #
0x00, 0x20, 0x78, 0xA8, 0xA0, 0x60, 0x30, 0x28, 0xA8, 0xF0, 0x20, 0x00, // $
0x00, 0x00, 0x48, 0xA8, 0xB0, 0x50, 0x28, 0x34, 0x54, 0x48, 0x00, 0x00, // %
0x00, 0x00, 0x20, 0x50, 0x50, 0x78, 0xA8, 0xA8, 0x90, 0x6C, 0x00, 0x00, // &
0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '
0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, // (
0x00, 0x40, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, // )
0x00, 0x00, 0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00, 0x00, 0x00, // *
0x00, 0x00, 0x20, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, // +
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, // ,
0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // -
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, // .
0x00, 0x08, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x00, // /
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // 0
0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // 1
0x00, 0x00, 0x70, 0x88, 0x88, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, 0x00, // 2
0x00, 0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, // 3
0x00, 0x00, 0x10, 0x30, 0x50, 0x50, 0x90, 0x78, 0x10, 0x18, 0x00, 0x00, // 4
0x00, 0x00, 0xF8, 0x80, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, // 5
0x00, 0x00, 0x70, 0x90, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // 6
0x00, 0x00, 0xF8, 0x90, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, // 7
0x00, 0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // 8
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x08, 0x48, 0x70, 0x00, 0x00, // 9
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, // :
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, // ;
0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, // <
0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, // =
0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, // >
0x00, 0x00, 0x70, 0x88, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, // ?
0x00, 0x00, 0x70, 0x88, 0x98, 0xA8, 0xA8, 0xB8, 0x80, 0x78, 0x00, 0x00, // @
0x00, 0x00, 0x20, 0x20, 0x30, 0x50, 0x50, 0x78, 0x48, 0xCC, 0x00, 0x00, // A
0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00, // B
0x00, 0x00, 0x78, 0x88, 0x80, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00, // C
0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00, // D
0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x48, 0xF8, 0x00, 0x00, // E
0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x40, 0xE0, 0x00, 0x00, // F
0x00, 0x00, 0x38, 0x48, 0x80, 0x80, 0x9C, 0x88, 0x48, 0x30, 0x00, 0x00, // G
0x00, 0x00, 0xCC, 0x48, 0x48, 0x78, 0x48, 0x48, 0x48, 0xCC, 0x00, 0x00, // H
0x00, 0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, // I
0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x90, 0xE0, 0x00, // J
0x00, 0x00, 0xEC, 0x48, 0x50, 0x60, 0x50, 0x50, 0x48, 0xEC, 0x00, 0x00, // K
0x00, 0x00, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0xFC, 0x00, 0x00, // L
0x00, 0x00, 0xD8, 0xD8, 0xD8, 0xD8, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, 0x00, // M
0x00, 0x00, 0xDC, 0x48, 0x68, 0x68, 0x58, 0x58, 0x48, 0xE8, 0x00, 0x00, // N
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // O
0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, // P
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0xE8, 0x98, 0x70, 0x18, 0x00, // Q
0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x50, 0x48, 0x48, 0xEC, 0x00, 0x00, // R
0x00, 0x00, 0x78, 0x88, 0x80, 0x60, 0x10, 0x08, 0x88, 0xF0, 0x00, 0x00, // S
0x00, 0x00, 0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // T
0x00, 0x00, 0xCC, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, // U
0x00, 0x00, 0xCC, 0x48, 0x48, 0x50, 0x50, 0x30, 0x20, 0x20, 0x00, 0x00, // V
0x00, 0x00, 0xA8, 0xA8, 0xA8, 0x70, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, // W
0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x50, 0x50, 0xD8, 0x00, 0x00, // X
0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // Y
0x00, 0x00, 0xF8, 0x90, 0x10, 0x20, 0x20, 0x40, 0x48, 0xF8, 0x00, 0x00, // Z
0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, // [
0x00, 0x40, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, // <Backslash>
0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, // ] 0x00, 0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ^
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, // _
0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x38, 0x48, 0x3C, 0x00, 0x00, // a
0x00, 0x00, 0xC0, 0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0x70, 0x00, 0x00, // b
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x40, 0x40, 0x38, 0x00, 0x00, // c
0x00, 0x00, 0x18, 0x08, 0x08, 0x38, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00, // d
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x78, 0x40, 0x38, 0x00, 0x00, // e
0x00, 0x00, 0x1C, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x78, 0x00, 0x00, // f
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x48, 0x30, 0x40, 0x78, 0x44, 0x38, // g
0x00, 0x00, 0xC0, 0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0xEC, 0x00, 0x00, // h
0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // i
0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0xE0, // j
0x00, 0x00, 0xC0, 0x40, 0x40, 0x5C, 0x50, 0x70, 0x48, 0xEC, 0x00, 0x00, // k
0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, // l
0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, 0x00, // m
0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0xEC, 0x00, 0x00, // n
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, // o
0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0x70, 0x40, 0xE0, // p
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x38, 0x08, 0x1C, // q
0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x60, 0x40, 0x40, 0xE0, 0x00, 0x00, // r
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x40, 0x30, 0x08, 0x78, 0x00, 0x00, // s
0x00, 0x00, 0x00, 0x20, 0x20, 0x70, 0x20, 0x20, 0x20, 0x18, 0x00, 0x00, // t
0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00, // u
0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x48, 0x50, 0x30, 0x20, 0x00, 0x00, // v
0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xA8, 0x70, 0x50, 0x50, 0x00, 0x00, // w
0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x50, 0x20, 0x50, 0xD8, 0x00, 0x00, // x
0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x48, 0x50, 0x30, 0x20, 0x20, 0xC0, // y
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x10, 0x20, 0x20, 0x78, 0x00, 0x00, // z
0x00, 0x18, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, // {
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // |
0x00, 0x60, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x60, 0x00, // }
0x40, 0xA4, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ~
};

fontdatatype16 bigFont[1520] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // <Space>
0x0000, 0x0000, 0x0700, 0x0F80, 0x0F80, 0x0F80, 0x0F80, 0x0F80, 0x0700, 0x0700, 0x0000, 0x0000, 0x0700, 0x0700, 0x0700, 0x0000, // !
0x0000, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0630, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // "
0x0000, 0x0C30, 0x0C30, 0x0C30, 0x7FFE, 0x7FFE, 0x0C30, 0x0C30, 0x0C30, 0x0C30, 0x7FFE, 0x7FFE, 0x0C30, 0x0C30, 0x0C30, 0x0000, // #
0x0000, 0x0240, 0x0240, 0x0FF8, 0x1FF8, 0x1A40, 0x1A40, 0x1FF0, 0x0FF8, 0x0258, 0x0258, 0x1FF8, 0x1FF0, 0x0240, 0x0240, 0x0000, // $
0x0000, 0x0000, 0x0000, 0x0E10, 0x0E30, 0x0E70, 0x00E0, 0x01C0, 0x0380, 0x0700, 0x0E70, 0x0C70, 0x0870, 0x0000, 0x0000, 0x0000, // %
0x0000, 0x0000, 0x0F00, 0x1980, 0x1980, 0x1980, 0x0F00, 0x0F08, 0x0F98, 0x19F8, 0x18F0, 0x18E0, 0x19F0, 0x0F98, 0x0000, 0x0000, // &
0x0000, 0x0000, 0x0700, 0x0700, 0x0700, 0x0E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '
0x0000, 0x0000, 0x00F0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x0700, 0x0380, 0x01C0, 0x00F0, 0x0000, 0x0000, // (
0x0000, 0x0000, 0x0F00, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0070, 0x0070, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0F00, 0x0000, 0x0000, // )
0x0000, 0x0000, 0x0180, 0x1188, 0x0990, 0x07E0, 0x07E0, 0x3FFC, 0x3FFC, 0x07E0, 0x07E0, 0x0990, 0x1188, 0x0180, 0x0000, 0x0000, // *
0x0000, 0x0000, 0x0000, 0x0000, 0x0180, 0x0180, 0x0180, 0x0FF0, 0x0FF0, 0x0180, 0x0180, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, // +
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0700, 0x0700, 0x0700, 0x0E00, 0x0000, // ,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FF8, 0x1FF8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // -
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0700, 0x0700, 0x0700, 0x0000, 0x0000, // ,
0x0000, 0x0000, 0x0002, 0x0006, 0x000E, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x1C00, 0x0000, 0x0000, // /

0x0000, 0x0000, 0x0FF0, 0x1C38, 0x1C78, 0x1CF8, 0x1CF8, 0x1DB8, 0x1DB8, 0x1F38, 0x1F38, 0x1E38, 0x1C38, 0x0FF0, 0x0000, 0x0000, // 0
0x0000, 0x0000, 0x0180, 0x0180, 0x0380, 0x1F80, 0x1F80, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x1FF0, 0x0000, 0x0000, // 1
0x0000, 0x0000, 0x0FE0, 0x1C70, 0x1C38, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0700, 0x0E38, 0x1C38, 0x1FF8, 0x0000, 0x0000, // 2
0x0000, 0x0000, 0x0FE0, 0x1C70, 0x1C38, 0x0038, 0x0070, 0x03C0, 0x03C0, 0x0070, 0x0038, 0x1C38, 0x1C70, 0x0FE0, 0x0000, 0x0000, // 3
0x0000, 0x0000, 0x00E0, 0x01E0, 0x03E0, 0x06E0, 0x0CE0, 0x18E0, 0x1FF8, 0x1FF8, 0x00E0, 0x00E0, 0x00E0, 0x03F8, 0x0000, 0x0000, // 4
0x0000, 0x0000, 0x1FF8, 0x1C00, 0x1C00, 0x1C00, 0x1C00, 0x1FE0, 0x1FF0, 0x0078, 0x0038, 0x1C38, 0x1C70, 0x0FE0, 0x0000, 0x0000, // 5
0x0000, 0x0000, 0x03E0, 0x0700, 0x0E00, 0x1C00, 0x1C00, 0x1FF0, 0x1FF8, 0x1C38, 0x1C38, 0x1C38, 0x1C38, 0x0FF0, 0x0000, 0x0000, // 6
0x0000, 0x0000, 0x1FFC, 0x1C1C, 0x1C1C, 0x1C1C, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0380, 0x0380, 0x0000, 0x0000, // 7
0x0000, 0x0000, 0x0FF0, 0x1C38, 0x1C38, 0x1C38, 0x1F38, 0x07E0, 0x07E0, 0x1CF8, 0x1C38, 0x1C38, 0x1C38, 0x0FF0, 0x0000, 0x0000, // 8
0x0000, 0x0000, 0x0FF0, 0x1C38, 0x1C38, 0x1C38, 0x1C38, 0x1FF8, 0x0FF8, 0x0038, 0x0038, 0x0070, 0x00E0, 0x07C0, 0x0000, 0x0000, // 9
0x0000, 0x0000, 0x0000, 0x0000, 0x0380, 0x0380, 0x0380, 0x0000, 0x0000, 0x0380, 0x0380, 0x0380, 0x0000, 0x0000, 0x0000, 0x0000, // :
0x0000, 0x0000, 0x0000, 0x0000, 0x0380, 0x0380, 0x0380, 0x0000, 0x0000, 0x0380, 0x0380, 0x0380, 0x0700, 0x0000, 0x0000, 0x0000, // ;
0x0000, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x1C00, 0x1C00, 0x0E00, 0x0700, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0000, // <
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3FFC, 0x3FFC, 0x0000, 0x0000, 0x3FFC, 0x3FFC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // =
0x0000, 0x1C00, 0x0E00, 0x0700, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x1C00, 0x0000, // >
0x0000, 0x03C0, 0x0FF0, 0x1E78, 0x1838, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x01C0, 0x0000, 0x0000, 0x01C0, 0x01C0, 0x01C0, 0x0000, // ?

0x0000, 0x0FF8, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1CFC, 0x1CFC, 0x1CFC, 0x1CFC, 0x1C00, 0x1C00, 0x1C00, 0x1FF0, 0x07F8, 0x0000, // @
0x0000, 0x0000, 0x03C0, 0x07E0, 0x0E70, 0x1C38, 0x1C38, 0x1C38, 0x1C38, 0x1FF8, 0x1C38, 0x1C38, 0x1C38, 0x1C38, 0x0000, 0x0000, // A
0x0000, 0x0000, 0x1FF0, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0FF0, 0x0FF0, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x1FF0, 0x0000, 0x0000, // B
0x0000, 0x0000, 0x07F0, 0x0E38, 0x1C38, 0x1C00, 0x1C00, 0x1C00, 0x1C00, 0x1C00, 0x1C00, 0x1C38, 0x0E38, 0x07F0, 0x0000, 0x0000, // C
0x0000, 0x0000, 0x1FE0, 0x0E70, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E70, 0x1FE0, 0x0000, 0x0000, // D
0x0000, 0x0000, 0x1FF8, 0x0E18, 0x0E08, 0x0E00, 0x0E30, 0x0FF0, 0x0FF0, 0x0E30, 0x0E00, 0x0E08, 0x0E18, 0x1FF8, 0x0000, 0x0000, // E
0x0000, 0x0000, 0x1FF8, 0x0E18, 0x0E08, 0x0E00, 0x0E30, 0x0FF0, 0x0FF0, 0x0E30, 0x0E00, 0x0E00, 0x0E00, 0x1F00, 0x0000, 0x0000, // F
0x0000, 0x0000, 0x07F0, 0x0E38, 0x1C38, 0x1C38, 0x1C00, 0x1C00, 0x1C00, 0x1CF8, 0x1C38, 0x1C38, 0x0E38, 0x07F8, 0x0000, 0x0000, // G
0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1FF0, 0x1FF0, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0000, 0x0000, // H
0x0000, 0x0000, 0x0FE0, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0380, 0x0FE0, 0x0000, 0x0000, // I
0x0000, 0x0000, 0x01FC, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x3870, 0x3870, 0x3870, 0x3870, 0x0FE0, 0x0000, 0x0000, // J
0x0000, 0x0000, 0x1E38, 0x0E38, 0x0E70, 0x0EE0, 0x0FC0, 0x0F80, 0x0F80, 0x0FC0, 0x0EE0, 0x0E70, 0x0E38, 0x1E38, 0x0000, 0x0000, // K
0x0000, 0x0000, 0x1F00, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x0E08, 0x0E18, 0x0E38, 0x1FF8, 0x0000, 0x0000, // L
0x0000, 0x0000, 0x1C1C, 0x1E3C, 0x1F7C, 0x1FFC, 0x1FFC, 0x1DDC, 0x1C9C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x0000, 0x0000, // M
0x0000, 0x0000, 0x1C1C, 0x1C1C, 0x1E1C, 0x1F1C, 0x1F9C, 0x1DDC, 0x1CFC, 0x1C7C, 0x1C3C, 0x1C1C, 0x1C1C, 0x1C1C, 0x0000, 0x0000, // N
0x0000, 0x0000, 0x03E0, 0x07F0, 0x0E38, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x0E38, 0x07F0, 0x03E0, 0x0000, 0x0000, // O

0x0000, 0x0000, 0x1FF0, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0FF0, 0x0FF0, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x1F00, 0x0000, 0x0000, // P
0x0000, 0x0000, 0x03E0, 0x0F78, 0x0E38, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C7C, 0x1CFC, 0x0FF8, 0x0FF8, 0x0038, 0x00FC, 0x0000, // Q
0x0000, 0x0000, 0x1FF0, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0FF0, 0x0FF0, 0x0E70, 0x0E38, 0x0E38, 0x0E38, 0x1E38, 0x0000, 0x0000, // R
0x0000, 0x0000, 0x0FF0, 0x1C38, 0x1C38, 0x1C38, 0x1C00, 0x0FE0, 0x07F0, 0x0038, 0x1C38, 0x1C38, 0x1C38, 0x0FF0, 0x0000, 0x0000, // S
0x0000, 0x0000, 0x1FFC, 0x19CC, 0x11C4, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x07F0, 0x0000, 0x0000, // T
0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0FE0, 0x0000, 0x0000, // U
0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0EE0, 0x07C0, 0x0380, 0x0000, 0x0000, // V
0x0000, 0x0000, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C9C, 0x1C9C, 0x1C9C, 0x0FF8, 0x0FF8, 0x0770, 0x0770, 0x0000, 0x0000, // W
0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x0EE0, 0x07C0, 0x0380, 0x0380, 0x07C0, 0x0EE0, 0x1C70, 0x1C70, 0x1C70, 0x0000, 0x0000, // X
0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0EE0, 0x07C0, 0x0380, 0x0380, 0x0380, 0x0380, 0x0FE0, 0x0000, 0x0000, // Y
0x0000, 0x0000, 0x1FF8, 0x1C38, 0x1838, 0x1070, 0x00E0, 0x01C0, 0x0380, 0x0700, 0x0E08, 0x1C18, 0x1C38, 0x1FF8, 0x0000, 0x0000, // Z
0x0000, 0x0000, 0x07F0, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x0700, 0x07F0, 0x0000, 0x0000, // [
0x0000, 0x0000, 0x1000, 0x1800, 0x1C00, 0x0E00, 0x0700, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x0007, 0x0000, 0x0000, // <Backslash>
0x0000, 0x0000, 0x07F0, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x07F0, 0x0000, 0x0000, // ] 0x0000, 0x0180, 0x03C0, 0x07E0, 0x0E70, 0x1C38, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, // _

0x0000, 0x0000, 0x1C00, 0x1C00, 0x0700, 0x0700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FE0, 0x0070, 0x0070, 0x0FF0, 0x1C70, 0x1C70, 0x1C70, 0x0FD8, 0x0000, 0x0000, // a
0x0000, 0x0000, 0x1E00, 0x0E00, 0x0E00, 0x0E00, 0x0FF0, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x1BF0, 0x0000, 0x0000, // b
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FE0, 0x1C70, 0x1C70, 0x1C00, 0x1C00, 0x1C70, 0x1C70, 0x0FE0, 0x0000, 0x0000, // c
0x0000, 0x0000, 0x00F8, 0x0070, 0x0070, 0x0070, 0x0FF0, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0FD8, 0x0000, 0x0000, // d
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FE0, 0x1C70, 0x1C70, 0x1FF0, 0x1C00, 0x1C70, 0x1C70, 0x0FE0, 0x0000, 0x0000, // e
0x0000, 0x0000, 0x03E0, 0x0770, 0x0770, 0x0700, 0x0700, 0x1FE0, 0x1FE0, 0x0700, 0x0700, 0x0700, 0x0700, 0x1FC0, 0x0000, 0x0000, // f
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FD8, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0FF0, 0x07F0, 0x0070, 0x1C70, 0x0FE0, // g
0x0000, 0x0000, 0x1E00, 0x0E00, 0x0E00, 0x0E00, 0x0EF0, 0x0F38, 0x0F38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x1E38, 0x0000, 0x0000, // h
0x0000, 0x0000, 0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0FC0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x0FF8, 0x0000, 0x0000, // i
0x0000, 0x0000, 0x0070, 0x0070, 0x0070, 0x0000, 0x03F0, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x1C70, 0x0CF0, 0x07E0, // j
0x0000, 0x0000, 0x1E00, 0x0E00, 0x0E00, 0x0E00, 0x0E38, 0x0E70, 0x0EE0, 0x0FC0, 0x0EE0, 0x0E70, 0x0E38, 0x1E38, 0x0000, 0x0000, // k
0x0000, 0x0000, 0x0FC0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x0FF8, 0x0000, 0x0000, // l
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FF8, 0x1C9C, 0x1C9C, 0x1C9C, 0x1C9C, 0x1C9C, 0x1C9C, 0x1C9C, 0x0000, 0x0000, // m
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FE0, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0000, 0x0000, // n
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FE0, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0FE0, 0x0000, 0x0000, // o

0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1BF0, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0FF0, 0x0E00, 0x0E00, 0x1F00, // p
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FB0, 0x38E0, 0x38E0, 0x38E0, 0x38E0, 0x38E0, 0x1FE0, 0x00E0, 0x00E0, 0x01F0, // q
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1EF0, 0x0FF8, 0x0F38, 0x0E00, 0x0E00, 0x0E00, 0x0E00, 0x1F00, 0x0000, 0x0000, // r
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FE0, 0x1C30, 0x1C30, 0x0F80, 0x03E0, 0x1870, 0x1870, 0x0FE0, 0x0000, 0x0000, // s
0x0000, 0x0000, 0x0000, 0x0100, 0x0300, 0x0700, 0x1FF0, 0x0700, 0x0700, 0x0700, 0x0700, 0x0770, 0x0770, 0x03E0, 0x0000, 0x0000, // t
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0FD8, 0x0000, 0x0000, // u
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x1C70, 0x0EE0, 0x07C0, 0x0380, 0x0000, 0x0000, // v
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C, 0x1C1C, 0x1C1C, 0x1C9C, 0x1C9C, 0x0FF8, 0x0770, 0x0770, 0x0000, 0x0000, // w
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1CE0, 0x1CE0, 0x0FC0, 0x0780, 0x0780, 0x0FC0, 0x1CE0, 0x1CE0, 0x0000, 0x0000, // x
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x0E38, 0x07F0, 0x03E0, 0x00E0, 0x01C0, 0x1F80, // y
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1FE0, 0x18E0, 0x11C0, 0x0380, 0x0700, 0x0E20, 0x1C60, 0x1FE0, 0x0000, 0x0000, // z
0x0000, 0x0000, 0x01F8, 0x0380, 0x0380, 0x0380, 0x0700, 0x1C00, 0x1C00, 0x0700, 0x0380, 0x0380, 0x0380, 0x01F8, 0x0000, 0x0000, // {
0x0000, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x0000, // |
0x0000, 0x0000, 0x1F80, 0x01C0, 0x01C0, 0x01C0, 0x00E0, 0x0038, 0x0038, 0x00E0, 0x01C0, 0x01C0, 0x01C0, 0x1F80, 0x0000, 0x0000, // }
0x0000, 0x0000, 0x1F1C, 0x3B9C, 0x39DC, 0x38F8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 // ~
};

void lcdPrint(String text, int x, int y, int fontSize, int color) {
int fontXSize ;
int fontYSize ;
switch (fontSize) {
case 1:
fontXSize = fontXSizeSmal ;
fontYSize = fontYSizeSmal ;
break;
case 2:
fontXSize = fontXSizeBig ;
fontYSize = fontYSizeBig ;
break;
case 3:
fontXSize = fontXSizeNum ;
fontYSize = fontYSizeNum ;
default:
fontXSize = fontSize / 1.4 ;
fontYSize = fontSize ;
// space = fontSize / 3 ;
}
char charInput ;
int cLenght = text.length();
int charDec ;
int c ;
int charHex ;
char char_array[cLenght];
text.toCharArray(char_array, cLenght) ;
for (int i = 0; i < cLenght ; i++) {
charInput = char_array[i] ;
charDec = int(charInput);
digitalWrite(LCD_CS, LOW);
SetWindows(x + (i * fontXSize), y, x + (i * fontXSize) + fontXSize - 1, y + fontYSize );
long charHex1 ;
for ( int n = 0 ; n < fontYSize ; n++ ) {
if (fontSize == 1) charHex1 = pgm_read_word_near(smallFont + ((charDec - 32) * fontYSize) + n);
if (fontSize == 2) charHex1 = pgm_read_word_near(bigFont + ((charDec - 32) * fontYSize) + n);
for (int t = 1; t < fontXSize + 1 ; t++) {
if (( charHex1 & (1 << (fontXSize - t))) > 0 ) {
c = color ;
} else {
c = background ;
};
lcd_data(c >> 8);
lcd_data(c);
}
}
digitalWrite(LCD_CS, HIGH);
}
}

zmemw16 Wed Oct 07, 2015 3:24 am

those are at a nice’ish price, £5 ukp, worth a try (twice:-)

that snippet is rather helpful as well

stephen

andreas_ferm Wed Oct 07, 2015 1:28 pm

I’ve thought about this a bit during the day, and it seems like a ‘working’ utft would be a way forward. In the huge monster stm32-thread on arduino.cc i found a “ported” utft library by Madias (http://forum.arduino.cc/index.php?actio … ach=114619) and it seems like he has adapted the hw definitions from “HW_MX20DX256.h” but only for 4 and 5 pin serial. The parts around 8 and 16bit parallel are commented out.

It looks a bit like this

case 16:
*/
*(volatile uint8_t *)(&GPIOD_PDOR) = VH;
GPIOB_PCOR = 0x000F000F; // clear data lines B0-3,B16-19
GPIOB_PSOR = (0x0F & VL) | ((VL >> 4) << 16); // set data lines 0-3,16-19 if set in cl
pulse_low(P_WR, B_WR);

*/ break;

andreas_ferm Wed Oct 07, 2015 8:46 pm

Thanks for that link Roger it seems to be touching the exact same thing i’m looking for.

I’m still trying to decipher what is actually done in that teensy port and then try to do exactly the same but on a maple mini

And i think i have most of it covered theoretically (i.e i’ve found the equivalent stm32 registers, GPIOx_OTYPER, GPIOx_BSSR, GPIOx_MODER

One thing i don’t yet understand though is in a function called UTFT::_set_direction_registers(byte mode) where the teensy port call a lot of

PORTD_PCR0 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR2 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR6 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
PORTD_PCR7 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);

RogerClark Wed Oct 07, 2015 11:24 pm

I don’t know anything about Teensy programming, but looks like its setting the pinMode of the port

The STM32 has a control register for each port as well, but it’s split into Control Low reg and Control High register, each 32 bits wide.
The STM32 has to do this because each port is 16 bits wide, but I think there are 4 control bits per pin (well it needs more than 2 per pin)

Hence it has to split the control for each port across 2 registers.

If need to set the pinmode for all of a port (or part of a port) you will need to setup one or both of the control registers for that port.

The easiest way to work out what to do is to look at the pinMode function.

https://github.com/rogerclarkmelbourne/ … tal_f1.cpp

and at

gpio_set_mode()

andreas_ferm Wed Oct 14, 2015 8:39 am

Good morning Guys,

I just got this screen working. And just as a summary it was indeed a ssd1289 screen that is run in 16bit parallel mode (haven’t had the time to try 8 yet), and i used the UTFT library that i found posted by Madias somewhere.

To be honest i had problems understanding “how” to do the implementation using whole or parts of the gpio ports (i gave it a shot but it didnt work), so instead i used “custom ports” and digitalWrite for each pin

And the UTFT_demo ran and completed (without delays) in 17501ms, and by changing digitalWrite to gpio_write_bit it completed in 7029ms.

Now comes the question, and bear in mind that this is the first time i’ve used a tft display, would this performance be ‘sufficient’, to me it will only serve as a gui with buttons and showing data for a beer brewing system with a temp sensor and two SSR’s for controlling heat and a pump.

I guess the “simplest” “whole port write” would be to put all the datalines on GPIOA on a maple mini, but that would then take the SPI1 pins as well, which i was hoping to use for the touch screen, or can one use SPI2 with UTOUCH for example?

I guess i got a bit bitten when seeing just what kind of performance increase i got from digitalWrite to gpio_write_bit.

If the 16 data lines would be on different ports then it comes to the whole “masking” thing that i’m having problems understanding at the moment.

I’ll try 8 bit as well, and if it works i can post it here if some other newbie that doens’t have an spi tft to try?

RogerClark Wed Oct 14, 2015 8:53 am

Its going to be significantly faster writing 16 bits in one go, or even 8 bits off 2 separate ports.

If you need good display performance, you should invest in a board that has enough free pins that you can dedicate a whole port to the display.
(Its still only going to cost you less than $15 )

See this post my @madias about the boards he uses.

http://www.stm32duino.com/viewtopic.php … =650#p6841

But if you are not doing a lot of screen updates, then the difference in overall performance of your system e.g. including controlling SSR’s etc, may be mininal — But it really depends on the rest of your code.

In terms of whether a 72Mhz STM32 board is capable of handling the control of the brewing as well as operating a touch display. I would suspect that this would not be a problem.

However you need to make sure you don’t write “blocking” code, i.e don’t use delay() or do anything which waits in a while() loop for user input e.g. touch screen.

Some of the touch screen libraries have interrupt driven touch detection, so you should use that were possible

Alternatively you may want to look at using one of the RTOS frameworks that have been ported; I know that @victorpv had good results using FreeRTOS

andreas_ferm Wed Oct 14, 2015 9:15 am

Thanks for that info Roger. I think i’ll try using it in the current configuration, and if the need presents itself further down the road i’ll investigate those boards :)

ahull Mon Oct 26, 2015 10:47 pm

Did anybody post a working version of the UTFT lib that works with parallel displays like this?..
Image
Image

RogerClark Mon Oct 26, 2015 10:49 pm

Andy

I thought someone said that they had ported it, but I can’t remember where they posted to.

(Sorry)

Sign in to reply