Display driver for Sharp's range of SPI-driven memory LCD's, leveraging the power of asynchronous transfers. Currently supports LS013B7DH03, but easily extendable to other models as well.

Dependents:   memLCD-Demo memLCD-Demo memLCD-Demo MemLCD-Temperature-Humidity-Demo ... more

Information

All examples in this repo are considered EXPERIMENTAL QUALITY, meaning this code has been created as one-off proof-of-concept and is suitable as a demonstration for experimental purposes only. This code will not be regularly maintained by Silicon Labs and there is no guarantee that these projects will work across all environments, SDK versions and hardware.

Memory LCD extension board

Caution

This library builds upon the asynchronous SPI interface provided by mbed, but not all platforms currently support this. So, make sure your platform is capable of asynchronous SPI (all Silicon Labs platforms are), otherwise you will get compiler errors!

Usage

The library is purposefully quite simple to use. To set it up, you initialize an SPI object and the required I/O pins, and call the library constructor with those. Make sure the display is powered on, enabled, and the inversion mode is set to external (EXTMODE is high).

setup

#define SCK     PD2
#define MOSI 	PD0

DigitalOut CS(PD3);
DigitalOut EXTCOM(PC4);

SPI displaySPI(MOSI, NC, SCK);
silabs::LS013B7DH03 display(&displaySPI, &CS, &EXTCOM);

You should also swap out the pin names for the relevant names on your platform.

After setup, you usually want to clear any static information left on the screen. To do that, you would call clearImmediate, and optionally provide a callback. The callback will get called when the clearing operation is complete and the display has been cleared. In this example, refreshCallback sets a global boolean 'refreshed' to true when called.

clearing the display

refreshed = false;
int result = display.clearImmediate(refreshCallback);
if(result == LS013B7DH03_OK) {
    while(refreshed == false) sleep();
} else {
    printf("Display error: %d", result);
}

Of course, instead of sleeping while the display is clearing, you could also just continue with the program, and check back whether the callback happened or not.

Then comes the fun part, actually writing stuff on the display! Since the display only supports one-way communication (i.e. you cannot read from it), it uses an internal frame buffer in RAM. So, to actually display something on the LCD, two steps need to happen: writing to the pixel buffer, and at the very end writing the pixel buffer to the LCD.

Pixelbuffer operations

The MemoryLCD library builds upon Simon Ford's TextDisplay library, which means you can use all of that functionality. Even printf is supported!

most important display operations

// Set one pixel at x=10, y=40 to the color White
display.pixel(10,40,White); 

// print "I love mbed" at the character position x=4, y=5
// i.e. starting on row 5, 4 characters from the left border
display.locate(4,5);
display.printf("I love mbed!");

// show a bitmap at a given location
// Constraints: bitmap is 8-bit, MSB first, 1 bit per pixel. Width, height and starting coordinates must be divisible by 8.
// This example: show a bitmap which is 128 pixels wide and high, and start at location 0,0.
display.showBMP(&mbed_logo, 128, 128, 0, 0);

//Draw a line (really a 1px wide rectangle) from (4,10) until (4,15)
display.fill(4, 10, 1, 5, White);

Updating the LCD

Updating the LCD (i.e. moving the framebuffer to the display) happens much the same way as clearing it: asynchronously. To start the update, you call update() on the display, optionally providing a callback to be called after the whole update has happened. In the example below, refreshCallback sets a global boolean 'refreshed' to true when called. Signature: void refreshCallback(void);

updating the display

refreshed = false;
int result = display.update(refreshCallback);
if(result == LS013B7DH03_OK) {
    while(refreshed == false) sleep();
} else {
    printf("Display error: %d", result);
}

Full example

example program

#include "LS013B7DH03.h"
#include "mbed_logo.h"
/******************** Define I/O *****************************/
DigitalOut myled(LED1);

#define SCK     PD2
#define MOSI 	PD0

DigitalOut CS(PD3);
DigitalOut EXTCOM(PC4);
DigitalOut EXTMODE(PD4);
DigitalOut DISP(PD5);

SPI displaySPI(MOSI, NC, SCK);
silabs::LS013B7DH03 display(&displaySPI, &CS, &EXTCOM);

/******************** Define Timers *****************************/

LowPowerTicker timeKeeping;

/***************** Define global variables **********************/
#define INIT_SECONDS		17600

volatile uint32_t prevSeconds = INIT_SECONDS, seconds = INIT_SECONDS;
volatile bool refreshed = false;

/***************** Define callback handlers *********************/
void secondsCallback(void);
void refreshCallback(void);

void secondsCallback(void) {
	seconds++;
}

/**
 * Callback for refresh completion
 */
void refreshCallback(void) {
	refreshed = true;
}

/*************************** MAIN *******************************/
int main() {
    // Enable the LCD
	EXTMODE = 1;
	DISP = 1;

	// Start generating the 1Hz call for keeping time
	timeKeeping.attach(&secondsCallback, 1.0f);

	// Reset the LCD to a blank state. (All white)
	refreshed = false;
	display.clearImmediate(refreshCallback);
	while(refreshed == false) sleep();

	printf("Initialization done! \n");

	// Apply mbed logo bitmap to the pixel buffer
	display.showBMP((uint8_t*)mbed_enabled_logo, 128, 128, 0, 0);
	display.printf("I like MBED!");

	// Push update to the display
	refreshed = false;
	display.update(refreshCallback);

	// Sleep while doing the transmit
	while(refreshed == false) sleep();

	// Go into clock mode
	while(1) {
		sleep();

		// In clock mode, only update once per second
		if(prevSeconds != seconds) {
			display.locate(4,15);
			display.printf("%02d:%02d:%02d", (seconds / 1200) % 24, (seconds / 60) % 60, seconds % 60);
			if(refreshed == true) {
				prevSeconds = seconds;
				refreshed = false;
				display.update(refreshCallback);
			}
		}
	}
}

Datasheet

Datasheet for the LCD (hosted by Mouser)

Committer:
stevew817
Date:
Wed Aug 12 14:06:07 2015 +0000
Revision:
11:0f8ae10b308d
Parent:
5:26851f9655cf
Implement Paul Staron's enhancements to the display driver classes, from https://developer.mbed.org/users/star297/code/MemoryLCD/rev/b64f87859c57

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Steven Cooreman 0:a0faa86660d4 1 /* mbed GraphicsDisplay Display Library Base Class
Steven Cooreman 0:a0faa86660d4 2 * Copyright (c) 2007-2009 sford
Steven Cooreman 0:a0faa86660d4 3 * Released under the MIT License: http://mbed.org/license/mit
Steven Cooreman 0:a0faa86660d4 4 */
Steven Cooreman 0:a0faa86660d4 5
Steven Cooreman 0:a0faa86660d4 6 #include "GraphicsDisplay.h"
Steven Cooreman 0:a0faa86660d4 7
stevew817 11:0f8ae10b308d 8 #define incx() x++, dxt += d2xt, t += dxt
stevew817 11:0f8ae10b308d 9 #define incy() y--, dyt += d2yt, t += dyt
stevew817 11:0f8ae10b308d 10
Steven Cooreman 0:a0faa86660d4 11 const unsigned char FONT8x8[97][8] = {
Steven Cooreman 0:a0faa86660d4 12 {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, num_bytes_per_char
Steven Cooreman 0:a0faa86660d4 13 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space 0x20
Steven Cooreman 0:a0faa86660d4 14 {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // !
Steven Cooreman 0:a0faa86660d4 15 {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // "
Steven Cooreman 0:a0faa86660d4 16 {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // #
Steven Cooreman 0:a0faa86660d4 17 {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $
Steven Cooreman 0:a0faa86660d4 18 {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // %
Steven Cooreman 0:a0faa86660d4 19 {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // &
Steven Cooreman 0:a0faa86660d4 20 {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // '
Steven Cooreman 0:a0faa86660d4 21 {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // (
Steven Cooreman 0:a0faa86660d4 22 {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // )
Steven Cooreman 0:a0faa86660d4 23 {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // *
Steven Cooreman 0:a0faa86660d4 24 {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // +
Steven Cooreman 0:a0faa86660d4 25 {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // ,
Steven Cooreman 0:a0faa86660d4 26 {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // -
Steven Cooreman 0:a0faa86660d4 27 {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // .
Steven Cooreman 0:a0faa86660d4 28 {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / (forward slash)
Steven Cooreman 0:a0faa86660d4 29 {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 0x30
Steven Cooreman 0:a0faa86660d4 30 {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1
Steven Cooreman 0:a0faa86660d4 31 {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2
Steven Cooreman 0:a0faa86660d4 32 {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3
Steven Cooreman 0:a0faa86660d4 33 {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4
Steven Cooreman 0:a0faa86660d4 34 {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5
Steven Cooreman 0:a0faa86660d4 35 {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6
Steven Cooreman 0:a0faa86660d4 36 {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7
Steven Cooreman 0:a0faa86660d4 37 {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8
Steven Cooreman 0:a0faa86660d4 38 {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9
Steven Cooreman 0:a0faa86660d4 39 {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
Steven Cooreman 0:a0faa86660d4 40 {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ;
Steven Cooreman 0:a0faa86660d4 41 {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // <
Steven Cooreman 0:a0faa86660d4 42 {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // =
Steven Cooreman 0:a0faa86660d4 43 {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // >
Steven Cooreman 0:a0faa86660d4 44 {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ?
Steven Cooreman 0:a0faa86660d4 45 {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ 0x40
Steven Cooreman 0:a0faa86660d4 46 {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A
Steven Cooreman 0:a0faa86660d4 47 {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B
Steven Cooreman 0:a0faa86660d4 48 {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C
Steven Cooreman 0:a0faa86660d4 49 {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D
Steven Cooreman 0:a0faa86660d4 50 {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E
Steven Cooreman 0:a0faa86660d4 51 {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F
Steven Cooreman 0:a0faa86660d4 52 {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G
Steven Cooreman 0:a0faa86660d4 53 {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H
Steven Cooreman 0:a0faa86660d4 54 {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I
Steven Cooreman 0:a0faa86660d4 55 {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J
Steven Cooreman 0:a0faa86660d4 56 {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K
Steven Cooreman 0:a0faa86660d4 57 {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L
Steven Cooreman 0:a0faa86660d4 58 {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M
Steven Cooreman 0:a0faa86660d4 59 {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N
Steven Cooreman 0:a0faa86660d4 60 {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O
Steven Cooreman 0:a0faa86660d4 61 {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P 0x50
Steven Cooreman 0:a0faa86660d4 62 {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q
Steven Cooreman 0:a0faa86660d4 63 {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R
Steven Cooreman 0:a0faa86660d4 64 {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S
Steven Cooreman 0:a0faa86660d4 65 {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T
Steven Cooreman 0:a0faa86660d4 66 {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U
Steven Cooreman 0:a0faa86660d4 67 {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V
Steven Cooreman 0:a0faa86660d4 68 {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W
Steven Cooreman 0:a0faa86660d4 69 {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X
Steven Cooreman 0:a0faa86660d4 70 {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y
Steven Cooreman 0:a0faa86660d4 71 {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z
Steven Cooreman 0:a0faa86660d4 72 {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [
Steven Cooreman 0:a0faa86660d4 73 {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // \ (back slash)
Steven Cooreman 0:a0faa86660d4 74 {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ]
Steven Cooreman 0:a0faa86660d4 75 {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^
Steven Cooreman 0:a0faa86660d4 76 {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _
Steven Cooreman 0:a0faa86660d4 77 {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` 0x60
Steven Cooreman 0:a0faa86660d4 78 {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a
Steven Cooreman 0:a0faa86660d4 79 {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b
Steven Cooreman 0:a0faa86660d4 80 {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c
Steven Cooreman 0:a0faa86660d4 81 {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d
Steven Cooreman 0:a0faa86660d4 82 {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e
Steven Cooreman 0:a0faa86660d4 83 {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f
Steven Cooreman 0:a0faa86660d4 84 {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g
Steven Cooreman 0:a0faa86660d4 85 {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h
Steven Cooreman 0:a0faa86660d4 86 {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i
Steven Cooreman 0:a0faa86660d4 87 {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j
Steven Cooreman 0:a0faa86660d4 88 {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k
Steven Cooreman 0:a0faa86660d4 89 {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l
Steven Cooreman 0:a0faa86660d4 90 {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m
Steven Cooreman 0:a0faa86660d4 91 {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n
Steven Cooreman 0:a0faa86660d4 92 {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o
Steven Cooreman 0:a0faa86660d4 93 {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p
Steven Cooreman 0:a0faa86660d4 94 {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q
Steven Cooreman 0:a0faa86660d4 95 {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r
Steven Cooreman 0:a0faa86660d4 96 {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s
Steven Cooreman 0:a0faa86660d4 97 {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t
Steven Cooreman 0:a0faa86660d4 98 {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u
Steven Cooreman 0:a0faa86660d4 99 {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v
Steven Cooreman 0:a0faa86660d4 100 {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w
Steven Cooreman 0:a0faa86660d4 101 {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x
Steven Cooreman 0:a0faa86660d4 102 {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y
Steven Cooreman 0:a0faa86660d4 103 {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z
Steven Cooreman 0:a0faa86660d4 104 {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // {
Steven Cooreman 0:a0faa86660d4 105 {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // |
Steven Cooreman 0:a0faa86660d4 106 {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // }
Steven Cooreman 0:a0faa86660d4 107 {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
Steven Cooreman 0:a0faa86660d4 108 {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}}; // DEL
Steven Cooreman 0:a0faa86660d4 109
Steven Cooreman 0:a0faa86660d4 110 GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
Steven Cooreman 0:a0faa86660d4 111 foreground((uint16_t)Black);
Steven Cooreman 0:a0faa86660d4 112 background((uint16_t)White);
Steven Cooreman 0:a0faa86660d4 113 // current pixel location
Steven Cooreman 0:a0faa86660d4 114 _x = 0;
Steven Cooreman 0:a0faa86660d4 115 _y = 0;
Steven Cooreman 0:a0faa86660d4 116 // window settings
Steven Cooreman 0:a0faa86660d4 117 _x1 = 0;
Steven Cooreman 0:a0faa86660d4 118 _x2 = 0;
Steven Cooreman 0:a0faa86660d4 119 _y1 = 0;
Steven Cooreman 0:a0faa86660d4 120 _y2 = 0;
Steven Cooreman 0:a0faa86660d4 121 }
Steven Cooreman 0:a0faa86660d4 122
Steven Cooreman 0:a0faa86660d4 123 void GraphicsDisplay::character(int column, int row, int value) {
stevew817 11:0f8ae10b308d 124 if(externalfont){ // send external font
stevew817 11:0f8ae10b308d 125 unsigned int hor,vert,offset,bpl,j,i,b;
stevew817 11:0f8ae10b308d 126 const unsigned char* sign;
stevew817 11:0f8ae10b308d 127 unsigned char z,w;
stevew817 11:0f8ae10b308d 128 if ((value < 31) || (value > 127)) return; // test char range
stevew817 11:0f8ae10b308d 129 // read font parameter from start of array
stevew817 11:0f8ae10b308d 130 offset = font[0]; // bytes / char
stevew817 11:0f8ae10b308d 131 hor = font[1]; // get hor size of font
stevew817 11:0f8ae10b308d 132 vert = font[2]; // get vert size of font
stevew817 11:0f8ae10b308d 133 bpl = font[3]; // bytes per line
stevew817 11:0f8ae10b308d 134 if (char_x + hor > width()) {
stevew817 11:0f8ae10b308d 135 char_x = 0;
stevew817 11:0f8ae10b308d 136 char_y = char_y + vert;
stevew817 11:0f8ae10b308d 137 if (char_y >= height() - font[2]) {
stevew817 11:0f8ae10b308d 138 char_y = 0;
stevew817 11:0f8ae10b308d 139 }
stevew817 11:0f8ae10b308d 140 }
stevew817 11:0f8ae10b308d 141 window(char_x, char_y,hor,vert); // char box
stevew817 11:0f8ae10b308d 142 sign = &font[((value -32) * offset) + 4]; // start of char bitmap
stevew817 11:0f8ae10b308d 143 w = sign[0]; // width of actual char
stevew817 11:0f8ae10b308d 144 for (j=0; j<vert; j++) { // vert line
stevew817 11:0f8ae10b308d 145 for (i=0; i<hor; i++) { // horz line
stevew817 11:0f8ae10b308d 146 z = sign[bpl * i + ((j & 0xF8) >> 3)+1];
stevew817 11:0f8ae10b308d 147 b = 1 << (j & 0x07);
stevew817 11:0f8ae10b308d 148 if (( z & b ) == 0x00) {
stevew817 11:0f8ae10b308d 149 putp(_foreground);
stevew817 11:0f8ae10b308d 150 }
stevew817 11:0f8ae10b308d 151 else {
stevew817 11:0f8ae10b308d 152 putp(_background);
stevew817 11:0f8ae10b308d 153 }
stevew817 11:0f8ae10b308d 154 }
stevew817 11:0f8ae10b308d 155 }
stevew817 11:0f8ae10b308d 156 if ((w + 2) < hor) { // x offset to next char
stevew817 11:0f8ae10b308d 157 char_x += w + 2;
stevew817 11:0f8ae10b308d 158 }
stevew817 11:0f8ae10b308d 159 else char_x += hor;
stevew817 11:0f8ae10b308d 160 }
stevew817 11:0f8ae10b308d 161 // send default font
stevew817 11:0f8ae10b308d 162 else {
stevew817 11:0f8ae10b308d 163 blitbit(column * 8, row * 8, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));
stevew817 11:0f8ae10b308d 164 }
Steven Cooreman 0:a0faa86660d4 165 }
Steven Cooreman 0:a0faa86660d4 166
Steven Cooreman 0:a0faa86660d4 167 void GraphicsDisplay::window(int x, int y, int w, int h) {
Steven Cooreman 0:a0faa86660d4 168 // current pixel location
Steven Cooreman 0:a0faa86660d4 169 _x = x;
Steven Cooreman 0:a0faa86660d4 170 _y = y;
Steven Cooreman 0:a0faa86660d4 171 // window settings
Steven Cooreman 0:a0faa86660d4 172 _x1 = x;
Steven Cooreman 0:a0faa86660d4 173 _x2 = x + w - 1;
Steven Cooreman 0:a0faa86660d4 174 _y1 = y;
Steven Cooreman 0:a0faa86660d4 175 _y2 = y + h - 1;
Steven Cooreman 0:a0faa86660d4 176 }
Steven Cooreman 0:a0faa86660d4 177
Steven Cooreman 0:a0faa86660d4 178 void GraphicsDisplay::putp(int colour) {
Steven Cooreman 0:a0faa86660d4 179 // put pixel at current pixel location
Steven Cooreman 0:a0faa86660d4 180 pixel(_x, _y, colour);
Steven Cooreman 0:a0faa86660d4 181 // update pixel location based on window settings
Steven Cooreman 0:a0faa86660d4 182 _x++;
Steven Cooreman 0:a0faa86660d4 183 if(_x > _x2) {
Steven Cooreman 0:a0faa86660d4 184 _x = _x1;
Steven Cooreman 0:a0faa86660d4 185 _y++;
Steven Cooreman 0:a0faa86660d4 186 if(_y > _y2) {
Steven Cooreman 0:a0faa86660d4 187 _y = _y1;
Steven Cooreman 0:a0faa86660d4 188 }
Steven Cooreman 0:a0faa86660d4 189 }
Steven Cooreman 0:a0faa86660d4 190 }
Steven Cooreman 0:a0faa86660d4 191
stevew817 11:0f8ae10b308d 192 void GraphicsDisplay::rect(int x0, int y0, int x1, int y1, int color) {
stevew817 11:0f8ae10b308d 193 if (x1 > x0) hline(x0,x1,y0,color);
stevew817 11:0f8ae10b308d 194 else hline(x1,x0,y0,color);
stevew817 11:0f8ae10b308d 195 if (y1 > y0) vline(x0,y0,y1,color);
stevew817 11:0f8ae10b308d 196 else vline(x0,y1,y0,color);
stevew817 11:0f8ae10b308d 197 if (x1 > x0) hline(x0,x1,y1,color);
stevew817 11:0f8ae10b308d 198 else hline(x1,x0,y1,color);
stevew817 11:0f8ae10b308d 199 if (y1 > y0) vline(x1,y0,y1,color);
stevew817 11:0f8ae10b308d 200 else vline(x1,y1,y0,color);
stevew817 11:0f8ae10b308d 201 return;
stevew817 11:0f8ae10b308d 202 }
stevew817 11:0f8ae10b308d 203
stevew817 11:0f8ae10b308d 204 void GraphicsDisplay::fillrect(int x0, int y0, int w, int h, int colour) {
stevew817 11:0f8ae10b308d 205 unsigned long int index=0;
stevew817 11:0f8ae10b308d 206 if (w < 0) {
stevew817 11:0f8ae10b308d 207 x0 = x0 + w;
stevew817 11:0f8ae10b308d 208 w = -w;
stevew817 11:0f8ae10b308d 209 }
stevew817 11:0f8ae10b308d 210 if (h < 0) {
stevew817 11:0f8ae10b308d 211 y0 = y0 + h;
stevew817 11:0f8ae10b308d 212 h = -h;
stevew817 11:0f8ae10b308d 213 }
stevew817 11:0f8ae10b308d 214 window(x0,y0,w,h);
stevew817 11:0f8ae10b308d 215 int num = h*w;
stevew817 11:0f8ae10b308d 216 for( index = 0; index<num; index++ ) {
stevew817 11:0f8ae10b308d 217 putp(colour);
stevew817 11:0f8ae10b308d 218 }
stevew817 11:0f8ae10b308d 219 return;
stevew817 11:0f8ae10b308d 220 }
stevew817 11:0f8ae10b308d 221
Steven Cooreman 0:a0faa86660d4 222 void GraphicsDisplay::fill(int x, int y, int w, int h, int colour) {
stevew817 11:0f8ae10b308d 223 fillrect(x, y, w, h, colour);
Steven Cooreman 0:a0faa86660d4 224 }
srodk 5:26851f9655cf 225
srodk 5:26851f9655cf 226 void GraphicsDisplay::circle(int x, int y, int r,int colour){
srodk 5:26851f9655cf 227 int ce = -r;
srodk 5:26851f9655cf 228 int cx = r;
srodk 5:26851f9655cf 229 int cy = 0;
srodk 5:26851f9655cf 230 while(cx >= cy){
srodk 5:26851f9655cf 231 pixel(x+cx,y+cy,colour);
srodk 5:26851f9655cf 232 pixel(x-cx,y-cy,colour);
srodk 5:26851f9655cf 233 pixel(x-cx,y+cy,colour);
srodk 5:26851f9655cf 234 pixel(x+cx,y-cy,colour);
srodk 5:26851f9655cf 235 pixel(x+cy,y+cx,colour);
srodk 5:26851f9655cf 236 pixel(x-cy,y+cx,colour);
srodk 5:26851f9655cf 237 pixel(x-cy,y-cx,colour);
srodk 5:26851f9655cf 238 pixel(x+cy,y-cx,colour);
srodk 5:26851f9655cf 239 ce += 2*cy++ + 1;
srodk 5:26851f9655cf 240 if(ce >= 0){
srodk 5:26851f9655cf 241 ce -= 2*cx---1;
srodk 5:26851f9655cf 242 }
srodk 5:26851f9655cf 243
srodk 5:26851f9655cf 244 }
srodk 5:26851f9655cf 245
srodk 5:26851f9655cf 246 }
stevew817 11:0f8ae10b308d 247
stevew817 11:0f8ae10b308d 248 // To draw circle set a and b to the same values
stevew817 11:0f8ae10b308d 249 void GraphicsDisplay::ellipse(int xc, int yc, int a, int b, unsigned int colour)
stevew817 11:0f8ae10b308d 250 {
stevew817 11:0f8ae10b308d 251 /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
stevew817 11:0f8ae10b308d 252 int x = 0, y = b;
stevew817 11:0f8ae10b308d 253 long a2 = (long)a*a, b2 = (long)b*b;
stevew817 11:0f8ae10b308d 254 long crit1 = -(a2/4 + a%2 + b2);
stevew817 11:0f8ae10b308d 255 long crit2 = -(b2/4 + b%2 + a2);
stevew817 11:0f8ae10b308d 256 long crit3 = -(b2/4 + b%2);
stevew817 11:0f8ae10b308d 257 long t = -a2*y; // e(x+1/2,y-1/2) - (a^2+b^2)/4
stevew817 11:0f8ae10b308d 258 long dxt = 2*b2*x, dyt = -2*a2*y;
stevew817 11:0f8ae10b308d 259 long d2xt = 2*b2, d2yt = 2*a2;
stevew817 11:0f8ae10b308d 260
stevew817 11:0f8ae10b308d 261 while (y>=0 && x<=a) {
stevew817 11:0f8ae10b308d 262 pixel(xc+x, yc+y, colour);
stevew817 11:0f8ae10b308d 263 if (x!=0 || y!=0)
stevew817 11:0f8ae10b308d 264 pixel(xc-x, yc-y, colour);
stevew817 11:0f8ae10b308d 265 if (x!=0 && y!=0) {
stevew817 11:0f8ae10b308d 266 pixel(xc+x, yc-y, colour);
stevew817 11:0f8ae10b308d 267 pixel(xc-x, yc+y, colour);
stevew817 11:0f8ae10b308d 268 }
stevew817 11:0f8ae10b308d 269 if (t + b2*x <= crit1 || // e(x+1,y-1/2) <= 0
stevew817 11:0f8ae10b308d 270 t + a2*y <= crit3) // e(x+1/2,y) <= 0
stevew817 11:0f8ae10b308d 271 incx();
stevew817 11:0f8ae10b308d 272 else if (t - a2*y > crit2) // e(x+1/2,y-1) > 0
stevew817 11:0f8ae10b308d 273 incy();
stevew817 11:0f8ae10b308d 274 else {
stevew817 11:0f8ae10b308d 275 incx();
stevew817 11:0f8ae10b308d 276 incy();
stevew817 11:0f8ae10b308d 277 }
stevew817 11:0f8ae10b308d 278 }
stevew817 11:0f8ae10b308d 279 }
stevew817 11:0f8ae10b308d 280 // To draw circle set a and b to the same values
stevew817 11:0f8ae10b308d 281 void GraphicsDisplay::fillellipse(int xc, int yc, int a, int b, unsigned int colour)
stevew817 11:0f8ae10b308d 282 {
stevew817 11:0f8ae10b308d 283 /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
stevew817 11:0f8ae10b308d 284 int x = 0, y = b;
stevew817 11:0f8ae10b308d 285 int rx = x, ry = y;
stevew817 11:0f8ae10b308d 286 unsigned int width = 1;
stevew817 11:0f8ae10b308d 287 unsigned int height = 1;
stevew817 11:0f8ae10b308d 288 long a2 = (long)a*a, b2 = (long)b*b;
stevew817 11:0f8ae10b308d 289 long crit1 = -(a2/4 + a%2 + b2);
stevew817 11:0f8ae10b308d 290 long crit2 = -(b2/4 + b%2 + a2);
stevew817 11:0f8ae10b308d 291 long crit3 = -(b2/4 + b%2);
stevew817 11:0f8ae10b308d 292 long t = -a2*y; // e(x+1/2,y-1/2) - (a^2+b^2)/4
stevew817 11:0f8ae10b308d 293 long dxt = 2*b2*x, dyt = -2*a2*y;
stevew817 11:0f8ae10b308d 294 long d2xt = 2*b2, d2yt = 2*a2;
stevew817 11:0f8ae10b308d 295 if (b == 0) {
stevew817 11:0f8ae10b308d 296 fillrect(xc-a, yc, 2*a+1, 1, colour);
stevew817 11:0f8ae10b308d 297 return;
stevew817 11:0f8ae10b308d 298 }
stevew817 11:0f8ae10b308d 299 while (y>=0 && x<=a) {
stevew817 11:0f8ae10b308d 300 if (t + b2*x <= crit1 || // e(x+1,y-1/2) <= 0
stevew817 11:0f8ae10b308d 301 t + a2*y <= crit3) { // e(x+1/2,y) <= 0
stevew817 11:0f8ae10b308d 302 if (height == 1)
stevew817 11:0f8ae10b308d 303 ; // draw nothing
stevew817 11:0f8ae10b308d 304 else if (ry*2+1 > (height-1)*2) {
stevew817 11:0f8ae10b308d 305 fillrect(xc-rx, yc-ry, width, height-1, colour);
stevew817 11:0f8ae10b308d 306 fillrect(xc-rx, yc+ry+1, width, 1-height, colour);
stevew817 11:0f8ae10b308d 307 ry -= height-1;
stevew817 11:0f8ae10b308d 308 height = 1;
stevew817 11:0f8ae10b308d 309 } else {
stevew817 11:0f8ae10b308d 310 fillrect(xc-rx, yc-ry, width, ry*2+1, colour);
stevew817 11:0f8ae10b308d 311 ry -= ry;
stevew817 11:0f8ae10b308d 312 height = 1;
stevew817 11:0f8ae10b308d 313 }
stevew817 11:0f8ae10b308d 314 incx();
stevew817 11:0f8ae10b308d 315 rx++;
stevew817 11:0f8ae10b308d 316 width += 2;
stevew817 11:0f8ae10b308d 317 } else if (t - a2*y > crit2) { // e(x+1/2,y-1) > 0
stevew817 11:0f8ae10b308d 318 incy();
stevew817 11:0f8ae10b308d 319 height++;
stevew817 11:0f8ae10b308d 320 } else {
stevew817 11:0f8ae10b308d 321 if (ry*2+1 > height*2) {
stevew817 11:0f8ae10b308d 322 fillrect(xc-rx, yc-ry, width, height, colour);
stevew817 11:0f8ae10b308d 323 fillrect(xc-rx, yc+ry+1, width, -height, colour);
stevew817 11:0f8ae10b308d 324 } else {
stevew817 11:0f8ae10b308d 325 fillrect(xc-rx, yc-ry, width, ry*2+1, colour);
stevew817 11:0f8ae10b308d 326 }
stevew817 11:0f8ae10b308d 327 incx();
stevew817 11:0f8ae10b308d 328 incy();
stevew817 11:0f8ae10b308d 329 rx++;
stevew817 11:0f8ae10b308d 330 width += 2;
stevew817 11:0f8ae10b308d 331 ry -= height;
stevew817 11:0f8ae10b308d 332 height = 1;
stevew817 11:0f8ae10b308d 333 }
stevew817 11:0f8ae10b308d 334 }
stevew817 11:0f8ae10b308d 335 if (ry > height) {
stevew817 11:0f8ae10b308d 336 fillrect(xc-rx, yc-ry, width, height, colour);
stevew817 11:0f8ae10b308d 337 fillrect(xc-rx, yc+ry+1, width, -height, colour);
stevew817 11:0f8ae10b308d 338 } else {
stevew817 11:0f8ae10b308d 339 fillrect(xc-rx, yc-ry, width, ry*2+1, colour);
stevew817 11:0f8ae10b308d 340 }
stevew817 11:0f8ae10b308d 341 }
stevew817 11:0f8ae10b308d 342
stevew817 11:0f8ae10b308d 343
stevew817 11:0f8ae10b308d 344 void GraphicsDisplay::line(int x0, int y0, int x1, int y1, int colour) {
stevew817 11:0f8ae10b308d 345 //window(x0, y, w, h);
stevew817 11:0f8ae10b308d 346 int dx = 0, dy = 0;
stevew817 11:0f8ae10b308d 347 int dx_sym = 0, dy_sym = 0;
stevew817 11:0f8ae10b308d 348 int dx_x2 = 0, dy_x2 = 0;
stevew817 11:0f8ae10b308d 349 int di = 0;
stevew817 11:0f8ae10b308d 350 dx = x1-x0;
stevew817 11:0f8ae10b308d 351 dy = y1-y0;
stevew817 11:0f8ae10b308d 352
stevew817 11:0f8ae10b308d 353 if (dx == 0) { /* vertical line */
stevew817 11:0f8ae10b308d 354 if (y1 > y0) vline(x0,y0,y1,colour);
stevew817 11:0f8ae10b308d 355 else vline(x0,y1,y0,colour);
stevew817 11:0f8ae10b308d 356 return;
stevew817 11:0f8ae10b308d 357 }
stevew817 11:0f8ae10b308d 358 if (dx > 0) {
stevew817 11:0f8ae10b308d 359 dx_sym = 1;
stevew817 11:0f8ae10b308d 360 } else {
stevew817 11:0f8ae10b308d 361 dx_sym = -1;
stevew817 11:0f8ae10b308d 362 }
stevew817 11:0f8ae10b308d 363 if (dy == 0) { /* horizontal line */
stevew817 11:0f8ae10b308d 364 if (x1 > x0) hline(x0,x1,y0,colour);
stevew817 11:0f8ae10b308d 365 else hline(x1,x0,y0,colour);
stevew817 11:0f8ae10b308d 366 return;
stevew817 11:0f8ae10b308d 367 }
stevew817 11:0f8ae10b308d 368 if (dy > 0) {
stevew817 11:0f8ae10b308d 369 dy_sym = 1;
stevew817 11:0f8ae10b308d 370 } else {
stevew817 11:0f8ae10b308d 371 dy_sym = -1;
stevew817 11:0f8ae10b308d 372 }
stevew817 11:0f8ae10b308d 373 dx = dx_sym*dx;
stevew817 11:0f8ae10b308d 374 dy = dy_sym*dy;
stevew817 11:0f8ae10b308d 375 dx_x2 = dx*2;
stevew817 11:0f8ae10b308d 376 dy_x2 = dy*2;
stevew817 11:0f8ae10b308d 377 if (dx >= dy) {
stevew817 11:0f8ae10b308d 378 di = dy_x2 - dx;
stevew817 11:0f8ae10b308d 379 while (x0 != x1) {
stevew817 11:0f8ae10b308d 380
stevew817 11:0f8ae10b308d 381 pixel(x0, y0, colour);
stevew817 11:0f8ae10b308d 382 x0 += dx_sym;
stevew817 11:0f8ae10b308d 383 if (di<0) {
stevew817 11:0f8ae10b308d 384 di += dy_x2;
stevew817 11:0f8ae10b308d 385 } else {
stevew817 11:0f8ae10b308d 386 di += dy_x2 - dx_x2;
stevew817 11:0f8ae10b308d 387 y0 += dy_sym;
stevew817 11:0f8ae10b308d 388 }
stevew817 11:0f8ae10b308d 389 }
stevew817 11:0f8ae10b308d 390 pixel(x0, y0, colour);
stevew817 11:0f8ae10b308d 391 } else {
stevew817 11:0f8ae10b308d 392 di = dx_x2 - dy;
stevew817 11:0f8ae10b308d 393 while (y0 != y1) {
stevew817 11:0f8ae10b308d 394 pixel(x0, y0, colour);
stevew817 11:0f8ae10b308d 395 y0 += dy_sym;
stevew817 11:0f8ae10b308d 396 if (di < 0) {
stevew817 11:0f8ae10b308d 397 di += dx_x2;
stevew817 11:0f8ae10b308d 398 } else {
stevew817 11:0f8ae10b308d 399 di += dx_x2 - dy_x2;
stevew817 11:0f8ae10b308d 400 x0 += dx_sym;
stevew817 11:0f8ae10b308d 401 }
stevew817 11:0f8ae10b308d 402 }
stevew817 11:0f8ae10b308d 403 pixel(x0, y0, colour);
stevew817 11:0f8ae10b308d 404 }
stevew817 11:0f8ae10b308d 405 return;
stevew817 11:0f8ae10b308d 406 }
stevew817 11:0f8ae10b308d 407
stevew817 11:0f8ae10b308d 408 void GraphicsDisplay::hline(int x0, int x1, int y, int colour) {
stevew817 11:0f8ae10b308d 409 int w;
stevew817 11:0f8ae10b308d 410 w = x1 - x0 + 1;
stevew817 11:0f8ae10b308d 411 window(x0,y,w,1);
stevew817 11:0f8ae10b308d 412 for (int x=0; x<w; x++) {
stevew817 11:0f8ae10b308d 413 putp(colour);
stevew817 11:0f8ae10b308d 414 }
stevew817 11:0f8ae10b308d 415 return;
stevew817 11:0f8ae10b308d 416 }
stevew817 11:0f8ae10b308d 417
stevew817 11:0f8ae10b308d 418 void GraphicsDisplay::vline(int x, int y0, int y1, int colour) {
stevew817 11:0f8ae10b308d 419 int h;
stevew817 11:0f8ae10b308d 420 h = y1 - y0 + 1;
stevew817 11:0f8ae10b308d 421 window(x,y0,1,h);
stevew817 11:0f8ae10b308d 422 for (int y=0; y<h; y++) {
stevew817 11:0f8ae10b308d 423 putp(colour);
stevew817 11:0f8ae10b308d 424 }
stevew817 11:0f8ae10b308d 425 return;
stevew817 11:0f8ae10b308d 426 }
stevew817 11:0f8ae10b308d 427
Steven Cooreman 0:a0faa86660d4 428 void GraphicsDisplay::cls() {
Steven Cooreman 0:a0faa86660d4 429 fill(0, 0, width(), height(), _background);
Steven Cooreman 0:a0faa86660d4 430 }
Steven Cooreman 0:a0faa86660d4 431
Steven Cooreman 0:a0faa86660d4 432 void GraphicsDisplay::blit(int x, int y, int w, int h, const int *colour) {
Steven Cooreman 0:a0faa86660d4 433 window(x, y, w, h);
Steven Cooreman 0:a0faa86660d4 434 for(int i=0; i<w*h; i++) {
Steven Cooreman 0:a0faa86660d4 435 putp(colour[i]);
Steven Cooreman 0:a0faa86660d4 436 }
Steven Cooreman 0:a0faa86660d4 437 }
Steven Cooreman 0:a0faa86660d4 438
Steven Cooreman 0:a0faa86660d4 439 void GraphicsDisplay::blitbit(int x, int y, int w, int h, const char* colour) {
Steven Cooreman 0:a0faa86660d4 440 window(x, y, w, h);
Steven Cooreman 0:a0faa86660d4 441 for(int i = 0; i < w*h; i++) {
Steven Cooreman 0:a0faa86660d4 442 char byte = colour[i >> 3];
Steven Cooreman 0:a0faa86660d4 443 int offset = i & 0x7;
Steven Cooreman 0:a0faa86660d4 444 int c = ((byte << (offset)) & 0x80) ? _foreground : _background;
Steven Cooreman 0:a0faa86660d4 445 putp(c);
Steven Cooreman 0:a0faa86660d4 446 }
Steven Cooreman 0:a0faa86660d4 447 }
Steven Cooreman 0:a0faa86660d4 448
Steven Cooreman 0:a0faa86660d4 449 int GraphicsDisplay::columns() {
Steven Cooreman 0:a0faa86660d4 450 return width() / 8;
Steven Cooreman 0:a0faa86660d4 451 }
Steven Cooreman 0:a0faa86660d4 452
Steven Cooreman 0:a0faa86660d4 453 int GraphicsDisplay::rows() {
Steven Cooreman 0:a0faa86660d4 454 return height() / 8;
Steven Cooreman 0:a0faa86660d4 455 }
Steven Cooreman 0:a0faa86660d4 456