Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 13:25 11 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : CPLD TFT

Author Message
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 05:50am 23 Jul 2016
Copy link to clipboard 
Print this post

Will there be support for CPLD TFT LCD's?
Or is it possible to add support using a CFunction or something else?

They are superior to the SDD1963 and have 8 page memory on them
They "look" to have a similar pinout.
[quote]
7 inch TFT LCD Display Module
Using CPLD + SDRAM drive RGB interface display(far more superior than SSD1963 and RA8875)
8080 timing 16-bit parallel bus interface
Resolution 800 x 480
16M color display
Integrated 8 memory (can be used as extended memory when rest)
Background write data
No need to initialize
Support 51, AVR, STM32 and other types SCM drive directly
Provides a series of practical features when convert between bus and RGB interface

Interface Definition:

GND: Ground
3.3V: Positive power supply 3.3V
NC: Empty
RS: data / command switch
WR: Write Data Clock
RD: Read Data Clock
DB8-DB15: Upper 8-Bit Data Bus
CS: Chip Select
F_CS: FLASH Chip Select (module aside FLASH chip W25X16, default is not affixed to pieces, do reserve purposes)
REST: Reset (reset operation procedure: pull low, sustained 8ms; then pull high, sustained 8ms)
5V: backlight power supply 5V input
LED_A: backlight control (factory default backlight is controlled by program,0-16 Adjustable backlight brightness, without LED_A control, if required by the LED_A manual control on the module Backlight Control Department to modify resistor pad jumpers can be changed manually LED_A control, manual control when, LED_A access high-back light, then lower the backlight off, the PWM signal is adjustable brightness)
DB0-DB7: Lower 8-bit data bus
Touch controller (XPT2046) interface:
T_CLK: Clock
T_CS: Chip Select
T_DIN: Data Entry (ie MOSI)
T_DO: Data Out (ie MISO)
T_IRQ: Data Interrupt (usually high, touch low)
SD card interface:
SD_DO: MISO
SD_CLK: Clock
SD_DIN: MOSI
SD_CS: Chip Select
[/quote]

Edited by lew247 2016-07-24
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 03:17am 28 Jul 2016
Copy link to clipboard 
Print this post

Found a video of the LCD working
it loads full page pictures practically instantly
Video HERE
The one shown is programmed in Bascom
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10570
Posted: 04:10am 28 Jul 2016
Copy link to clipboard 
Print this post

  Quote  it loads full page pictures practically instantly


No it doesn't. It switches between pre-loaded images on specific pages very quickly. Loading is dependent on the SD card speed (or wherever else the pics come from).

The unit uses a 16-bit bus which isn't ideal with the Micromite as there isn't a a 16-bit port which doesn't conflict with various critical special function pins (the one thing I disagree with Geoff about in the way he allocated pins on the MM+). So the display won't be very easy to drive very fast. Also, note that it appears to be only RGB565 whereas the SSD1963 is RGB888.

The display is very nice and a loadable driver is not too difficult but it is too expensive for just playing. Also note that the GUI controls on the MM+ wouldn't work across multiple pages as there is no way of telling them which page they are on.
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 07:30am 28 Jul 2016
Copy link to clipboard 
Print this post

That's a shame, I thought it might use the same pinout as the SSD1963, they look almost identical.
It would have been great if it had been possible.
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 09:27am 06 Apr 2018
Copy link to clipboard 
Print this post

I know this is an old topic, but I am new here

I would like to use my existing 7" CPLD display with my latest acquisition Micromite Extreme MMX144, which means writing a driver.
Since I am totally New to MMBasic I have no idea where to start. I understand the initialisation is very simple unlike the SSD1963.
Are the CFunctions like Write_Cmd, Write_Data, and Write_Com_Data for 16 bit available to
MMBasic users? If so how do I call them?
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10570
Posted: 12:41pm 06 Apr 2018
Copy link to clipboard 
Print this post

  Quote  Since I am totally New to MMBasic I have no idea where to start.


Best place is to write a user driver in Basic see the file "User Display Driver.txt" in the Micromite distribution from Geoff and this thread . Once this is working you can then port to C. Best start for that is to use one of my drivers as a template.

I've attached a recent driver you can use as a template. It is SPI rather than parallel but this is just a matter of changing the HW I/F code

2018-04-06_224001_ILI9481Loadable.X.zip
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 10:23pm 10 Apr 2018
Copy link to clipboard 
Print this post

Thanks for your reply, I have got the display working of sorts, but only in basic which is as expected very slow. I don't have the skills to write my own CFuntions to speed it up as don't understand everything that is going on in your example.
I enclose my limited efforts at coding part of a basic driver which all work.



' testing driver for TFT 16bit CPLD Controller

setpin 139, dout 'reset
setpin 140, dout 'RS
setpin 141, dout 'WR
setpin 142, dout 'RD
setpin 143, dout 'CS
setpin 114, dout 'VL D0 on port J
setpin 115, dout
setpin 116, dout
setpin 117, dout
setpin 131, dout
setpin 132, dout
setpin 133, dout
setpin 134, dout ' D7 on port J
setpin 7, dout 'VH D8 on port J
setpin 8, dout
setpin 10, dout
setpin 27, dout
setpin 9, dout
setpin 28, dout
setpin 29, dout
setpin 30, dout ' D15 on port j
pin(139) = 1
pin(140) = 1
pin(141) = 1
pin(142) = 1
pin(143) = 1

' Program start
print "Start"
CPLD_Init
draw_FRectangle(0,0,360,260,&hc6F0) 'Clear a patch
'lcd_clear(&hffff) 'Clear to white

draw_FRectangle(80,80,350,250,&h001F) 'clear blue patch
draw_Rectangle(80,80,350,250,&hf800)
'draw_HLine(80,80,350,&hF800)
draw_FRectangle(150,100,300,200,&h07c0) 'draw box filled green
draw_Rectangle(150,100,300,200,&hf6f0)
draw_HLine(10,10,100,&h0000)
draw_VLine(10,10,100,&h0000)
draw_Rectangle(20,20,120,120,&hf800)
set_Pixel(100,100,&hffff)
' End of program so far

sub lcd_Writ_Bus(reg%)
port(114,4,131,4,7,2,10,1,27,1,9,1,28,3) = reg%
pin(141) = 0 'WR low
pin(141) = 1 'WR high
end sub

sub lcd_WR_DATA(da%)
pin(140) = 1
lcd_Writ_Bus(da%)
end sub

sub lcd_WR_REG(da%)
pin(140) = 0 'RS low
lcd_Writ_Bus(da%)
end sub

sub Address_set(x1%,y1%,x2%,y2%)
lcd_WR_REG(&h0002)
lcd_WR_DATA(y1%)
lcd_WR_REG(&h0003)
lcd_WR_DATA(x1%)
lcd_WR_REG(&h0006)
lcd_WR_DATA(y2%)
lcd_WR_REG(&h0007)
lcd_WR_DATA(x2%)
lcd_WR_REG(&h000F)
end sub

sub CPLD_Init
pin(139) = 0 'Reset low
pause 1
pin(139) = 1 'Reset high
pause 1
pin(143) = 0 'CS low
lcd_WR_REG(&h0001)
lcd_WR_DATA(&h000F)
pin(143) = 1 'CS low
print "Reset TFT"
end sub

sub lcd_Clear(Col%) 'clear screen
Address_set(0,0,799,479)
for i% = 0 to 799
for j% = 0 to 479
lcd_WR_DATA(Col%)
next j%
next i%
end sub

sub set_Pixel(x1,y1,col%)
Address_set(x1,y1,x1,y1)
lcd_WR_DATA(col%)
end sub

sub draw_HLine(x1,y1,x2,Col%)
Address_set(x1,y1,x2,y1)
for i% = x1 to x2
lcd_WR_DATA(Col%)
next i%
end sub

sub draw_VLine(x1,y1,y2,Col%)
Address_set(x1,y1,x1,y2)
for j% = y1 to y2
lcd_WR_DATA(Col%)
next j%
end sub

sub draw_Rectangle(x1,y1,x2,y2,Col%)
Address_set(x1,y1,x2,y2)
draw_HLine(x1,y1,x2,Col%)
draw_HLine(x1,y2,x2,Col%)
draw_VLine(x1,y1,y2,Col%)
draw_VLine(x2,y1,y2,Col%)
end sub

sub draw_FRectangle(x1,y1,x2,y2,Col%) 'filled rectangle
Address_set(x1,y1,x2,y2)
for i% = x1 to x2
for j% = y1 to y2
lcd_WR_DATA(Col%)
next j%
next i%
end sub

 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 09:12am 11 Apr 2018
Copy link to clipboard 
Print this post

Off topic but how do you put the CODE in a nice white box???
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2006
Posted: 09:26am 11 Apr 2018
Copy link to clipboard 
Print this post

At the top of the post reply page you will see a box marked 'Code' click on it and paste your code in the middle between the two sets of brackets.
Paul
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 09:43pm 11 Apr 2018
Copy link to clipboard 
Print this post

I have tried using my CPLD initialisation code with OPTION LCDPANEL USER, 800,480 setting as described in writing display drivers in basic, it semms to partially work.
CLS does not work and box and line only seem to work on black and white, is this normal?
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 10:13pm 25 May 2018
Copy link to clipboard 
Print this post

One for matherp I think.

I have finally got my CPLD driver working as a CFunction. All LCD drawing functions work including Text command including scale of font in the Text command, the gui commands seem to work OK if the Font command is set to 1. If I set Font 2 or higher it just clears the space where the command used would write to the screen.
Is there a special way the Font command hooks into the TFT drawing routines.
As expected everything works OK on a SSD1963 display with appropriate options set.
I have used the SSD1963_44 16 bit source with mods to achieve this.

Trevor
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 10:12am 26 May 2018
Copy link to clipboard 
Print this post

Following my previous post, here is the CFunction I have been working on to get my CPLD display working with a modified MM E100.



TREVOR



/*******************************************************************************
*
* Driver for CPLD Display written as CFunctions
*
* (c) Peter Mather 2015 with acknowledgements to Peter Carnegie & Geoff Graham
* was SSD1963_44 modified by Trevor Henshaw 21/May/2018
*
* This CFunction MUST be compiled with Optimization Level 1, -O1
* -O2,-O3,-Os will compile successfully, but generate exceptions at runtime.
*
* When Generating the CFunction, use MERGE CFunction mode, and name the CFunction
* CPLDinit
*
* Entry point is function long long main(long long *MyAddress,
* long long *RST,
* long long *orientation
* long long *size)
*
* V1.0 2015-07-21 Peter Mather
* 1.01 Change orientation codes to 1:landscape, 2:portrait, 3:rlandscape, 4:rportrait
* 1.02 Use fixed PortC pinout for maximum performance
* 1.03 Stripped routines for use as loadable LIBRARY
* 1.04 Conditional compilation for 44 and 64-pin parts
* 1.1 Convert to Nathan approach
* 1.11 Minor change for compatibility with touch and restricting page usage
* 1.2 Implement RGB565, add-in triangle drawing read/write
******************************************************************************/
#define Version 111 //Version 1.11
#include <stdarg.h>
#include <xc.h> // Required for SFR defs
#include <sys/attribs.h> // Required to use __longramfunc__
#include "CFunctions.h"
#define MX470 //Comment out for compilation for 44-pin part
#define pin100
#define RGB565
#define aport *(volatile unsigned int *)(0xbf886030) //latch registers
#define aclrport *(volatile unsigned int *)(0xbf886034) //latch registers
#define asetport *(volatile unsigned int *)(0xbf886038) //latch registers
#define aread *(volatile unsigned int *)(0xbf886020) //latch registers
#define atrisinv *(volatile unsigned int *)(0xbf88601C) //latch registers
#define bclrport *(volatile unsigned int *)(0xbf886134) //latch registers
#define bsetport *(volatile unsigned int *)(0xbf886138) //latch registers
#define cport *(volatile unsigned int *)(0xbf886230) //latch registers
#define cread *(volatile unsigned int *)(0xbf886220) //latch registers
#define ctrisinv *(volatile unsigned int *)(0xbf88621C) //latch registers
#define cclrport *(volatile unsigned int *)(0xbf886234) //latch registers
#define csetport *(volatile unsigned int *)(0xbf886238) //latch registers
#define eport *(volatile unsigned int *)(0xbf886430) //latch registers
#define eread *(volatile unsigned int *)(0xbf886420) //latch registers
#define etrisinv *(volatile unsigned int *)(0xbf88641C) //latch registers
#define eclrport *(volatile unsigned int *)(0xbf886434) //latch registers
#define esetport *(volatile unsigned int *)(0xbf886438) //latch registers
#define DEVID (*(volatile unsigned int *)0xBF80F220)
#define swap(a, b) {int t; t = a; a = b; b = t; }

//Offsets into the persistent RAM of variables
#ifdef MX470
#ifndef pin100
#define RS_Pin_No 27
#define WR_Pin_No 24
#define RS_Pin 0x1000
#define WR_Pin 0x0800
#define clrport bclrport
#define setport bsetport
#else
#define RS_Pin_No 18
#define WR_Pin_No 19
#define RS_Pin 0x100
#define WR_Pin 0x200
#define RD_Pin_No 6
#define clrport eclrport
#define setport esetport
#endif
#define port eport // Data port Db0-Db7
#define portH aport // Data port Db8-Db15
#define read eread
#define trisinv etrisinv
#define RSLo PinSetBit(RS_Pin_No,LATCLR);
#define RSHi PinSetBit(RS_Pin_No,LATSET);
#define WRLo {PinSetBit(WR_Pin_No,LATCLR);asm("NOP");}
#define WRHi {PinSetBit(WR_Pin_No,LATSET);asm("NOP");}
#else
#define RS_Pin_No 4
#define WR_Pin_No 5
#define RS_Pin 0x100
#define WR_Pin 0x200
#define clrport cclrport
#define setport csetport
#define port cport
#define read cread
#define trisinv ctrisinv
#define RSLo clrport=RS_Pin
#define RSHi setport=RS_Pin
#define WRLo clrport=WR_Pin
#define WRHi setport=WR_Pin
#endif
#define Both WR_Pin | RS_Pin
#define RDLo (*(volatile unsigned int *)RDclrport)=RDpin
#define RDHi (*(volatile unsigned int *)RDsetport)=RDpin
#define LANDSCAPE 1
#define PORTRAIT 2
#define RLANDSCAPE 3
#define RPORTRAIT 4

/*************************************************************************
*
* defines start/end coordinates for memory access from host to SSD1963
* also maps the start and end points to suit the orientation
*
* This function is a modified version of the function inside the MMBasic
* Interpreter for MM+ on 'MX470 chips
*
*
**************************************************************************/
void defineregion(long x, long y, long width,long height){ //Address Set
long x1=x,x2=x+width-1,y1=y,y2=y+height-1;
unsigned long xstart,xend,ystart,yend,Vertical,Horizontal;
RSLo;
if(HRes>VRes){
Vertical=VRes;
Horizontal=HRes;
}
else {
Vertical=HRes;
Horizontal=VRes;
}
if(Option->DISPLAY_ORIENTATION!=LANDSCAPE)goto isP;
xstart = x1;
xend = x2;
ystart = y1;
yend = y2 ; //Must be Landscape
goto setreg;
isP:
if(Option->DISPLAY_ORIENTATION!=PORTRAIT)goto isRL;
xstart = y1;
xend = y2;
ystart = (Vertical - 1) - x2;
yend = (Vertical - 1) - x1;
goto setreg;
isRL:
if(Option->DISPLAY_ORIENTATION!=RLANDSCAPE)goto isRP;
xstart = (Horizontal - 1) - x2;
xend = (Horizontal - 1) - x1;
ystart = (Vertical - 1) - y2;
yend = (Vertical - 1) - y1;
goto setreg;
isRP:
xstart = (Horizontal - 1) - y2;
xend = (Horizontal - 1) - y1;
ystart = x1;
yend = x2;
setreg:
// Address Set these are the registers used for setting screen work area
port=0x02; RSLo; WRLo; WRHi; // RS low
portH=(ystart>>8 ); RSHi;
port=(ystart & 0x00FF) | Both; WRLo; WRHi; // RS HIGH
port=0x03; RSLo; WRLo; WRHi; // RS low
portH=(xstart>>8 ); RSHi;
port=(xstart & 0x00FF) | Both; WRLo; WRHi; // RS HIGH
port=0x06; RSLo; WRLo; WRHi; // RS low
portH=(yend>>8 ); RSHi;
port=(yend & 0x00FF) | Both; WRLo; WRHi; // RS HIGH RSHi;
port=0x07; RSLo; WRLo; WRHi; // RS low
portH=(xend>>8 ); RSHi;
port=(xend & 0x00FF) | Both; WRLo; WRHi; // RS HIGH*/
port=0x0F; RSLo; WRLo; WRHi; // RS low
}

void DisplayPage(int pg){ // NOT implemented
if(pg > 7) {pg = 0;}
port=0x04; RSLo; WRLo; WRHi; // RS low
port=(pg & 0x00FF) | Both; RSHi; WRLo; WRHi; // RS HIGH*/
}

void WritePage(int pg){ // Not implemented
if(pg > 7) {pg = 0;}
port=0x05; RSLo; WRLo; WRHi; // RS low
port=(pg & 0x00FF) | Both; RSHi; WRLo; WRHi; // RS HIGH*/
}

/***********************************************************************************************
* Display the bitmap of a char on the TFT panel
*
* This function is NEVER called by MMBasic programs
*
* This is optimised for the
* x, y - the top left of the char
* width, height - size of the char's bitmap
* scale - how much to scale the bitmap
* fg, bg - foreground and background colour
* bitmap - pointer to the butmap
*
* This function is a modified version of the function inside the MMBasic Interpreter
* for MM+ on 'MX470 chips
***********************************************************************************************/
void DrawBitmap_CPLD(int x1, int y1, int width, int height, int scale, int fc, int bc, unsigned char *bitmap ){
long i, j, k, m, n;
unsigned int fhb, flb, bhb, blb, xtest, ytest;
unsigned char *p;
xtest=HRes;
ytest=VRes;
fhb = ((fc >> 16) & 0b11111000) | ((fc >> 13) & 0b00000111);
flb = ((fc >> 5) & 0b11100000) | ((fc >> 3) & 0b00011111);
bhb = ((bc >> 16) & 0b11111000) | ((bc >> 13) & 0b00000111);
blb = ((bc >> 5) & 0b11100000) | ((bc >> 3) & 0b00011111);
n=0;
defineregion(x1,y1,width*scale,height*scale);
RSHi;
for(i = 0; i < height; i++) { // step thru the font scan line by line
for(j = 0; j < scale; j++) { // repeat lines to scale the font
for(k = 0; k < width; k++) { // step through each bit in a scan line
for(m = 0; m < scale; m++) { // repeat pixels to scale in the x axis
if(x1 + k * scale + m >= 0 && x1 + k * scale + m < xtest && y1 + i * scale + j >= 0 && y1 + i * scale + j < ytest) { // if the coordinates are valid
if((bitmap[((i * width) + k)/8] >> (((height * width) - ((i * width) + k) - 1) %8)) & 1) {
portH = fhb;
port = (flb & 0xFF) | Both;
WRLo; WRHi;
} else {
// if(bc==1 && Option->LCD_CS!=0){
portH = bhb;
port = (blb & 0xFF) | Both;
WRLo; WRHi;
n+=2;
// }
}
}
}
}
}
}
// }
if(bc==1 && Option->LCD_CS!=0) FreeMemory(p);
}

/******************************************************************
*
* Called by MMBasic Interpreter to draw a rectangle
* on the CPLD panel
*
* This function is NEVER called by MMBasic programs
*
*
*****************************************************************/

void DrawRectangle_CPLD(int x1, int y1, int x2, int y2, int fc){
int t,j;
long width, height;
unsigned long i,ch,cl;
// make sure the coordinates are kept within the display area
if(x2 <= x1) { t = x1; x1 = x2; x2 = t; }
if(y2 <= y1) { t = y1; y1 = y2; y2 = t; }
if(x1 < 0) x1 = 0; if(x1 >= HRes) x1 = HRes - 1;
if(x2 < 0) x2 = 0; if(x2 >= HRes) x2 = HRes - 1;
if(y1 < 0) y1 = 0; if(y1 >= VRes) y1 = VRes - 1;
if(y2 < 0) y2 = 0; if(y2 >= VRes) y2 = VRes - 1;
width=x2-x1+1;
height=y2-y1+1;
i=width*height;
//Convert fc to RGB565
ch = ((fc >> 16) & 0b11111000) | ((fc >> 13) & 0b00000111);
cl = ((fc >> 5) & 0b11100000) | ((fc >> 3) & 0b00011111);
//ch = (((fc>>19)&0x1F)<<11)|(((fc>>10)&0x3F)<<6)|(((fc>>3)&0x1F));
defineregion(x1,y1,width,height);
RSHi;
for(i = 0; i < width; i++){
for(j = 0; j < height; j++){
portH = ch;
port = (cl & 0x00FF) | Both;
WRLo; WRHi;
}
}
}
int ReadRectangle(int x1, int y1, int width, int height, int pos, char *p ){
int j,RDpin, RDsetport, RDclrport;
RDpin=1<<GetPinBit(Option->LCD_CS);
RDsetport=(unsigned int)GetPortAddr(Option->LCD_CS,LATSET);
RDclrport=(unsigned int)GetPortAddr(Option->LCD_CS,LATCLR);

#ifdef RGB565
j=width*height*2+pos;
#else
j=width*height*3+pos;
#endif
defineregion(x1,y1,width,height);
#ifdef MX470
#ifndef pin100
RSLo;
#endif
#endif
port=0x22E ; WRLo; WRHi; // RS low
#ifdef MX470
#ifndef pin100
RSHi;
#endif
#endif
trisinv=0xFF; //set pins to read
#ifdef RGB565
atrisinv=0xFF;
#endif
do { //read in the screen area to be overlayed
#ifndef RGB565
RDLo;
asm("NOP");asm("NOP");asm("NOP");
RDHi;
p[pos++]=(read & 0xFF);
RDLo;
asm("NOP");asm("NOP");asm("NOP");
RDHi;
p[pos++]=(read & 0xFF);
RDLo;
asm("NOP");asm("NOP");asm("NOP");
RDHi;
p[pos++]=(read & 0xFF);
#else
RDLo;
asm("NOP");asm("NOP");asm("NOP");
RDHi;
p[pos++]=(read & 0xFF);
p[pos++]=(aread & 0xFF);
#endif
} while(pos<j);
trisinv=0xFF; //set pins to write
#ifdef RGB565
atrisinv=0xFF;
#endif


}
int RestoreRectangle(int x1, int y1, int width, int height, int pos, char p[]){
int i;
defineregion(x1,y1,width,height);
i=width*height;
#ifdef MX470
#ifndef pin100
RSLo;
#endif
#endif
#ifdef RGB565
aclrport=0xFF;
#endif
port=0x22C ; WRLo; WRHi; // RS low
#ifdef MX470
#ifndef pin100
RSHi;
#endif
#endif
#ifdef RGB565
while (i--) {
port=p[pos++] | Both; asetport=p[pos]; aclrport=(p[pos++]^0xFF);
WRLo; WRHi;
}
#else
while(i--){
port=p[pos++] | Both; WRLo; WRHi;
port=p[pos++] | Both; WRLo; WRHi;
port=p[pos++] | Both; WRLo; WRHi;
}
#endif
return pos;
}
long triangles(int mode, int buffpos, char *buff, long col, long x0, long y0, long x1, long y1,long x2, long y2) {//Cfunction
long a, b, y, last;
long dx01, dy01, dx02, dy02, dx12, dy12, sa, sb;

if (y0>y1) {
swap(y0, y1);
swap(x0, x1);
}
if (y1>y2) {
swap(y2, y1);
swap(x2, x1);
}
if (y0>y1) {
swap(y0, y1);
swap(x0, x1);
}
if(y0==y2) { // Handle awkward all-on-same-line case as its own thing
a=x0;
b=x0;
if(x1<a) {
a=x1;
} else {
if(x1>b) b=x1;
}
if(x2<a) {
a=x2;
} else {
if(x2>b) b=x2;
}
if(mode==0){
buffpos=ReadRectangle(a,y0,1,b-a+1,buffpos,buff);
} else if(mode==1) {
buffpos=RestoreRectangle(a,y0,1,b-a+1,buffpos,buff);
} else {
DrawRectangle_CPLD(a,y0,a,b-a+y0,col);
}
} else {
dx01=x1-x0; dy01=y1-y0; dx02=x2-x0; dy02=y2-y0; dx12=x2-x1; dy12=y2-y1; sa=0; sb=0;
if(y1==y2) {
last=y1; //Include y1 scanline
} else {
last=y1-1; // Skip it
}
for (y=y0;y<=last;y++){
a=x0+sa / dy01;
b=x0+sb / dy02;
sa=sa+dx01;
sb=sb+dx02;
a=x0+(x1-x0) * (y-y0) / (y1-y0);
b=x0+(x2-x0) * (y-y0) / (y2-y0);
if(a>b)swap(a,b);
if(mode==0){
buffpos=ReadRectangle(a,y,b-a+1,1,buffpos,buff);
} else if(mode==1) {
buffpos=RestoreRectangle(a,y,b-a+1,1,buffpos,buff);
} else {
DrawRectangle_CPLD(a,y,b,y,col);
}
}
sa=dx12 * (y-y1);
sb=dx02 * (y-y0);
while (y<=y2){
a=x1+sa / dy12;
b=x0+sb / dy02;
sa=sa+dx12;
sb=sb+dx02;
a=x1+(x2-x1) * (y-y1) / (y2-y1);
b=x0+(x2-x0) * (y-y0) / (y2-y0);
if(a>b) swap(a,b);
if(mode==0){
buffpos=ReadRectangle(a,y,b-a+1,1,buffpos,buff);
} else if(mode==1) {
buffpos=RestoreRectangle(a,y,b-a+1,1,buffpos,buff);
} else {
DrawRectangle_CPLD(a,y,b,y,col);
}
y=y+1;
}
}

return buffpos;
}

__attribute__((noinline)) void getFPC(void *a, void *b, volatile unsigned int *c)
{
*c = (unsigned int) (__builtin_return_address (0) - (b -a)) ;
}
void pstring(const char *s){
volatile unsigned int libAddr ;
getFPC(NULL,&&getFPCLab,&libAddr) ; // warning can be ignored, stupid editor
getFPCLab: { }
unsigned char * testData = (unsigned char *)((void *)s + libAddr );
MMPrintString(testData);
}

/*******************************************************************************
*
* CPLDinit : Initialise the CFunction Driver Sub-System
*
* Function called to initialise the driver SubSystem
*
* CPLDinit is ALWAYS called from an MMBasic program
* On exit, vectors DrawRectangleVector, and DrawBitmapVector will
* be set to point to the CFunctions DrawRectangle_SSD1963 and
* DrawBitmap_SSD1963 respectively
*
* Input Arguments
* MyAddress: The Address of the CFunction, use PEEK(CFUNADDR CPLDinit)
* RST: The pin connected to the Reset input on the display
* orientation:
* is 0 for Portrait orientation, 1 for reverse portrait, 2 for landscape, 3 for reverse landscape
* size: The display size 4, 5, or 7"
*
* Exit Value Version
*
* Note, For added performance, it may be desirable to create a
* separate WriteData function which doen't asser/de-asser CS for each byte and
* instead use block CSLo/CSHi around data transfers. These "block" CSLo/CSHi
* statements have been left in the code as comments.
*
******************************************************************************/
//CFunction CPLDinit
long long main(char *orientation, unsigned char *p1, long long p2[], long long p3[], long long p4[], long long p5[], long long p6[],long long p7[], long long p8[]){
int t,HorizontalRes,VerticalRes;
unsigned int p[17];
int i,j,c;
if(Option->LCD_CS){
PinSetBit(Option->LCD_CS, LATSET);
}
volatile unsigned int libAddr ;
getFPC(NULL,&&getFPCLab,&libAddr) ; // warning can be ignored, stupid editor
getFPCLab: { }

if(*orientation>=0 && *orientation<=4){
Option->DISPLAY_ORIENTATION=*orientation;
Option->LCD_CS=0;
#ifndef MX470
if(p2[0])Option->LCD_CS=p2[0];
#else
if(*p1)Option->LCD_CS=*p1;
#endif
Option->DISPLAY_ORIENTATION=*orientation;
Option->LCD_CD=*p2; //save the display size as the display type for use in the driver routines

#ifdef MX470
#ifndef pin100
Option->LCD_Reset=28;
p[0]=60;
p[1]=61;
p[2]=62;
p[3]=63;
p[4]=64;
p[5]=1;
p[6]=2;
p[7]=3;
#else
Option->LCD_Reset=42;
p[0]=93;
p[1]=94;
p[2]=98;
p[3]=99;
p[4]=100;
p[5]=3;
p[6]=4;
p[7]=5;
p[8]=17;
p[9]=38;
p[10]=58;
p[11]=59;
p[12]=60;
p[13]=61;
p[14]=91;
p[15]=92;
p[16]=48;
#endif

#else
Option->LCD_Reset=*p1;
p[0]=25;
p[1]=26;
p[2]=27;
p[3]=36;
p[4]=37;
p[5]=38;
p[6]=2;
p[7]=3;
#endif
for(j=0;j<17;j++){
ExtCfg(p[j],EXT_DIG_OUT,0);ExtCfg(p[j],EXT_BOOT_RESERVED,0);
PinSetBit(p[j],LATCLR);
}
//Control Signals
ExtCfg(RS_Pin_No,EXT_DIG_OUT,0);ExtCfg(RS_Pin_No,EXT_BOOT_RESERVED,0);
RSHi;

ExtCfg(WR_Pin_No,EXT_DIG_OUT,0);ExtCfg(WR_Pin_No,EXT_BOOT_RESERVED,0);
WRHi;

ExtCfg(Option->LCD_Reset,EXT_DIG_OUT,0);ExtCfg(Option->LCD_Reset,EXT_BOOT_RESERVED,0);
PinSetBit(Option->LCD_Reset, LATSET);

if(Option->LCD_CS){
ExtCfg(Option->LCD_CS, EXT_DIG_OUT,0);
ExtCfg(Option->LCD_CS, EXT_BOOT_RESERVED,0);
PinSetBit(Option->LCD_CS, LATSET);
}

//Save DisplayMetrics
if(Option->LCD_CD<5){
HorizontalRes=480;
// if(Option->DISPLAY_ORIENTATION==1) VerticalRes=272*3; //3 frame buffers
/*else*/ VerticalRes=272;
} else {
HorizontalRes=800;
VerticalRes=480;
HRes = 800;
VRes = 480;
}

//Reset the CPLD
PinSetBit(Option->LCD_Reset,LATSET);
uSec(10000);
PinSetBit(Option->LCD_Reset,LATCLR);
uSec(10000);
PinSetBit(Option->LCD_Reset,LATSET);
uSec(10000);
port=0x0F; RSLo; WRLo; WRHi; // RS low
port=0x01; RSLo; WRLo; WRHi; // RS low
port=0x10; RSHi; // RS high
portH=0x00 | Both; WRLo; WRHi; // RS high
port=0x0F; RSLo; WRLo; WRHi;// RS low
PinSetBit(p[16],LATSET); //Turn on backlight

if(Option->DISPLAY_ORIENTATION&1){
HRes=HorizontalRes;
VRes=VerticalRes;
} else {
VRes=HorizontalRes;
HRes=VerticalRes;
}
//Save the current values of the Vectors

//Set the DrawRectangle vector to point to our function
DrawRectangleVector= (unsigned int)&DrawRectangle_CPLD + libAddr;

//Set the DrawBitmap vector to point to our function
DrawBitmapVector=(unsigned int)&DrawBitmap_CPLD + libAddr;
// DisplayPageVector=(unsigned int)&DisplayPage +libAddr;
// WritePageVector=(unsigned int)&WritePage +libAddr;

//Clear Screen to Black
if(Option->LCD_CD<5) {
DrawRectangle(0,0,HRes-1,VRes*3-1,0x000000);
} else {
DrawRectangle(0,0,HRes-1,VRes-1,0x000000);
}
#ifdef MX470
#ifndef pin100
static const char startup[]="SSD1963_64 driver loaded\r\n";
#else
static const char startup[]="CPLD_100 driver loaded\r\n";
#endif
#else
static const char startup[]="SSD1963_44 driver loaded\r\n";
#endif
pstring(startup);
}
} // . EVERYTHING BELOW COMMENTED OUT
/* else if(*orientation==5){
int num=p1[0],a=1;
unsigned char ch,cm;
if(p2!=NULL){
num=*p2-1;
a=0;
}
#ifdef RGB565
while (a<num) {
// port=p1[a++] | Both; asetport=p1[a]; aclrport=(p1[a++]^0xFF);
ch=p1[a++] & 0b11111000;
ch|=p1[a]>>5;
cm=(p1[a++]<<3) & 0b11100000;
cm|=(p1[a++]>>3);
port=cm | Both; asetport=ch; aclrport=(ch^0xFF);
WRLo; WRHi;
}
#else
while(a<num){
port=p1[a++] | Both; WRLo; WRHi;
port=p1[a++] | Both; WRLo; WRHi;
port=p1[a++] | Both; WRLo; WRHi;
}
#endif
} else if(*orientation==6){
return ReadRectangle(*p2, *p3, *p4, *p5, *p6, p1 );
} else if(*orientation==7){
return RestoreRectangle(p2[0], p3[0], p4[0], p5[0], p6[0], p1 );
} else if(*orientation==8){
defineregion(*p1, *p2, *p3, *p4);
#ifdef MX470
#ifndef pin100
RSLo;
#endif
#endif
#ifdef RGB565
aclrport=0xFF;
#endif
port=0x22C ; WRLo; WRHi; // RS low
#ifdef MX470
#ifndef pin100
RSHi;
#endif
#endif
return 8;
} else if(*orientation==9){
if(Option->DISPLAY_ORIENTATION==1){
VRes=272*3;
j=(*p1-1) * 272;
write_command_data(0x37,2,j>>8,j&0xFF);
}
}
#ifdef RGB565
else if(*orientation==10){
int num=p1[0],a=1,astore;
astore=aport & 0xFF00;
if(p2!=NULL){
num=*p2-1;
a=0;
}
while (a<num) {
aport=p1[a++]|astore;
port=p1[a++] | Both;
WRLo; WRHi;
}
#endif
} else { //must be triangles
int count=*orientation & 0x7F;
int i=0,j,buffpos=0;
while(i<count && p2<0){ //repeat for any restores
buffpos=triangles(1,buffpos,p1,p2,p3,p4,p5,p6,p7,p8);
i++;
}
buffpos=0;
j=i;
while(i<count && p2>=0){ //repeat for any store and write commands
buffpos=triangles(0,buffpos,p1,p2,p3,p4,p5,p6,p7,p8);
i++;
}
i=j;
while(i<count && p2>=0){ //repeat for any store and write commands
buffpos=triangles(2,buffpos,p1,p2,p3,p4,p5,p6,p7,p8);
i++;
}
return buffpos>>3;

}*/
//}
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10570
Posted: 09:08am 27 May 2018
Copy link to clipboard 
Print this post

  Quote  Is there a special way the Font command hooks into the TFT drawing routines.


No: do different fonts work with the TEXT command?

Please confirm the connections you are using on the E100
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 09:37am 27 May 2018
Copy link to clipboard 
Print this post

Hi Peter,
Just to be clear I am using a spare E100 board wired up for 16 bit.

The low data port is PortE, pins 93,94,98,99,100,3,4,5 that is Db0-7

High data port is PortA, pins 17,38,58,59,60,61,91,92 that is Db8-15

RS pin 18, WR pin 19, RD pin 6, 42 pin reset and 48 LedA.

CS is permanently grounded.

I haven't tested every command, but basic graphics routines seem to work as expected.
When I tried the Pump example screen it all went wrong, setting the GUI font to greater than 1 was the main cause. I haven't tried running that demo on the SSD1963_44 to see if there is same problem with the loadable.(will try that next).


Trevor
Edited by TrevorH 2018-05-28
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 01:01pm 27 May 2018
Copy link to clipboard 
Print this post

I have just tried seven segment and dot matrix fonts as given in firmware pack with the Text command and they work ok even when scaled up.

TrevorEdited by TrevorH 2018-05-28
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 04:10pm 31 May 2018
Copy link to clipboard 
Print this post

I have now tried the Pump graphics screen example on the SSD1963_44 loadable driver
and it works OK.
Using my CPLD screen and the modified driver works with the Pump example if I change all the FONT commands to "FONT 1,2" instead of "FONT 2" & "FONT 3".

It does seem that no-one else is interested in what is going on here, maybe these screens are
not much liked by this group, but they are fully supported in the Arduino world. I am trying to move on from that!

Trevor
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 02:58pm 04 Jun 2018
Copy link to clipboard 
Print this post

One for matherp again,

I wish to setup a couple of calls to the CPLD driver, one to switch ram pages to write to and one to switch ram pages to display.
These calls need to be called from Basic.

The question is how do I create 2 routines to call from basic that give me access to protected ports and control pins within the driver and how do I call them.

I suspect it is not that difficult but I don't know where to start.

PS any thoughts on the Font thing?

TrevorEdited by TrevorH 2018-06-06
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10570
Posted: 04:11pm 04 Jun 2018
Copy link to clipboard 
Print this post

  Quote  The question is how do I create 2 routines to call from basic that give me access to protected ports and control pins within the driver and how do I call them.


These need to be called from the same routine that sets up the driver. See the SSD1963 driver for how I have done it (code you have commented out).

  Quote  PS any thoughts on the Font thing?


Sorry - no idea. If different fonts are working using the "TEXT" command then the driver is working. The GUI commands call the same driver routines.
 
TrevorH
Senior Member

Joined: 06/04/2018
Location: United Kingdom
Posts: 145
Posted: 09:47am 05 Jun 2018
Copy link to clipboard 
Print this post

@matherp

Got it sorted! paged ram switching now working, by adding 2 parameters to the front of the queue,
one for display page and one for write page.

But, there always is a But, how do I trap if I miss one of the parameters. If I do, I get an exception and processor restart and CFunction reload. If I miss both I get syntax error.

On the Font thing, after looking at Geoff's source code I thought the GUI routines call "SpecialDraw..." routines that seems to built in, but I am guessing ????.


Trevor.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10570
Posted: 10:04am 05 Jun 2018
Copy link to clipboard 
Print this post

  Quote  But, there always is a But, how do I trap if I miss one of the parameters. If I do, I get an exception and processor restart and CFunction reload. If I miss both I get syntax error.

See tutorial 4 for how to implement error handling in a CFunction.

Then you need to check for parameters missing. I think (but not sure) you need to fully specify the CFunction call with the parameter list in Basic

e.g.

CFunction SGetStr(float, integer, integer) string


and then Basic will generate NULL parameters to the Cfunction for missing parameters

void myfunc(int *fred, int *bert){
if(bert==NULL)....
}


but you will need to test this.

  Quote  On the Font thing, after looking at Geoff's source code I thought the GUI routines call "SpecialDraw..." routines that seems to built in, but I am guessing ????.


Yes: but these all resolve into calls to DrawBitamp or Drawrectangle
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025