BoxIdee

Driver per i controller ILI9481, ILI9341 e SSD1289

»    English section at the end


Driver per il controller ILI9481

L'oggetto in questione è un bel modulo con display 3.5"; ho letto da qualche parte che era usato sull' iPhone 3G.
Le caratteristiche sono: 480x320 pixels a 64K (o 256K) colori; è fornito dai cinesi su una board studiata (!?) per Arduino 1, con interfaccia parallela a 8 bit, 5 bit di comando e bit (non utilizzati al momento) per il connettore SPI della SD card; non ha il Touch Panel.
3 pin sono dedicati all'alimentazione del modulo: GND, +5, +3.3. Ovviamente la non-documentazione non cita se sono richieste entrambe, ne per che cosa.

Il primo passo è stato quindi di cercare e studiarmi lo Shield (si chiama così?) di Arduino 1 per capire cosa sono questi pin; potevano essere 2 ingressi, o 1 ingresso + 1 uscita da Arduino.
Risultato: sono 2 ingressi di cui uno, il 3.3V, inutile; funziona tutto senza e sul modulo c'è comunque un LDO da 3.3V

Secondo passo: prendere un programma precedente (driver per ILI4341) come template per il nuovo.
Di norma questo rende quasi immediato sviluppare il nuovo driver: si riconfigura l'Header con le definizioni dei pin di interfaccia e le dichiarazioni dei registri per il nuovo controller e quindi si passa a modificare il file con le funzioni di basso livello del driver, ovvero le procedure per scrivere comandi e dati sull'interfaccia e, punto fondamentale, la procedura di inizializzazione del controller.
La prima parte è solo noiosa; una lunga serie di copia/incolla dei nomi e dei codici dei registri dal datasheet.
La seconda parte è invece sempre la più ostica e foriera di errori; l'esperienza aiuta a scrivere la sequenza di inizializzazione abbastanza facilmente; in fondo la 'filosofia' dei controller è sempre molto simile.
Peccato che ci sia sempre quella parte misteriosa che riguarda i registri per il controllo delle alimentazioni, dei formati delle frame e del controllo della gamma colori, assolutamente sconosciuti (per me) e senza il benchè minimo aiuto da parte del datasheet.
Per l'ILI9481 c'è un registro con 12 parametri da fornire per la Gamma Correction senza una riga di indicazione su quali valori devono essere forniti.
Qui diventa indispensabile la ricerca in rete: misteriosamente qualcuno ha queste informazioni (spesso anche in contrasto tra loro); si copiano 2 o 3 esempi per recuperare i parametri che successivamente verrano provati.
A volte vengono citati registri non definiti nel DS o con codici diversi; in questo caso salto l'istruzione.
Santa Internet, questo è il solo aiuto concreto che cerco in rete e fortunatamente finora l'ho sempre trovato.
La regola del buon senso dice di non toccare questi registri finchè non si sia avuta una qualche risposta significativa dal display; male che vada il risultato in termini di colori e posizioni sarà caotico, ma questo si può sistemare dopo. L'importante ora è dare vita allo schermo.
Il fatto che rende frustrante scrivere un driver è che in presenza anche di un solo errore non si ha la benchè minima risposta e non esistono strumenti diagnostici (se non forse un'enorme pazienza) per capire perchè accidenti il maledetto display non fa qualcosa. Se poi di errori ce n'è più di uno, diventa un incubo, come nel mio caso.


Cronaca

  1. Ho scritto il codice, ho connesso fisicamente il modulo alla scheda di sviluppo e ho dato l'alimentazione. Niente.
    Si accendono i led della backlight e lo schermo è di un brutto bianco lattiginoso, senza segni evidenti di vita.
    Incomincia il solito triplo check delle alimentazioni e delle connessioni fisiche: tutto regolare.
    Passiamo al codice.

    Ovviamente ci si concentra subito sulle 3 procedure sopra dette, ovvero: scrivi_comando, scrivi_dato, inizializza. Controllo attentamente (!!!... vedi parte 2) questa parte: è sicuramente tutto a posto.
    Il pericolo in questi casi è dato dalla stanchezza (occhi e mentale) che dopo un pò subentra e spinge a fare prove sempre più assurde. Il rischio reale è di introdurre un paio di errori in più invece di risolverne uno.
    Dopo svariate prove e tanto tempo, decido di cominciare dall'inizio, ovvero dal file di configurazione dell'interfaccia. Poche righe e mi cade l'occhio (e anche qualcos'altro) nel vedere che due dei segnali di controllo sono stati assegnati allo stesso pin fisico... (BIP!...moccoli).
    Prima mi prendo a schiaffi, poi mi complimento con me stesso per aver risolto così velocemente il problema. Correggo un 2 in un 3 et voila, problema risolto (???!!!!???).
    Non è vero: non è cambiato nulla; ho ancora lo schermo lattiginoso che mi guarda!
    Metto da parte tutto per la seconda parte.

  2. Fresco e riposato, riprendo il codice, tornando sulle 3 funzioni critiche già rilette e analizzate decine di volte.
    Ma perchè non volete funzionare ?
    In fondo si tratta di attivare il CS, mettere il dato sull'interfaccia e dare un impulso sul pin Write.
    Per la scrittura di un dato il pin DATA va a 1, mentro per un comando il pin va a 1 (a 1 ????); ma sei ceccato?
    deve andare a 0, accidenti a me #!§#!...moccoli
    Avrò letto queste 6 righe di codice almeno una ventina di volte, ma ovviamente l'occhio di rifiuta di vedere queste castronerie. Finito di prendermi ancora a sberle, e anche a pedate questa volta, mi stringo la mano.
    Due stupidate così banali non le avevo ancora fatte finora, ma ora è tutto a posto.

    In effetti, ora il display ha smesso di fissarmi come una cernia lessa e mi concede un bel sfondo nero con qualche sprazzo di colore. Daccordo, la posizione dei quadrati di prova e il loro colore non sono proprio giusti, ma per questo c'è spazio di miglioramento. Ora si tratta di completare l'opera con la programmazione corretta di qualche registro e passare alla verifica delle funzioni grafiche prese dalla precedente libreria. Semplificando un pò, diciamo che con qualche colpetto qua e là tutte le funzioni funzionano (altrimenti che funzioni sarebbero?).
    Però (c'è sempre un però) quei colori li non mi piacciono per niente. Dov'è il blu?
    Ho solo delle belle tonalità che vanno da verde al rosso, passando per il giallo, ma niente azzurri e viola.
    E qui viene il bello.

  3. Può essere un problema HW o uno SW di qualche maledetto registro (il codice è sicuramente corretto).
    L'HW non è: c'è un bit in un registro che permette di scambiare i bit del blu col rosso (chissa a cosa serve?).
    Se lo attivo, il mio bel display ha dei magnifici blue e azzurri, senza però traccia dei rossi.
    Quindi devo trovare il maledetto registro che mi crea il problema; il datasheet ha 'solo' un centinaio di pagine ed è una spiritosa, chiara e fresca lettura serale estiva.
    Scrivo anche un programmino in Visual Basic per parlare al PIC e dagli in pasto codici e valori dei registri 'on the fly'.
    Non cambia nulla. Vuoi vedere che che c'è, altissimamente improbabile, un erore nel codice?
    C'è (--- ...ho finito i moccoli), e di una stupidità mostruosa, oltre che subdola.
    Per inviare il valore di un colore a 16bit devo fare 2 scritture sulla porta; uno per il byte alto e uno per quello basso.
    Per il basso ho definito di usare il dato da 16 bit mascherato con 0xFF (oltretutto è del tutto inutile perchè viene un po difficile scrivere 16 bit su una porta da 8 bit).
    Peccato che il codice scritto è stato: dataport = valore && 0xff;
    NOTARE BENE IL '&&' INVECE DI '&'
    In pratica, invece di mascherare valore con 255 ho fatto l'AND logico tra valore e 255; il risultato può essere solo 0 o 1, quindi tutti i miei brevi bit del byte basso scomparivano.
    Il byte basso contiene TUTTO il valore del blu e una parte del verde. Scrivendo 0 o 1 mi perdevo tutto.

Questo insegna tante cose:

  1. un carattere errato può causare il blocco o malfunzionamenti seri di tutto un programma.
  2. se è un blocco, è più facile trovare il baco, ma se è un malfunzionamento che si verifica solo in alcuni casi, è una rogna.
  3. la vista perfetta, come nel mio caso, l'età fisiologica e le tarde ore serali, le uniche disponibili per questi lavori, introducono inevitabilmente questi problemucci.
  4. MAI DARE PER SCONTATO DI AVER SCRITTO LA COSA GIUSTA

Anche questa comunque è andata ed ora ho il mio bravo driver per l'ILI9481; non mi resta che trovarne un uso adeguato.
Alla prossima



Codice del Driver

/* ============================================================
* Oggetto:		Driver per modulo 3.5" TFT
* Controller:	ILI9481 - risoluzione 480x320 pixel - 64K colori
* CPU:				18F46K22 @ 64MHz
* Modulo:			Funzioni driver e primitive grafiche
* Autore:			Alpha Orionis
* Contatti:		www.boxidee.it - idee@boxidee.it
* Versione:		1.1
* Creato:			5 Luglio 2016
* ============================================================ */

Il codice è in linguaggio C, realizzato con XC8 di Microchip in ambiente MPLAB-X.
NOTA BENE: quello che segue è il solo codice del driver, con le funzioni di accesso e comunicazione a basso livello e le principali primitive grafiche.
A parte il programma applicativo vero e proprio, non è qui presentato l'altro modulo fondamentale per la gestione del testo (incluse le tabelle delle Font) e per l'eventuale comunicazione con il mondo esterno, realizzata con una porta seriale a 115K.

Il sorgente è liberamente disponibile; nel caso lo usiate sarebbe cosa gradita un piccola citazione da qualche parte del sottoscritto, non fosse altro per la fatica fatta a tradurre dal Cino-Inglese.
Grazie


Scarica il sorgente del Driver ILI9481

P.S. nel mio codice sono presenti 3 routine grafiche che ho a mia volta trovato in Internet, e sono dedicate alla parte matematica sulla quale non mi trovo assolutamente a mio agio. Purtroppo non ho più i riferimenti sull'autore, altrimenti l'avrei di certo ricordato nel codice.



  ILI9481 Driver

What follows are just few brief notes on the driver I developed for the ILI9481 controller.
The module, bougth for very few dollars on EBay fron China, is engineered to be used as a shield for the Arduino UNO.

The main features are:

  • Size: 3.5": Resolution: 480x320 pixels: Colors: max 256K (64K used here)
  • SD card reader (not used here): no Touch Screen
  • 8 bit Parallel port + 5 command pins
  • Power: 5V with on-board 3.3V LDO regulator (for the SD)
  • Back light with 6 leds (no way to control them)

On the board (as you can see in a picture on the right) there are two rows of contacts: a row is assigned to the interface: (8 bits parallel port + 4 bits for the SPI port to communicate with the SD reader), while the second is used for the 5 control signals (Reset, DCX, CS, Write and Read) and the power (+5V, +3.3V [not used] and Ground).

The driver is intended for any Microchip 28 pins MCU of the 18F family, with at least 16K of EPROM; I used a 18F46K22 just because it is part of my test bed. It can set to operate at any clock speed (I used it at 64MHz).
The driver was develop with XC8 under MPLAB-X; what is not included here is the module for Text and Fonts management; possibly I could add it in the future.
You can freely download and use the driver from the above link. I would appreciate a citation in your software or a post card !
I do not assure that it is perfect, but it works!




Modulo TFT 3.5'' con ILI9481





Driver per il controller ILI9341

Grazioso modulo con display da 2.2", piccolo ma per questo con un'ottima definizione visti i 320x240 pixel con 64K colori.
L'interfaccia è molto semplice in quanto richiede solo 8 pin di collegamento; la limitazione principale è data dall'interfaccia SPI a 8 bit, cosa che riduce considerevolmente la velocità di trasferimento dei dati.
Il modulo è dotato del consueto connettore per schede SD, non utilizzato dal codice.



Scarica il sorgente del Driver ILI9341



Display 2.2'' con ILI9341





Driver per il controller SSD1289

Grazioso modulo con display da 2.2", piccolo ma per questo con un'ottima definizione visti i 320x240 pixel con 64K colori.
L'interfaccia è molto semplice in quanto richiede solo 8 pin di collegamento; la limitazione principale è data dall'interfaccia SPI a 8 bit, cosa che riduce considerevolmente la velocità di trasferimento dei dati.
Il modulo è dotato del consueto connettore per schede SD, non utilizzato dal codice.



Scarica il sorgente del Driver SSD1289



TFT 3.2'' 320x240 con SSD1289



ì