Nokia 6100 lcd + sam7s256 + Schmartboard pcb adaptors

Status
Not open for further replies.
May 11, 2008
21,712
1,302
126
Well, i started with a pcb i already made long ago. Unfortunately, the tiny hirose connector i ordered at mouser long ago was broken when i used it. the lcd connector is type DF23C-10DS- 0.5V

The pins have a pitch of 0.5mm so it is small.

DF23C-10DS-0.5V(51).jpg


I first took a bit of prototyping board and cut the traces and to make sort of a footprint for the tiny connector. Using single strands to connect the tiny connector to standard 1/10 inch prototyping pcb.
Unfortunately, the connector got damaged the first time i used and it had connection problems. I think this happened because under the pins was no pcb, i cut it away. Therefore there was no mechanical support for the pins and i had to think of something else.

con0.jpg~original


I removed the defective one.
I had enough connectors but no pcb with a footprint where the lcd connector would fit on. So i looked around and found out that Farnell has Schmartboard pcb adaptors. Mouser has them as well.

The model i bough is a 10 pin dfn to 1/10 inch prototyping pcb.SCHMARTBOARD 204-0022-01

204_0022_01_Big__17155.1435789428.1280.1280.jpg


These tiny pcb's are great for prototyping with SMT ICs in a DFN package.
In the middle of the adaptor pcb is an open via hole to electrically connect the tab that some dfn ic's have on the bottom side. But for me that was not handy since it could short the pins of the lcd connector. So i drilled it out with a 2mm drill bit.
I soldered the lcd new (hirose) connector on it.

con1.jpg~original


Connected it all with the pcb i already made with all needed electronics on it.
I used a CAT4240 led driver for the back light of the lcd and i added pwm dim control by making use of one of the 3 16 bit timers the sam7s series have. Each timer can be switch in a mode to generate two pwm signals. For this purpose i only needed one.

New schmart adaptor pcb with a shiny new connector. The lcd does not show text yet, but at least i got it initialized. It is an LCD with an epson controller. I just found out.

con2.jpg~original
 
Last edited:
May 11, 2008
21,712
1,302
126
Schmart pcb adaptors are for sale at mouser and farnell (newark).
I added a few commands to my terminal menu program in the sam7s256 that allows me to enter commands one by one by hand. This to debug the 6100 lcd.

term2.jpg~original


After trying out the commands according to the manual of James Lynch, i found out it is not a NXP controller but an Epson model : Epson S1D15G10.
term1.jpg~original



Now that i know it works, i can add menu commands to do the initializing automatically and see if i can draw figures and text.

^_^.

Link to pdf with useful information :
http://www.sparkfun.com/tutorial/Nokia 6100 LCD Display Driver.pdf
The datasheets are the ultimate resource, and can be googled for but are available at sparkfun.com

Example code can be found here :
https://www.olimex.com/Products/ARM/Atmel/SAM7-EX256/

I am certainly not the first, but i always wanted to do something with this color lcd.
It has 132x132 pixels and 12 bit color.

When i have written code to use it, i can order the special sensor i want.
 
Last edited:
May 11, 2008
21,712
1,302
126
Well, i extended my menu a bit but i am still debugging my functions and the lcd .
I ordered the lcd long ago at a mobile phone parts website.
And as it turns out, i have en epson knock off. This lcd only supports the 12 bit color mode with the 3 byte format.
I found a lot of examples, and they all work sort off. But filled with errors as is often the case with free example code. I should know, even my own free code i posted once for W-ARM contains errors. (Reminder, must update code to latest version).
I am now creating my own functions. What i am doing different, is that i use a struct. Instead of having draw functions with lots of parameters, i use a struct that must be filled with values and then passed as parameter (The address of the struct is passed as a pointer to that specific type of struct)for my functions. This should speedup code execution.

This is version one.
When i get around to start using the fonts, i might add some more variables for the fonts as well.
This way, i can create a display struct for every object to be drawn on the screen.


Code:
typedef struct s_lcd6100
{
uint32_t	color;		// front color.
uint8_t		xstart;		// X start position.	
uint8_t		xend;			// X end position.
uint8_t		ystart;		// Y start position.
uint8_t		yend;			// Y end position.	
uint32_t	bcolor;		// Background color used for text only.
uint8_t	     fontstyle	// Font style selects the type of font to be used. 
}lcd6100_t;

Unfortunately, as i read here and there while googling why my lcd has offset.
It seems these lcd have offset and the the memory addresses for the pixels do no start a 0 and end at 131 (for a 131 x131 pixel lcd).
As i am now finding out, the lcd starts at x and ends at xxx (I am still determining that), i will update this post later.

So i made a define in my header file :
Note, that i am still are in the situation of determining the correct values.
It seems that only the y position has offset.

Code:
// LCD view size	
#define LCD_WIDTH_START	0	
#define LCD_HEIGHT_START 0
#define LCD_WIDTH_END 129
#define LCD_HEIGHT_END 133
 
Last edited:
May 11, 2008
21,712
1,302
126
it seems the lcd has a few extra lines visible, a larger viewing area. :)

I am very happy with my Saleae logic analyzer.
https://www.saleae.com/?gclid=CIyqmcy6xckCFWXkwgod7AELww

It is a device that connects to the usb port and turns the pc into a logic analyzer. I have an 8 channel model.

saleae1.jpg~original


I used it before to make sure i got all settings of the SPI bus set up correct. And as it turns out, i did. Now i used it to see if i got the correct spi clock of 6MHz. And i do. :)

I expanded my menu a bit with a few lcd commands. Will be more.
term3.jpg~original

I am planning to make a demo with music. That will be tricky, because i have only one spi bus and i must share it between the lcd and the sd card.
I will have to create a lock flag whenever the DMA controller is filling the audio buffers with data from the sd card. The lcd will have to wait.
When i got it working, i might make use of the DMA controller as well to fill up the lcd with data.

Finally a proper image, a 4 color image.
lcd1.jpg~original


Next is to create a few draw functions and to get the drawing of fonts working.
 
May 11, 2008
21,712
1,302
126
This is the code to get the box :

Code:
//*************************************************************************************************
//
// select lcd, CS = L.
//
static inline void LCD_SELECT(void)
{
	AT91C_BASE_PIOA->PIO_CODR = LCD_NCS;
}
//*************************************************************************************************
//
// unselect lcd CS = H.
//
static inline void LCD_DESELECT(void)
{
	AT91C_BASE_PIOA->PIO_SODR = LCD_NCS;
}
//*************************************************************************************************
//
// reset lcd, RESET = L.
//
static inline void LCD_LRESET(void)
{
	AT91C_BASE_PIOA->PIO_CODR = LCD_NRST;
}
//*************************************************************************************************
//
// no reset lcd RESET = H.
//
static inline void LCD_HRESET(void)
{
	AT91C_BASE_PIOA->PIO_SODR = LCD_NRST;
}

Code:
//*************************************************************************************************
//
// Create 11-Bar Color 
//
void DrawColorBar(void)
{
  lcd6100_t					displayobject; //display object
	
	displayobject.xstart = LCD_WIDTH_START;
	displayobject.xend = LCD_WIDTH_END;
	displayobject.ystart = LCD_HEIGHT_START;
	displayobject.yend = 13;
	
	displayobject.color = WHITE;
	LcdFillWindow(&displayobject);
	
	displayobject.ystart = 14;
	displayobject.yend = 26;
  displayobject.color = CYAN; 
	LcdFillWindow(&displayobject);
	
	displayobject.ystart = 27;
	displayobject.yend = 39;
  displayobject.color = BLUE; 
	LcdFillWindow(&displayobject);
 
	displayobject.ystart = 40;
	displayobject.yend = 52;
  displayobject.color = MAGENTA; 
	LcdFillWindow(&displayobject);
  
	displayobject.ystart = 53;
	displayobject.yend = 65;
  displayobject.color = PINK;
	LcdFillWindow(&displayobject);
		
	displayobject.ystart = 66;
	displayobject.yend = 78;
  displayobject.color = RED;
	LcdFillWindow(&displayobject);
	
	displayobject.ystart = 79;
	displayobject.yend = 91;
  displayobject.color = GREEN;
	LcdFillWindow(&displayobject);	
	
	displayobject.ystart = 92;
	displayobject.yend = 104;
  displayobject.color = ORANGE;
	LcdFillWindow(&displayobject);		

	displayobject.ystart = 105;
	displayobject.yend = 117;
  displayobject.color = BROWN;
	LcdFillWindow(&displayobject);
	
	displayobject.ystart = 116;
	displayobject.yend = LCD_HEIGHT_END;
  displayobject.color = BLACK;
	LcdFillWindow(&displayobject);
}

Code:
//*************************************************************************************************
//
//  (x1,y1)						
//     ********************		
//     *                  *		
//     *                  *		
//     ********************		
//                    (x2,y2)	
//
//
void LcdSetWindow(lcd6100_t  *ps_display)
{
   LcdCmdWrite(CASET);   											// Page Start/Eend ram
   LcdDataWrite(ps_display->xstart);     
   LcdDataWrite(ps_display->xend);

   LcdCmdWrite(PASET);   											// Column Start/End ram
   LcdDataWrite(ps_display->ystart);     
   LcdDataWrite(ps_display->yend);
}


Code:
//*************************************************************************************************
//
// 
//
void LcdFillWindow(lcd6100_t  *ps_display)
{
  uint8_t 	total_bytes1;
  uint8_t 	total_bytes2;
  uint32_t 	total_bytes;
	uint32_t	i;
	uint8_t		cb1;
	uint8_t		cb2;
	uint8_t		cb3;
	uint32_t	color;
	
  LcdSetWindow(ps_display);
	
	color = ps_display->color;
	cb1 = (uint8_t)(color >> 4) & 0xFF;
	cb2 = (uint8_t)((color & 0xF) << 4 ) | ((color >> 8) & 0xF);
	cb3 = (uint8_t)color & 0xFF;

  LcdCmdWrite(RAMWR);
  total_bytes1 = (ps_display->xend - ps_display->xstart); 
  total_bytes2 = (ps_display->yend - ps_display->ystart);
  total_bytes = total_bytes1 * total_bytes2;
	if(total_bytes == 0)
	{
		total_bytes = 1;
	}
  
	//total_bytes
	for (i = 0; i < total_bytes; i++)
  {
		LcdDataWrite(cb1);
		LcdDataWrite(cb2);
		LcdDataWrite(cb3);
  }
	
}

Code:
//*************************************************************************************************
//
// 
//
void LcdDataWrite(uint32_t data)
{
	uint32_t	r;	

	LCD_SELECT();
	
	data = data | 0x00000100;
	
	while( !( AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer complete wait
	AT91C_BASE_SPI->SPI_TDR = data;

	while( !( AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for data
	r = AT91C_BASE_SPI->SPI_RDR;
	
	LCD_DESELECT();
}

//*************************************************************************************************
//
// 
//
void LcdCmdWrite(uint32_t data)
{
	uint32_t	r;	

	LCD_SELECT();
	
	data = data & 0x000000FF;
	
	while( !( AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer complete wait
	AT91C_BASE_SPI->SPI_TDR = data;

	while( !( AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for data
	r = AT91C_BASE_SPI->SPI_RDR;
	
	LCD_DESELECT();
}



I am a bit tipsy, so it could have still some errors.
 
Last edited:
May 11, 2008
21,712
1,302
126
Code:
//*************************************************************************************************
// This initialization procedure is for the Epson controller 
// Based upon the code created by James P Lynch. 
//
void Init6100Lcd(void)
{
	ResetLcd();
	Timer_Wait(20);

	// Display Control
	LcdCmdWrite(DISCTL);
	LcdDataWrite(0x00); // P1: 12 = 1100 - CL dividing ratio [don't divide] switching period 8H (default)
	LcdDataWrite(0x20); // P2: 0x20 = 130 lines.
	LcdDataWrite(0x00); // P3: 0x00 = no inversely highlighted lines
	LcdDataWrite(0x01); // P4: 0x00 No dispersion..

	Timer_Wait(5);
	// COM scan
	LcdCmdWrite(COMSCN);
	LcdDataWrite(0x01); // P1: 0x01 = Scan 1->80, 160<-81
	Timer_Wait(5);
	// Internal oscilator ON
	LcdCmdWrite(OSCON);
	Timer_Wait(5);
	// Sleep out
	LcdCmdWrite(SLPOUT);
	Timer_Wait(5);
	// Power control
	LcdCmdWrite(PWRCTR);
	LcdDataWrite(0x0f); // reference voltage regulator on, circuit voltage follower on, BOOST ON
	Timer_Wait(150);
	// Inverse display
	LcdCmdWrite(DISINV);
	Timer_Wait(5);
	// Data control
	LcdCmdWrite(DATCTL);
	LcdDataWrite(0x00); // P1: 0x01 = page address inverted, col address normal, address scan in col direction
	LcdDataWrite(0x00); // P2: 0x00 = RGB sequence (default value)
	LcdDataWrite(0x02); // P3: 0x02 = Grayscale ->16 bits (selects 12-bit color, type A)
	Timer_Wait(5);
	
	// Voltage control (contrast setting)
	LcdCmdWrite(VOLCTR);
	LcdDataWrite(0x20); // P1 = 32 volume value (adjust this setting for your display
	LcdDataWrite(0x03); // P2 = 3 resistance ratio (determined by experiment)
	Timer_Wait(5);

	// turn on the display
	LcdCmdWrite(DISON);
		
}

Code:
// ************************************************************************************************
// This function adjusts the backlight level of the LCD.
// In 100 steps.
// 
//
void SetLcdBacklight(uint32_t value)
{
	value = value << 5; // Value * 32.

	if(value > (100 << 5))  // 100 * 32 = 3200.
	{
		value = (100 << 5);
	}

	if(value < 32) 
	{
		value = 32;
	}

	AT91C_BASE_TC2->TC_CCR |= AT91C_TC_CLKDIS;	//Disable MR2.

	AT91C_BASE_TC2->TC_RC = 3300;	// Load RC with 3300.
	AT91C_BASE_TC2->TC_RA = value;

	AT91C_BASE_TC2->TC_CCR |= AT91C_TC_CLKEN;	//Enable MR2.
	AT91C_BASE_TC2->TC_CCR |= AT91C_TC_SWTRG;	// Start PWM wave generator. 
}

Code:
//*************************************************************************************************
//
// CPOL = 0, CPHASE = 1, 9 bits, 6Mhz clock. 
//
void SetSpiTo_Lcd(void)
{
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
	
	// SPI mode: master, FDIV=0, fault detection disabled
	AT91C_BASE_SPI->SPI_MR  = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;
	
	AT91C_BASE_SPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_NCPHA | AT91C_SPI_BITS_9 | (0x08 << 8);
	
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
}


//*************************************************************************************************
//
// CPOL = 0, CPHASE = 1, 8 bits.
//
void setSpiTo_Sd(void)
{
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
	
	// SPI mode: master, FDIV=0, fault detection disabled
	AT91C_BASE_SPI->SPI_MR  = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;
	
	AT91C_BASE_SPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_NCPHA | AT91C_SPI_BITS_8 | (0xFE << 8);
	
	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
}

Code:
// ****************************************************************************************************
// This function configures the timer counter 2 as a PWM generator with the TIO2A as pwm output.
// With this PWM we control the backlight of the LCD. The PWM will generate at around ~1KHz.

void Configure_TMR2(void)
{
//	AT91C_BASE_PMC	// Base address masterclock controller.
	
	
		AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC2;    // Enable the clock to TMR2.

		AT91C_BASE_TC2->TC_CCR |= AT91C_TC_CLKDIS; //Clock is disabled.
		AT91C_BASE_TC2->TC_CMR = 0;	  // reset all bits of channel mode register to known state.

		
		// 	454 Hz PWM generator.
		//  Tperiod = 454 Hz = 2.2*10e-3.
		//  Start dUty cycle = 25 %
		//	DIV = 32.
		//  DIV * RCvalue = Tperiod * MCK. RCvalue = (Tperiod * MCK ) / DIV
		//  RCvalue = 0.0022 * 48,000,000 / 32
		//  RCvalue = 3300. RA = RC/ 2 (50%) = 1650. (25%)= 825.		
		
		
		AT91C_BASE_TC2->TC_CMR = 	AT91C_TC_CLKS_TIMER_DIV3_CLOCK |	// TMR2 clock = MCLK/32. 
											//AT91C_TC_EEVT_XC2 |								// TMR2IOB = output.
											AT91C_TC_WAVESEL_UP_AUTO |				// Trigger on RC compare and reload.
											AT91C_TC_WAVE |										// PWM wave generator.
											AT91C_TC_ACPA_TOGGLE |						// Toggle TMR2IOA when RA compares.
											AT91C_TC_ACPC_TOGGLE |						// Toggle TMR2IOA when RC compares.
											AT91C_TC_ASWTRG_SET; 							// Set output on software trigger.
											
		AT91C_BASE_TC2->TC_RC = 3300;	// Load RC with 3300.
		AT91C_BASE_TC2->TC_RA = 825;	// Load RA with 825.									
		
		AT91C_BASE_TC2->TC_CCR |= AT91C_TC_CLKEN;	//Enable MR2.
		AT91C_BASE_TC2->TC_CCR |= AT91C_TC_SWTRG;	// Start PWM wave generator. 
}
 
May 11, 2008
21,712
1,302
126
This is the code to initialize the spi bus for the sd card. But the finctions to setup the spi bus fort the lcd are above.

Code:
// ************************************************************************************************
//
// Init SPI-Interface (Platform dependent)                               
//
// ************************************************************************************************
void init_spi(void)
{
	// set SPI pins to the peripheral function
	PPIO_BASE_SPI->PIO_ASR = AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK;
	// disable PIO from controlling the pins (so they are used for peripheral)
	PPIO_BASE_SPI->PIO_PDR = AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK;

	// set chip-select as output high (unselect card) 
	// manual control for CS !                        
	AT91C_BASE_PMC->PMC_PCER = ( 1 << PMC_ID_CS ); // enable needed PIO in PMC
	PPIO_BASE_CS->PIO_PER  = CARD_SELECT_PIN;  // enable GPIO of CS-pin (disable peripheral functions)
	PPIO_BASE_CS->PIO_SODR = CARD_SELECT_PIN;  // set high
	PPIO_BASE_CS->PIO_OER  = CARD_SELECT_PIN;  // output enable

	// enable peripheral clock for SPI ( PID Bit 5 )
	AT91C_BASE_PMC->PMC_PCER = ( 1 << AT91C_ID_SPI ); // n.b. IDs are just bit-numbers

	// SPI disable
	PSPI_BASE->SPI_CR = AT91C_SPI_SPIDIS;

	// init the SPI's PDC-controller:
	// disable PDC TX and RX
	PSPI_BASE->SPI_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
	// init counters and buffer-pointers to 0
	// "next" TX
	PSPI_BASE->SPI_TNPR = 0;
	PSPI_BASE->SPI_TNCR = 0;
	// "next" RX
	PSPI_BASE->SPI_RNPR = 0;
	PSPI_BASE->SPI_RNCR = 0;
	// TX
	PSPI_BASE->SPI_TPR = 0;
	PSPI_BASE->SPI_TCR = 0;
	// RX
	PSPI_BASE->SPI_RPR = 0;
	PSPI_BASE->SPI_RCR = 0;

	// SPI enable and reset
	// The state machine for revB version needs to have 2 SPI
	// software resets to properly reset the state machine. 
	// See erratalist in datasheet.
	PSPI_BASE->SPI_CR = AT91C_SPI_SWRST;
	PSPI_BASE->SPI_CR = AT91C_SPI_SWRST;
	PSPI_BASE->SPI_CR = AT91C_SPI_SPIEN;

	// SPI mode: master, FDIV=0, fault detection disabled
	PSPI_BASE->SPI_MR  = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;

	// set chip-select-register
	// 8 bits per transfer, CPOL=0, ClockPhase=1, DLYBCT = 0
	PSPI_BASE->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_NCPHA | AT91C_SPI_BITS_8;

	// slow during init
	AT91_spiSetSpeed(0xFE);

	// enable SPI
	PSPI_BASE->SPI_CR = AT91C_SPI_SPIEN;
}

For example (a snippet from my menu):

Code:
				if(StrCmp(char_array,(uint8_t *)"clrlcd") == 0)
				{
					commandstatus = 1;
					SetSpiTo_Lcd();
					LcdClearScreen();
					setSpiTo_Sd();
				}

Code:
#define SPI_SCBR_MIN          2

static void AT91_spiSetSpeed(uint8_t speed)
{
	uint32_t reg;

	if ( speed < SPI_SCBR_MIN ) 
	{
		speed = SPI_SCBR_MIN;
	}
	if ( speed > 1 )
	{
		 speed &= 0xFE;
	}

	reg = PSPI_BASE->SPI_CSR[SPI_CSR_NUM];
	
	reg = ( reg & ~(AT91C_SPI_SCBR) ) | ( (uint32_t)speed << 8 );
	
	PSPI_BASE->SPI_CSR[SPI_CSR_NUM] = reg;
}
 
Last edited:
May 11, 2008
21,712
1,302
126
I cleaned up the code : (See above)

Looks much better.

For example to fill one pixel only :

Code:
void LcdOrangeBox(void) 
{
  lcd6100_t					displayobject; //display object

	displayobject.color = ORANGE;	
	displayobject.xstart = 32;
	displayobject.xend = 32; //97;
	displayobject.ystart = 32;
	displayobject.yend = 32; //97;	

	LcdFillWindow(&displayobject);
}

Other parts that may be needed
Code:
// Definitions.
#define SPI_CSR_NUM           0		
		
		
// Epson controller command set :
#define DISON       0xaf   										
#define DISOFF      0xae										
#define DISNOR      0xa6
#define DISINV      0xa7
#define COMSCN      0xbb
#define DISCTL      0xca
#define SLPIN       0x95
#define SLPOUT      0x94
#define PASET       0x75
#define CASET       0x15
#define DATCTL      0xbc
#define RGBSET8     0xce
#define RAMWR       0x5c
#define RAMRD       0x5d
#define PTLIN       0xa8
#define PTLOUT      0xa9
#define RMWIN       0xe0
#define RMWOUT      0xee
#define ASCSET      0xaa
#define SCSTART     0xab
#define OSCON       0xd1
#define OSCOFF      0xd2
#define PWRCTR      0x20
#define VOLCTR      0x81
#define VOLUP       0xd6
#define VOLDOWN     0xd7
#define TMPGRD      0x82
#define EPCTIN      0xcd
#define EPCOUT      0xcc
#define EPMWR       0xfc
#define EPMRD       0xfd
#define EPSRRD1     0x7c
#define EPSRRD2     0x7d
#define NOP         0x25
		
// 12-bit color definitions
#define WHITE 0xFFF
#define BLACK 0x000
#define RED 0xF00
#define GREEN 0x0F0
#define BLUE 0x00F
#define CYAN 0x0FF
#define MAGENTA 0xF0F
#define YELLOW 0xFF0
#define BROWN 0xB22
#define ORANGE 0xFA0
#define PINK 0xF6A
 
Last edited:
May 11, 2008
21,712
1,302
126
Well, i made my own version of the character display function.
I use the three font tables by James P Lynch. I did for now removed the info bytes at the beginning that the font tables have describing the font tables.
For now, i have three font types i can use.

x,y
8x8 small.
8x8 medium.
8x16 large.

Code:
// Font selection
#define FONT_SMALL		1
#define FONT_MEDIUM 	2
#define FONT_LARGE		3

Code:
// Struct
// Note , The information in this struct is modified when using the LcdWriteChar function and the LcdWriteString function.
// x,y start and x,y end are modified and must be back upped.
typedef struct s_lcd6100
{
uint32_t	color;		// front color.
uint8_t		xstart;		// X start position.	
uint8_t		xend;			// X end position.
uint8_t		ystart;		// Y start position.
uint8_t		yend;			// Y end position.	
uint32_t	bcolor;		// Background color used for text only.
uint32_t	fontstyle;	// Font style selects the type of font to be used. 
}lcd6100_t;

Code:
void LcdWriteChar(lcd6100_t  *ps_display, uint8_t c)
{
	uint32_t	color0;
	uint32_t	color1;
	uint8_t		cb1;
	uint8_t		cb2;
	uint8_t		cb3;
	uint32_t	columnsize=0;
	uint32_t	rowsize=0;
	uint32_t	columnindex;
	uint32_t	rowindex;
	uint32_t	index;
	const uint8_t	*ptr=0;
	uint8_t		pixeltest;


	index = c - 0x20; //Font table starts at 0x20 of ascii table.
	columnsize = 4;	//Actual columnsize = 8. But we calculate two pixels at once.
	switch(ps_display->fontstyle) // select font
	{
		case FONT_SMALL:
			ps_display->xend = ps_display->xstart + 7;
			ps_display->yend = ps_display->ystart + 7;
			rowsize = 8;
			ptr = font6x8; 
			index = index << 3; // * 8.
			break;
		case FONT_MEDIUM:
			ps_display->xend = ps_display->xstart + 7;
			ps_display->yend = ps_display->ystart + 7;
			rowsize = 8;
			ptr = font8x8;
			index = index << 3; // * 8.
			break;
		case FONT_LARGE:
			ps_display->xend = ps_display->xstart + 7;
			ps_display->yend = ps_display->ystart + 15;
			rowsize = 16;
			ptr = font8x16;
			index = index << 4; // * 16.
			break;
	}
		
	ptr = ptr + index;
	
	LcdSetWindow(ps_display);

  LcdCmdWrite(RAMWR);
				
	for(rowindex = 0; rowindex < rowsize;rowindex++)
	{
		pixeltest = *ptr;
		for(columnindex = 0;columnindex < columnsize;columnindex++)
		{
			if((pixeltest & 0x80) == 0)
			{
				color0 = ps_display->bcolor;
			}
			else
			{
				color0 = ps_display->color;
			}
			
			pixeltest = pixeltest << 1;
			if((pixeltest & 0x80) == 0)
			{
				color1 = ps_display->bcolor;
			}
			else
			{
				color1 = ps_display->color;
			}
		
			pixeltest = pixeltest << 1;
			
			cb1 = (uint8_t)(color0 >> 4) & 0xFF;
			cb2 = (uint8_t)((color0 & 0xF) << 4 ) | ((color1 >> 8) & 0xF);
			cb3 = (uint8_t)color1 & 0xFF;
		
			LcdDataWrite(cb1);
			LcdDataWrite(cb2);
			LcdDataWrite(cb3);
		}
		ptr++;
	}	
	LcdCmdWrite(NOP);
}

Some example code.
Code:
	displayobject.color = BLUE;	
	displayobject.xstart = 35;
	displayobject.ystart = 35;
	displayobject.bcolor = PINK;	
	displayobject.fontstyle = FONT_SMALL;
	LcdWriteChar(&displayobject, '!');
	displayobject.xstart = 43;
	LcdWriteChar(&displayobject, 'a');

	displayobject.fontstyle = FONT_MEDIUM;
	displayobject.xstart = 51;
	LcdWriteChar(&displayobject, '!');

	displayobject.fontstyle = FONT_LARGE;
	displayobject.xstart = 59;
	LcdWriteChar(&displayobject, '!');

Now i have to write an Write String function that makes use of LcdWriteChar.
 
Last edited:
May 11, 2008
21,712
1,302
126
lcd2.jpg~original


Yahoo. That works too. ^_^



Code:
void LcdOrangeBox(void) 
{
  lcd6100_t					displayobject; //display object

	displayobject.color = ORANGE;	
	displayobject.xstart = 0;
	displayobject.xend = 120;
	displayobject.ystart = 0;
	displayobject.yend = 30;	

	LcdFillWindow(&displayobject);
	
	displayobject.color = PINK;	
	displayobject.xstart = 5;
	displayobject.ystart = 5;
	displayobject.bcolor = BROWN;	
	displayobject.fontstyle = FONT_SMALL;
	LcdWriteChar(&displayobject, '!');
	displayobject.xstart = 13;
	LcdWriteChar(&displayobject, 'a');

	displayobject.fontstyle = FONT_MEDIUM;
	displayobject.xstart = 21;
	LcdWriteChar(&displayobject, '!');

	displayobject.fontstyle = FONT_LARGE;
	displayobject.xstart = 29;
	LcdWriteChar(&displayobject, '!');
	
	displayobject.color = RED;	
	displayobject.xstart = 20;
	displayobject.ystart = 50;
	displayobject.bcolor = BLACK;	
	displayobject.fontstyle = FONT_SMALL;
	LcdWriteString(&displayobject, "hi ATHT !");

	displayobject.color = GREEN;	
	displayobject.xstart = 20;
	displayobject.ystart = 70;
	displayobject.bcolor = BLACK;	
	displayobject.fontstyle = FONT_MEDIUM;
	LcdWriteString(&displayobject, "hi ATHT !");

	displayobject.color = BLUE;	
	displayobject.xstart = 20;
	displayobject.ystart = 90;
	displayobject.bcolor = BLACK;	
	displayobject.fontstyle = FONT_LARGE;
	LcdWriteString(&displayobject, "hi ATHT !");
	
	displayobject.color = CYAN;	
	displayobject.xstart = 20;
	displayobject.ystart = 110;
	displayobject.bcolor = BLACK;	
	displayobject.fontstyle = FONT_LARGE;
	LcdWriteString(&displayobject, "By William !");
	
}

Code:
//*************************************************************************************************
//
// 
//
void LcdWriteString(lcd6100_t  *ps_display, char *string)
{
	uint8_t	charposition;
	uint8_t	offset;
	
	charposition = ps_display->xstart;

	switch(ps_display->fontstyle) // select font
	{
		case FONT_SMALL:
			offset = 8;
			break;
		case FONT_MEDIUM:
			offset = 8;
			break;
		case FONT_LARGE:
			offset = 9;
			break;
	}
	
	while(*string != 0x00)
	{
		ps_display->xstart = charposition;
		LcdWriteChar(ps_display, *string);
		charposition += offset;
		string++;
	}
}

EDIT:

I changed the write string function a bit to increase readability when using the 8x16 size font. In the image can be seen that the characters touch each other. I solved that issue by positioning each character one pixel away.
 
Last edited:
May 11, 2008
21,712
1,302
126
Well, now i can display bmp images as well.
The program i use is a freeware program called NokiaImageCreator v 1.00.
Unfortunately, it crashes when i want to import bmp files. I have to look into that. The program converts the files to a c file with in it an array with thousands of bytes describing the image a 12bit color in a 2pixel per 3byte format.

This function prints the bmp files. It only works well when x size and y size are of a even value. It was easy to make because i had an example.


Code:
//*************************************************************************************************
//
// 
//
void LcdWriteBmp(lcd6100_t  *ps_display, const uint8_t *ptr)
{
	uint32_t	yindex;
	uint32_t	xindex;
	uint32_t	yend;
	uint32_t	xend;
		
	LcdSetWindow(ps_display);
		
	yend = ps_display->yend;
	xend = ps_display->xend;
	xend = xend >> 1; // we write two pixels at once.

	for(yindex=0;yindex < yend;yindex++) 
	{
		LcdCmdWrite(RAMWR);
		
		for(xindex = 0;xindex < xend;xindex++)
		{
			LcdDataWrite(*ptr);
			ptr++;
			LcdDataWrite(*ptr);
			ptr++;
			LcdDataWrite(*ptr);
			ptr++;
		}
	}
}

Example code :
Code:
void LcdPic1(void)
{
	lcd6100_t					displayobject; //display object
	
	displayobject.xstart = LCD_WIDTH_START;
	displayobject.xend = LCD_WIDTH_END;
	displayobject.ystart = LCD_HEIGHT_START;
	displayobject.yend = LCD_HEIGHT_END;
	
	LcdWriteBmp(&displayobject, testimage);
}

Code:
void LcdPic2(void)
{
  lcd6100_t					displayobject; //display object
	
	displayobject.xstart = LCD_WIDTH_START;
	displayobject.xend = LCD_WIDTH_END;
	displayobject.ystart = LCD_HEIGHT_START;
	displayobject.yend = LCD_HEIGHT_END;
	
	LcdWriteBmp(&displayobject, smiley);
}


lcd4.jpg~original


lcd3.jpg
 
Last edited:
Status
Not open for further replies.