Monochrome Graphic Display Source Code Driver Project
Section 04 . Using The Driver In Your Project

04 . Using The Driver In Your Project

a) Updating The Display

Displaying Bitmaps

Use the ‘display_bitmap’ function. For example:-


display_bitmap(0, ec_logo_128x64,			//Bitmap (flash / program memory)
		DISPLAY_BITMAP_INVERT_PIXELS_OFF,	//Options
		0, 0);					//X, Y

Available options:

DISPLAY_BITMAP_INVERT_PIXELS_OFF

DISPLAY_BITMAP_INVERT_PIXELS_ON

Displaying Text

Use the ‘display_const_string’ and ‘display_variable_string’ functions to display null terminated strings. Individual strings may be displayed as monospace or proportional width text with left, centre or right alignment. For example:


	display_const_string(0, font_05x07, //Bitmap (flash / program memory)
					(DISPLAY_STRING_ON_X_AXIS |
					DISPLAY_STRING_INVERT_PIXELS_OFF |
					DISPLAY_STRING_PROPORTIONAL |
					DISPLAY_STRING_CENTER_ALIGN),			//Options
					20, 20,							//X, Y
					(CONSTANT BYTE*)"Hello World");	//String

CONSTANT BYTE sample_const_string [] = {"Hello World"};

	display_const_string(0, font_05x07, 	//Bitmap (flash/program memory)
					(DISPLAY_STRING_ON_X_AXIS |
					DISPLAY_STRING_INVERT_PIXELS_OFF |
					DISPLAY_STRING_MONOSPACE |
					DISPLAY_STRING_LEFT_ALIGN),			//Options
					20, 20,							//X, Y
					sample_const_string);					//String

BYTE sample_variable_string[12] = {"Hello World"};

	display_variable_string(0, font_05x07, //Bitmap (flash/program memory)
					(DISPLAY_STRING_ON_X_AXIS |
					DISPLAY_STRING_INVERT_PIXELS_OFF |
					DISPLAY_STRING_MONOSPACE |
					DISPLAY_STRING_LEFT_ALIGN),		//Options
					20, 20,						//X, Y
					sample_variable_string);			//String

Available options:


	DISPLAY_STRING_INVERT_PIXELS_OFF
	DISPLAY_STRING_INVERT_PIXELS_ON

	DISPLAY_STRING_ON_X_AXIS
	DISPLAY_STRING_ON_Y_AXIS

	DISPLAY_STRING_MONOSPACE
	DISPLAY_STRING_PROPORTIONAL

	DISPLAY_STRING_LEFT_ALIGN
	DISPLAY_STRING_CENTER_ALIGN
	DISPLAY_STRING_CENTRE_ALIGN
	DISPLAY_STRING_RIGHT_ALIGN

Displaying Scrolling Text

The following examples demonstrate how to use the scrolling text function.

Displaying a scrolling constant string (string stored in program memory) example

//Define the string (always include a trailing space)
CONSTANT BYTE my_string[] = {"        Hello World "};

//Call this function initially with display_scroll_text_start_pixel = 0xff, and then every time you want to move the text on 1 place
void display_scrolling_text (void)
{
	static CONSTANT BYTE *p_start_character = &my_string[0];

	display_scroll_text_start_pixel += 1;	//1 for faster scrolling)
	display_scroll_text_display_pixels_count = 40;	//Width of the display area
 //to display within, in pixels

	display_const_string(0, font_05x07, 	//Bitmap (flash / program memory)
				(DISPLAY_STRING_ON_X_AXIS |
DISPLAY_STRING_INVERT_PIXELS_OFF |
DISPLAY_STRING_SCROLL),	//Options
				10, 10,			//X, Y start coordinate
				p_start_character);	//String

	if (display_scroll_1st_char_done_skip_pixels)
	{
		//FIRST CHARACTER HAS FALLEN OFF THE START OF THE DISPLAY
//MOVE TO NEXT ONE
		p_start_character++;
		if (p_start_character >= (&my_string[0] + sizeof(my_string) - 1))
			p_start_character = &my_string[0];

		//Reset the number of pixels to skip
		if (display_scroll_1st_char_done_skip_pixels < 0xff)	//(0xff = reset to zero)
		    display_scroll_text_start_pixel = display_scroll_1st_char_done_skip_pixels;
		else
		    display_scroll_text_start_pixel = 0;
	}
}
Displaying a scrolling variable string (string stored in ram) example

//Call this function initially with display_scroll_text_start_pixel = 0xff, and then every time you want to move the text on 1 place
void display_scrolling_text (void)
{
	static BYTE my_string[] = "Hello World ";
	BYTE *p_source;
	BYTE *p_dest;
	BYTE first_character;

	display_scroll_text_start_pixel += 1;	//1 for faster scrolling)
	display_scroll_text_display_pixels_count = 60;	//Width of the display area
//to display within, in pixels

	display_variable_string(0, font_07x13, 	//Bitmap (flash / program memory)
					(DISPLAY_STRING_ON_X_AXIS |
DISPLAY_STRING_INVERT_PIXELS_OFF |
DISPLAY_STRING_SCROLL),	//Options
					2, 15,				//X, Y start coordinate
					my_string);			//String

	if (display_scroll_1st_char_done_skip_pixels)
	{
		//FIRST CHARACTER HAS FALLEN OFF THE START OF THE DISPLAY
//MOVE IT TO THE END
		p_source = &my_string[1];
		p_dest = &my_string[0];
		first_character = *p_dest;
		while (*p_source != 0x00)
			*p_dest++ = *p_source++;

		*p_dest++ = first_character;
		*p_dest++ = 0x00;

		//Reset the number of pixels to skip
		if (display_scroll_1st_char_done_skip_pixels < 0xff)	//(0xff = reset to zero)
		    display_scroll_text_start_pixel = display_scroll_1st_char_done_skip_pixels;
		else
		    display_scroll_text_start_pixel = 0;
	}

}

This will display the string which will continuously scroll, automatically moving each character to the end of the string each time they fall off the start, so that the scrolling never resets.

Scrolling Details

The implementation of scrolling is deliberately provided in this quite raw fashion so that you can fine tune it exactly as you wish and also use the functionality to do special things if desired. These are the variables that provide the scrolling functionality when any string is displayed with the DISPLAY_STRING_SCROLL option selected:

display_scroll_text_start_pixel

This variable defines how many pixels at the start of the displayed string to ignore. You would typically incremented it each time the string is displayed.

display_scroll_text_display_pixels_count

Set to the required width you want the text to be displayed within (any extra trailing characters or part characters will not be displayed). Must be set each time the string is displayed.

display_scroll_1st_char_done_skip_pixels

This variable will contain 0 after a scrolling string has been displayed if the first character of the string is still partly displayed. If not zero then the first character of the string can be removed and the value indicates the value to reset display_scroll_text_start_pixel to (0xff = set it to zero). Although it is best for fastest processing to remove characters from the start of strings and reset display_scroll_text_start_pixel, doing this is optional and you could simply keep on incrementing display_scroll_text_start_pixel all the way to the end of the string if you wished.

Manipulation of display_scroll_text_start_pixel and display_scroll_text_display_pixels_count variables gives you the flexibility to create your own special scrolling or bespoke string display capabilities should you wish.

Scrolling Notes

Displaying fast scrolling text and large scrolling text, requires enough processing speed and a fast enough communications interface to your display to avoid scrolling being slowed. Most other display functions don’t require your hardware to be very fast, as a slight delay while a bitmap or string is displayed is barely noticed by the eye. However when moving text along pixel by pixel slowness of updating can become an issue if your hardware is not fast enough. If scrolling is too slow the following may help:

Slow the scrolling speed

Reduce the size of the text

Use fonts that are stored in a C header file (instead of an external binary file)

Enable the DISPLAY_USE_LOCAL_RAM_BUFFER define so that internal microcontroller / processor memory is used to buffer the display data, avoiding the driver having to read from the display.

Clear The Screen


	 display_clear_screen(0);	//Clear the screen

	 display_clear_screen(1);	//Clear the screen with all pixels on

b) How To Create Graphical Elements

Creating User Interface Menu Bars

Create bitmap images of each of the menu elements. Display these and then use text strings to overwrite on top of each menu item. Using the ‘invert pixels’ option allows you to display text over bitmap blocks without needing to create a new inverted font.

Creating Windows With Variable Content

Create a bitmap image of the whole window and then overwrite it with text strings and small bitmap images in the required places to create the variable content inside.

Creating Flashing Or Animated Icons

Create two or more bitmap images of the same size and then display each one over the top of the last using a timer

Creating Progress Bars

Create a bitmap of the empty progress bar and then use a single bitmap of one row of pixels to update the progress bar for each successive step, moving it on one column or row at a time.

Creating Lines

For variable length lines use a single pixel bitmap and display repeatedly to make the line, or use bitmaps of complete lines.

Creating Graphs

Create a bitmap for your graph X and Y axis markers and then use a single pixel bitmap to create each of the points of a graph line.

Updating Screen In A Single Operation

If you want to be able to update the contents of your display in local ram and then write to the screen in a single bulk operation this is possible by modifying the driver when using the DISPLAY_USE_LOCAL_RAM_BUFFER define. With this define included, so that a local ram buffer is used to store a copy of the display output, you could remove the actual output to the screen code in the function display_write_bitmap_byte. Instead this function would update the local ram buffer as usual but wouldn’t attempt to write to the display. When you wanted to update the display you could then provide your own function to write the complete display_copy_buffer to your screen.

c) Using Driver With A New Screen Model

Using the driver with a new screen model requires adjusting each of the functions in the display-model.c file to suit your screen and its driver (these files contain just the functions that are screen specific and don’t contain any of the general display processing driver functions). Unfortunately due to the massive amount of screens and screen driver IC’s available there is no generic way of doing this, but following this guide should make the process straightforward.

Copy A Pair Of Sample Files

First copy the sample display-model.c and display-model.h pair of files for the included screen types that is most similar to your screen to use as a reference. These can then be modified as necessary for your screen and its controller IC.

If your screen includes 2 controller IC’s (many do to drive half of the screen each) then select sample files that are for a screen that also uses 2 controllers.

Screen Specific Defines

Go through each of the defines in the display-model.h file and update as required for your screen.

DISPLAY_WIDTH_PIXELS

The width of the screen in pixels (X coordinate)

DISPLAY_HEIGHT_PIXELS

The height of the screen in pixels (Y coordinate – this is used for the page address – divide this value by 8 to give the number of pages). This axis must match the axis that the screen addresses in bytes (for instance it may be the real world X axis even though its called height in the driver). As the driver allows screens to be used in all 4 possible orientations width and height will actually refer to the Y and X axis in 2 of the possible orientations.

DISPLAY_WIDTH_START_OFFSET

Offset to first actual display position (0 if not applicable – required if screen has a number of unused rows that need to be skipped past).

DISPLAY_DEFAULT_CONTRAST

The default contrast value for the screen (only required if screen has digital contrast control)

DISPLAY_USE_LOCAL_RAM_BUFFER

The driver provides complete functionality without requiring a local ram buffer of the outputted display data. It will read the current display state of individual bytes back from the display when it needs to. However if your microcontroller has sufficient ram available the display functions can be speeded up if a local copy of the display output is stored, especially if the display has a serial interface. If you are using a display that does not provide the means to read back display data (for instance serial displays which have a ‘SI’ serial in pin and no ‘SO’ serial out pin) then you will have to use this use local ram buffer option for the driver to function correctly. Your local ram buffer will need to be big enough to hold every pixel of the display which is typically (X resolution * Y resolution) / 8. If the resolution of either axis is not a multiple of 8 then increase it up to the next multiple of 8 before carrying out this calculation.

ORIENTATION_IS_0
ORIENTATION_IS_90
ORIENTATION_IS_180
ORIENTATION_IS_270

Enabling 1 of these defines (comment out the other 3) selects the orientation your screen is to be used in. (Use the same setting for the Bitmap Converter Application).

INVERT_Y_AXIS_COORDINATES

Should be commented out normally, but include if you need to reverse the direction of display on the Y axis (only applicable when in screen orientations when the Y axis is horizontal). Typically required for one of the four possible orientations.

IO Defines

Alter the IO defines to provide all of the input and output pins required by your screen and serial port access if your screen uses a serial rather than parallel interface.

Bus Access Delay Defines

DISPLAY_BUS_ACCESS_DELAY

This define may be used with parallel interface screens to add in one or more null (no operation) instructions to allow data bus signals to stabilise during read or write access. 2 layer PCB’s (no ground plane) and PCB’s with long track lengths are more likely to require this. If you are experiencing problems setting up a new screen it is worth using this define to give a reasonable delay and then remove it later once you have the screen working.

User Options

INCLUDE_DISPLAY_BYTE_TEST_SEQUENCE_FUNCTION

The test sequence function is useful when configuring the driver for a new screen. Comment this define out to remove the function to save program memory space. An example of its use is included in the sample projects. See the description of this function in this manual.

Screen Specific Functions

void display_model_initialise(void)

Adjust this to provide the initialisation sequence required by your screen. This can often be found in the screens data sheet or by contacting the screen manufacturer to request the initialisation sequence required. Controller IC’s used in the screens are often quite generic and can therefore be confusing to know exactly the configuration that is required for the particular screen model they have been used in. Therefore it is reasonable to expect the screen manufacturer to provide this if they have failed to include it in a screen datasheet.

void display_model_set_contrast(BYTE contrast_value)

If your screen includes digital contrast control then include the command sequence in this function to set the contrast to a new level. If there is no digital contrast command just leave this as an empty function.

void display_write_bitmap_byte (BYTE bitmap_mask, BYTE bitmap_data, WORD x_byte_coord, WORD y_byte_coord)

This function is called to output each byte to the display. It first reads the current byte value from the display (if DISPLAY_USE_LOCAL_RAM_BUFFER is not defined), and you may need to adjust this to suit your display. It then modifies the byte with the new data to be written, which you shouldn’t modify. Finally it writes the new byte value to the display, which you may need to adjust to suit your display.

void display_set_address (WORD x_coord, WORD y_coord_page)

This function outputs the address of the byte being output to the display and may need to be altered to suit your display.

void display_write_command (BYTE data)

This function outputs individual command bytes to the display and may need to be altered to suit your display.

Getting A New Screen To Work

Screen data sheets don’t always provide very good information to help you get a new screen working. Some datasheets simply provide the mechanical details of the screen, the electrical characteristics and specify which display controller IC is used in the screen. Here’s some tips:-

Beware of screen mechanical drawings – just because a data sheet shows a screen in a particular orientation doesn’t mean that this is the correct orientation to use the screen! If the datasheet doesn’t specify the correct viewing angle the best way to check is to get the screen working and see which orientation provides the best viewing angle for the intended application. If you can’t do this ask the manufacturer to confirm the correct orientation or find a photo of the screen in use. The bitmap converter application allows you to rotate your bitmap images and fonts into all 4 orientations, allowing you to use a screen any way round.

Get the datasheet for the display controller IC being used. Also check to see if there is a technical manual as some IC datasheets provide little helpful information on how to get a screen working because this is provided in a separate technical manual or application note.

Your screen may use 2 off the same display driver IC. This makes the screen access functions slightly more complicated as each IC has to be individually addressed. Sample screen drivers which have 2 driver IC’s are included with this driver which you can copy and modify when configuring for your screen.

Some screens, such as LCD screens, have specific voltage requirements. If you are lucky your screen will use a controller IC that includes generation of these voltages. You will still need to configure the driver to provide the voltages required by the screen, but you will not need to provide the voltages externally. If not then you will need to provide the required voltage(s). For LCD screens there are many IC’s available designed to provide bias voltages, often with a digital interface to provide the contrast adjustment (variation of the bias voltage). Otherwise a simple potentiometer may be used. Be aware that sometimes the bias voltage needs to be negative, so you may have to use a DCDC converter if your application has no negative voltage rail.

A controller IC provides the actual drive of the display pixels and a standard data bus connection to your processor / microcontroller. Some controller IC’s provide advanced features such as more than 1 ‘layer’ of display output. This driver uses a single layer so any other layers can be ignored. If your screen has no built in controller IC you will need to select one and fit it between the screen and your processor / microcontroller. This can be a complex task and is outside the scope of this manual. A good solution is to see if there is an evaluation board available for the screen and copy the controller IC used on this, or find another screen that includes a built in controller IC!

Tips on configuring the driver for your screen

If your screen has built in contrast control a good way to check that your initialisation sequence is working is to use a routine to cycle through the contrast values. If all is well you should see the contrast change on the screen regardless of what the screen might be displaying. This confirms that you are at least communicating correctly with the screen. If there is no contrast command maybe your screen driver has special commands to say turn all pixels on, again providing a means to confirm that you are communicating correctly.

Ask your screen supplier or manufacturer if there is an example code sequence available for your screen or an application note. Often screen datasheets just specify the controller IC used and then leave it to you to work out how that generic controller IC needs to be configured for the screen it is being used with. Ask the manufacturer for this information as its often available but not included in the datasheet.

Using the ‘display_byte_ordering_test_sequence’ function is a very useful way to discover how your screen addresses bitmap data. See the description of this function in this manual. This will also confirm that you are able to write to the correct area of the controller IC ram to output bitmap data. Sometimes controller IC’s have larger display ram areas than are needed for the screen you are using and will therefore need to adjust the ‘display_set_address’ function to allow for this.

All addressing is done using X and Y coordinates. However these are software based coordinates and will not necessarily match the logical directions you would assume for the orientation you are using your screen in. Therefore try displaying a bitmap in the centre of the screen and see which way it is orientated, or try it at coordinates 0, 0 and then max x, max y (e.g. 127, 63 for a 128 x 64 pixel screen). Initially displaying it at a position that is a multiple of 8 for the Y coordinate is a good idea in case some adjustment is needed to deal with bit position offsetting.

The driver writes 1 byte of display data at a time and it does this on the Y axis. Therefore ensure you have specified you resolution the correct way round for DISPLAY_WIDTH_PIXELS and DISPLAY_HEIGHT_PIXELS. You may need to reverse these values to match your screen (remember don’t assume X and Y will match the way you think it ought to be). Using the ‘display_byte_ordering_test_sequence’ function will show you in which coordinate your screen is byte addressed.

Remember that you will also need to convert your source bitmap files using the bitmap converter application to the orientation that matches the orientation you have set in the header file.

If your display is working in the reverse direction modify the ‘display_set_address’ function to correct this. You may also need to use the INVERT_Y_AXIS_COORDINATES define (see explanation above). Note that often what appears as a garbage display of a bitmap is simply caused by reverse X or Y addressing.

If text doesn’t display in the direction you expect change the DISPLAY_STRING_ON_#_AXIS option when calling the string display function (its an option when displaying a string as sometimes you may wish to display in the other axis for vertical text)

The X and Y addressing can seem daunting but it is usually relatively simple to solve by a little bit of trial and error. Once this is set correctly for a new screen you are ready to use the full power of this driver.