Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Microchip Graphics Library

Status
Not open for further replies.
Yep. Several different projects.
 
Could you point me to some examples? The examples from Microchip all use the PMP interface with the Solomon Systech SSD1926 image processor to establish an RGB interface.

The way I'm trying is with the SSD2119 controller directly using PMP (rather than RGB).
 
So you're trying to drive the pixel clock, hsync, vsync etc with the PMP? That isn't generally what you want to do. If you do get it to work, your graphics will be very slow and not very impressive. You'll have to constantly send the data out of the PMP without stopping else the LCD image will probably fade out. Generally, you'd want to go through PMP or some type of serial to a graphics controller and allow the graphics controller to handle the RGB interface. I'm not saying that it is impossible to do RGB with the PIC, just that it isn't going to be easy at all.

In any case, the library is setup such that the first thing you need to do is define PutPixel to have it place a single pixel on the display. Once you get that working, you're half way home.

There are a couple of projects on this page that may be useful: PIC24-Eval-RevC
 
  • Like
Reactions: 3v0
No, I'm trying to send data and instructions to the SSD2119 controller directly with the PMP using the Intel 8080 parallel interface. The SSD2119 controller is built into my crystal fontz CFAF320240F-T display.

The microchip demonstration board uses 18-bit parallel RGB, so the primitive layer demo (which i'm trying to learn from) would need to be modified or completely rewritten in order to use the library.

BTW, I'm using a prototyped 44-pin dsPIC33FJ128MC804 as my DSC. I have been able to get the display working using raw I/O functions to control the 8080 parallel interface (but not with the PMP, or the graphics library).
 
I think what you pretty much need to do is rewrite the SSD1926.c file and create your own for SSD2119.c. The remainder of the library can remain untouched. I've done this for 4 or 5 different graphics controllers now.

For instance, one of the displays I worked I used an S1D13743 external graphics chip. It required that you give it a X,Y coordinates for 4 corners of a box that you wanted to draw in before it'd let you draw a single pixel. For drawing one pixel, this was terribly inefficient but for drawing large areas of text or images, it was much better than x,y,data,x,y,data,x,y,data etc. This is what I changed my PutPixel function to:
Code:
void PutPixel(SHORT x, SHORT y)
{
    CS_LAT_BIT = 0;
    
    Write_GE_RegAddr( REG38_WINXSPOS0 );    
    Write_GE_RegData( (Uint8)x );                    // lower byte of x start
    Write_GE_RegData( (Uint8)(x>>8) );            // upper byte of x start
    Write_GE_RegData( (Uint8)y );                    // lower byte of y start
    Write_GE_RegData( (Uint8)(y>>8) );            // upper byte of y start
    Write_GE_RegData( (Uint8)x+1 );                // lower byte of x end
    Write_GE_RegData( (Uint8)((x+1)>>8) );        // upper byte of x end
    Write_GE_RegData( (Uint8)y+1 );                // lower byte of y end
    Write_GE_RegData( (Uint8)((y+1)>>8) );        // upper byte of y end
    
    Write_GE_SRAMData( _color.Val );   
    
    CS_LAT_BIT = 1;
}

I don't remember how the default "Bar" function is, but if it repeatedly calls PutPixel to draw a bar, then we'd be there all day. I changed it to
Code:
void Bar(SHORT left, SHORT top, SHORT right, SHORT bottom)
{
Uint16 x, y;
Uint32 nbr_of_pixels;

	x = left;
	y = top;
	
	nbr_of_pixels = (right - left + 1) * (bottom - top + 1);

	CS_LAT_BIT = 0;
	
	// Set register access to window X start position and write the position
	// data.  The register access will autoincrement until it reaches the GRAM
	// data.  Once GRAM is reached, just output data for each pixel until all 
	// pixels have been written
	Write_GE_RegAddr( REG38_WINXSPOS0 );	
	Write_GE_RegData( (Uint8)left );					// lower byte of x start
	Write_GE_RegData( (Uint8)(left>>8) );			// upper byte of x start
	Write_GE_RegData( (Uint8)top );					// lower byte of y start
	Write_GE_RegData( (Uint8)(top>>8) );			// upper byte of y start
	Write_GE_RegData( (Uint8)right );				// lower byte of x end
	Write_GE_RegData( (Uint8)(right>>8) );			// upper byte of x end
	Write_GE_RegData( (Uint8)bottom );				// lower byte of y end
	Write_GE_RegData( (Uint8)(bottom>>8) );		// upper byte of y end
	
	
	while (nbr_of_pixels--)
	{
		Write_GE_SRAMData( _color.Val );
	}			
	
	CS_LAT_BIT = 1;
}

The driver I started with used an 8-bit PMP bus and I needed a 16-bit bus, so I further redefined SetIndex and WriteData as follows:
Code:
//#define SetIndex(index)  RS_LAT_BIT=0;PMDIN1=0;PMPWaitBusy();PMDIN1=index;PMPWaitBusy();
#define SetIndex(index)	RS_LAT_BIT=0; PMDIN1=index; PMPWaitBusy();

//#define WriteData(byte1,byte0) RS_LAT_BIT=1;PMDIN1=byte1;PMPWaitBusy();PMDIN1=byte0;PMPWaitBusy();
#define WriteData(byte1,byte0) RS_LAT_BIT=1;PMDIN1=(byte1<<8 | byte0); PMPWaitBusy();

Since I wanted to be able to change the orientation of my display easily, I also modified the SetAddress macro so I could select whether or not my display was upside down (it also changes the startup code automatically as well)
Code:
#if INVERT_DISPLAY
	#define SetAddress(addr2,addr1,addr0)  \
	SetIndex(0x20);WriteData(0,GetMaxX()-addr0);\
	SetIndex(0x21);WriteData(addr2,addr1);\
	SetIndex(0x22);
#else
	#define SetAddress(addr2,addr1,addr0)  \
	SetIndex(0x20);WriteData(0,addr0);\
	SetIndex(0x21);WriteData(addr2,addr1);\
	SetIndex(0x22);
#endif

I don't know if any of this is helpful at all though, I hope it is. There are several different drivers provided in the microchip graphics library, one of them may be helpful as well.
 
Thanks for the reply Noggin! The microchip graphics library supports the SSD2119 (the one I'm using) in the library now (in file drvTFT002.c).

I'm not quite sure if I've got the PMP set up correctly, or I may have an error on the circuit:

Circuit Diagram: (see attached)


Data and command functions:

Code:
void write_command(unsigned int command)
{
	CLR_CD;
	PMDIN1 = command;
}

void write_data(unsigned int data)
{
	SET_CD;
	PMDIN1 = data;
}

In Main:

Code:
// ---------------------------------------
//PMP setup
//---------------------------------------
PMMODE = 0; PMAEN = 0; PMCON = 0;

PMMODEbits.MODE   = 2;  // Intel 80 master interface
PMMODEbits.WAITB  = 0;
PMMODEbits.WAITM  = 0b0001;
PMMODEbits.WAITE  = 0;  
PMMODEbits.MODE16 = 0; // 8-bit Mode
PMCONbits.PTRDEN  = 1; // enable RD line
PMCONbits.PTWREN  = 1; // enable WR line
PMCONbits.WRSP    = 0; // Make WR active low
PMCONbits.RDSP    = 0; // Make RD active low
PMCONbits.CSF0	  = 0b10; // PMCS1 functions as chip select
//PMCONbits.CSF2    = 0b
PMCONbits.PMPEN   = 1; // enable PMP
//---------------------------------------


//---------------------------------------
//Configure for 39.92MhzMIPS using FRC w/PLL
//---------------------------------------
CLKDIVbits.PLLPRE = 1;     //7.37Mhz/3 = 2.457Mhz
PLLFBDbits.PLLDIV = 63;    //PLLDIV+2 = 65 = VCO out:159.683Mhz
CLKDIVbits.PLLPOST = 0;   //Fcy=((((Oscilator/PLLPRE)*(PLLDIV+2))/PLLPOST)/2)
                                                 //   =((((7.37Mhz/3)*(65))/2)/2) = 39.92Mhz
while(!OSCCONbits.LOCK); 
//---------------------------------------

Let me know what you think,

Thanks,
Michael
 

Attachments

  • TFT PMP.pdf
    40 KB · Views: 401
Last edited:
The first thing I'd do is make you redo the schematic ;) None of the signal names match but I suspect that they still connect (you should double check though). The chip select signal looks highly suspicious, more so than the rest. I would also control the chip select manually, set it low at the beginning of PutPixel, PutImage, Bar, etc type functions, then set it high at the end. Otherwise, I think chip select will get set and cleared around each byte that gets sent. That might be fine, I don't know because I've never tried it.

Another thing to spend some time on is write a function (if one isn't available) to read back registers after you've written them. Make sure they match, that'll let you know if data is getting through and set properly.

If you have access to one, an oscilloscope to verify every signal would be very helpful.
 
Last edited:
OK, you're right the schematic was confusing. It has been redone, and is attached. I'm now controlling the chip select with RB3 (port i/o). I am able to get the screen initialized and running the demo from crystal fontz via the PMP with the following:

Code:
#include "p33FJ128MC804.h"
#include <libpic30.h>
#include "customdelays.h"


//********Configuration Bytes********//
_FBS(RBS_NO_RAM & BSS_NO_FLASH & BWRP_WRPROTECT_OFF);
_FSS(RSS_NO_RAM & SSS_NO_FLASH & SWRP_WRPROTECT_OFF);
_FGS(GSS_OFF & GCP_OFF & GWRP_OFF);
_FOSCSEL(FNOSC_FRCPLL & IESO_OFF);
_FOSC(FCKSM_CSECME & IOL1WAY_ON & OSCIOFNC_ON & POSCMD_NONE);
_FWDT(FWDTEN_OFF & WINDIS_OFF & WDTPRE_PR128 & WDTPOST_PS32768);
_FPOR(PWMPIN_ON & HPOL_ON & LPOL_ON & ALTI2C_OFF & FPWRT_PWR128);
_FICD(JTAGEN_OFF & ICS_PGD1);

int main(void);

/* Control line pin definitions */
#define  CLR_RST		LATBbits.LATB2 = 0;
#define  SET_RST		LATBbits.LATB2 = 1;

#define  CLR_CD			LATCbits.LATC0 = 0;
#define  SET_CD			LATCbits.LATC0 = 1;

#define  CLR_CS			LATBbits.LATB3 = 0;
#define  SET_CS			LATBbits.LATB3 = 1;

// Color definitions
#define	BLACK	  0x0000
#define	BLUE	  0x001F
#define	RED 	  0xF800
#define	GREEN     0x07E0
#define CYAN	  0x07FF
#define MAGENTA   0xF81F
#define YELLOW    0xFFE0
#define WHITE	  0xFFFF


//*********Function Prototypes*******//

void write_command(unsigned int command)
{
	CLR_CS;
	CLR_CD;

	PMDIN1 = (command>>8);
	DELAY_US(1);

	PMDIN1 = (command);
	DELAY_US(1);

	SET_CS;
}

void write_data(unsigned int data)
{
	CLR_CS;
	SET_CD;
	
	PMDIN1 = (data>>8);
	DELAY_US(1);

	PMDIN1 = (data);
	DELAY_US(1);

	SET_CS;
}


void initialization()
{
	SET_CS;
	SET_CD;
	SET_RST;
	write_data(0x00);

	CLR_RST;
	DELAY_MS(200);
	SET_RST;
	DELAY_MS(500);

	write_command(0x0028);    // VCOM OTP
	write_data(0x0006);       // Page 55-56 of SSD2119 datasheet

	write_command(0x0000);    // start Oscillator
	write_data(0x0001);       // Page 36 of SSD2119 datasheet

	write_command(0x0010);    // Sleep mode
	write_data(0x0000);       // Page 49 of SSD2119 datasheet

	write_command(0x0001);    // Driver Output Control
	write_data(0x32EF);       // Page 36-39 of SSD2119 datasheet

	write_command(0x0002);    // LCD Driving Waveform Control
	write_data(0x0600);       // Page 40-42 of SSD2119 datasheet

	write_command(0x0003);    // Power Control 1
	write_data(0x6A38);       // Page 43-44 of SSD2119 datasheet

	write_command(0x0011);    // Entry Mode
	write_data(0x6870);       // Page 50-52 of SSD2119 datasheet

	write_command(0X000F);    // Gate Scan Position
	write_data(0x0000);       // Page 49 of SSD2119 datasheet

	write_command(0X000B);    // Frame Cycle Control
	write_data(0x5308);       // Page 45 of SSD2119 datasheet

	write_command(0x000C);    // Power Control 2
	write_data(0x0003);       // Page 47 of SSD2119 datasheet

	write_command(0x000D);    // Power Control 3
	write_data(0x000A);       // Page 48 of SSD2119 datasheet

	write_command(0x000E);    // Power Control 4
	write_data(0x2E00);       // Page 48 of SSD2119 datasheet

	write_command(0x001E);    // Power Control 5
	write_data(0x00BE);       // Page 53 of SSD2119 datasheet

	write_command(0x0025);    // Frame Frequency Control
	write_data(0x8000);       // Page 53 of SSD2119 datasheet

	write_command(0x0026);    // Analog setting
	write_data(0x7800);       // Page 54 of SSD2119 datasheet

	write_command(0x004E);    // Ram Address Set
	write_data(0x0000);       // Page 58 of SSD2119 datasheet

	write_command(0x004F);    // Ram Address Set
	write_data(0x0000);       // Page 58 of SSD2119 datasheet

	write_command(0x0012);    // Sleep mode
	write_data(0x08D9);       // Page 49 of SSD2119 datasheet

	// Gamma Control (R30h to R3Bh) -- Page 56 of SSD2119 datasheet
	write_command(0x0030);
	write_data(0x0000);

	write_command(0x0031);
	write_data(0x0104);

	write_command(0x0032);
	write_data(0x0100);

	write_command(0x0033);
	write_data(0x0305);

	write_command(0x0034);
	write_data(0x0505);

	write_command(0x0035);
	write_data(0x0305);

	write_command(0x0036);
	write_data(0x0707);

	write_command(0x0037);
	write_data(0x0300);

	write_command(0x003A);
	write_data(0x1200);

	write_command(0x003B);
	write_data(0x0800);		 

	write_command(0x0007);    // Display Control 
	write_data(0x0033);       // Page 45 of SSD2119 datasheet

	DELAY_MS(150);

	write_command(0x0022);    // RAM data write/read
}

void Display_Home()
{
	write_command(0x004E);    // RAM address set
	write_data(0x0000);       // Page 58 of SSD2119 datasheet
	write_command(0x004F);    // RAM address set
	write_data(0x0000);       // Page 58 of SSD2119 datasheet

	write_command(0x0044);    // Vertical RAM address position
	write_data(0xEF00);       // Page 57 of SSD2119 datasheet
	write_command(0x0045);    // Horizontal RAM address position 
	write_data(0x0000);       // Page 57 of SSD2119 datasheet
	write_command(0x0046);    // Horizontal RAM address position
	write_data(0x013F);       // Page 57 of SSD2119 datasheet

	write_command(0x0022);    // RAM data write/read
}

void LCD_test()
{
	unsigned int i,j;
	Display_Home();

	for(i=0;i<320;i++)
	{
		for(j=0;j<240;j++)
		{
			if(i>279)write_data(BLACK);
			else if(i>239)write_data(BLUE);
			else if(i>199)write_data(GREEN);
			else if(i>159)write_data(CYAN);
			else if(i>119)write_data(RED);
			else if(i>79)write_data(MAGENTA);
			else if(i>39)write_data(YELLOW);
			else write_data(WHITE);
		}
	}
}

void display_rgb(unsigned int data)
{
	unsigned int i,j;
	Display_Home();
	for(i=0;i<320;i++)
  {
  	for(j=0;j<240;j++)
  	{
  		write_data(data);
  	}
  }
}

int main()
{	
	AD1PCFGL = 0x0FFF;		// Disable ADC, make AN pins Digital I/O
	AD1CON2  = 0x0000;		// Use AVDD and AVSS as ADC reference voltages
	IC1CON   = 0x0000;		// Disable change notification on CN3
	IC2CON   = 0x0000;		// Disable change notification on CN4 and all other CNs
	TRISA    = 0x0000;		// Configure port A all as digital I/O 
	TRISB    = 0x0000;		// Configure port B all as digital I/O
	TRISC    = 0x0000;		// Configure port C all as digital I/O

// ---------------------------------------
//PMP setup
//---------------------------------------
PMMODE = 0; PMAEN = 0; PMCON = 0;

PMMODEbits.MODE   = 2;  // Intel 80 master interface
PMMODEbits.WAITB  = 0b0000;
PMMODEbits.WAITM  = 0b0010;
PMMODEbits.WAITE  = 0b0000;  
PMMODEbits.MODE16 = 0; // 8-bit Mode
PMCONbits.PTRDEN  = 1; // enable RD line
PMCONbits.PTWREN  = 1; // enable WR line
PMCONbits.WRSP    = 0; // Make WR active low
PMCONbits.RDSP    = 0; // Make RD active low
PMCONbits.PMPEN   = 1; // enable PMP
//---------------------------------------

//---------------------------------------
//Configure for 39.92MhzMIPS using FRC w/PLL
//---------------------------------------
CLKDIVbits.PLLPRE = 1;     //7.37Mhz/3 = 2.457Mhz
PLLFBDbits.PLLDIV = 63;    //PLLDIV+2 = 65 = VCO out:159.683Mhz
CLKDIVbits.PLLPOST = 0;   //Fcy=((((Oscilator/PLLPRE)*(PLLDIV+2))/PLLPOST)/2)
                                                 //   =((((7.37Mhz/3)*(65))/2)/2) = 39.92Mhz
while(!OSCCONbits.LOCK); 
//---------------------------------------


initialization();
Display_Home();


while(1)
{
	DELAY_MS(1000);
	display_rgb(BLACK);
	DELAY_MS(1000);
	display_rgb(BLUE);
	DELAY_MS(1000);
	display_rgb(RED);
	DELAY_MS(1000);
	display_rgb(GREEN);
	DELAY_MS(1000);
	display_rgb(CYAN);
	DELAY_MS(1000);
	display_rgb(MAGENTA);
	DELAY_MS(1000);
	display_rgb(YELLOW);
	DELAY_MS(1000);
	display_rgb(WHITE);
	DELAY_MS(1000);
	LCD_test();
}



return 0;	
}

Now, I'm going to need to try the PutPixel, PutImage, Bar etc. type functions from the Microchip library. When you did these did you use the graphic library stack from microchip (in the microchip solutions directory), or did you just rewrite their functions in your own project?
 

Attachments

  • TFT PMP.pdf
    40.4 KB · Views: 300
Last edited:
I'm not sure I completely understand the question. In general, I used microchip's graphic library except for PutPixel, PutImage, Bar, etc. Those I wrote myself. I kept the putchar, GOLFind, GOLDraw, etc. I did make some very helpful changes though.

For instance, the GOLDraw function can take a LOOOONG time (100 mS or more) so I changed that function to only draw one object at a time and then return.

Also, if you convert any fonts to use using their graphics conversion tool, you'll find that the fonts tend to leave a lot of blank space on the display above each character. I've seen as many as 12 rows of completely unused pixels above the characters. COMPLETE waste of space. I found a fairly good work around for it though. If you inspect the .c file that the conversion tool creates, the second byte of the array is unused and is always zero. I commandeered that byte to use as as offset. I set it to 12 for the font that had 12 blank pixels above it, and I edited the putchar function to print the font 12 pixels above where it thinks it needs to print. This eliminates the wasted space.

Oh yeah, another good tip for if your display uses a fine pitch ribbon cable. Print gradients on the display. If there are any shorts on your cable, the gradient can help identify them very quickly.

Code:
for (x = 0; x < 255; x++)
{
	SetColor( RGB565CONVERT( x, 0, 0 ) );
	Bar( 0, x, 79, x );
}
	
for (x = 0; x < 255; x++)
{
	SetColor( RGB565CONVERT( 0, x, 0 ) );
	Bar( 80, x, 159, x );
}
				
for (x = 0; x < 255; x++)
{
	SetColor( RGB565CONVERT( 0, 0, x ) );
	Bar( 160, x, 239, x );
}

All 3 bars should transition smoothly from black to a color. If there are any disparities in any color, or you don't see the right number of transitions, etc, then you know you have a problem on your data lines.
 
Last edited:
Cool thanks for all the help, I got it working! I'm now trying use the meter widget in the library and get it to update on the screen. I think its with the MtrSetVal function, but i haven't got it working yet.

Another problem i'm having is i need my maximum value to be 100000, but anything over 1000 doesn't come out right on the meter. Any ideas?

Thanks,
Michael
 
I've never used the meter so anything I said would be guessing. So here is a guess... Is the value that MtrSetVal stores the data in a 32 bit number?

As an alternative, can you have a variable, such as Uint32 meter_value, and do MtrSetVal( meter_value / 100 )?
 
Problems with widget METER

Can anybody help me to actualize measurement values of widget Meter?
Meter is displayed correctly on TFT.
When I update value with: MtrSetVal(pAnzeige_OBJ_METER_2_2, 260);

C30 compiler gives me an error:

Main.c:761: error: 'pAnzeige_OBJ_METER_2_2' undeclared (first use in this function)

In GDD_Screens.c Microchip Graphics Display Designer has automatically defined:

METER *pAnzeige_OBJ_METER_2_2;
pAnzeige_OBJ_METER_2_2 = MtrCreate(Anzeige_OBJ_METER_2_2,265,20,480,221,16384,0,0,300,NULL,NULL,(XCHAR*)Anzeige_OBJ_METER_2_2text,defscheme);

It seems to me like 'pAnzeige_OBJ_METER_2_2' is only local in Createxxxxx - function (GDD_Screens.c) ????

Thanks a lot for help!

Alfred
 
Status
Not open for further replies.

Latest threads

Back
Top