Library for interfacing to Nokia 5110 LCD display (as found on the SparkFun website).

Dependents:   LV7_LCDtest LV7_Grupa5_Tim003_Zadatak1 lv7_Grupa5_Tim008_zad1 LV7_PAI_Grupa5_tim10_Zadatak1 ... more

This library is designed to make it easy to interface an mbed with a Nokia 5110 LCD display.

These can be found at Sparkfun (https://www.sparkfun.com/products/10168) and Adafruit (http://www.adafruit.com/product/338).

The library uses the SPI peripheral on the mbed which means it is much faster sending data to the display than other libraries available on other platforms that use software SPI.

The library can print strings as well as controlling individual pixels, meaning that both text and primitive graphics can be displayed.

Committer:
valavanisalex
Date:
Tue Mar 21 10:43:19 2017 +0000
Revision:
42:596c207519de
Parent:
36:00ebd449b6f3
Child:
43:c2598020fcac
setPixel() now accepts a state parameter.  clearPixel() deprecated

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eencae 0:d563e74f0ae9 1 #include "mbed.h"
eencae 0:d563e74f0ae9 2 #include "N5110.h"
eencae 0:d563e74f0ae9 3
eencae 21:4cbdc20fea9f 4 // overloaded constructor includes power pin - LCD Vcc connected to GPIO pin
eencae 21:4cbdc20fea9f 5 // this constructor works fine with LPC1768 - enough current sourced from GPIO
eencae 21:4cbdc20fea9f 6 // to power LCD. Doesn't work well with K64F.
valavanisalex 29:5bc91bd44c77 7 N5110::N5110(PinName const pwrPin,
valavanisalex 29:5bc91bd44c77 8 PinName const scePin,
valavanisalex 29:5bc91bd44c77 9 PinName const rstPin,
valavanisalex 29:5bc91bd44c77 10 PinName const dcPin,
valavanisalex 29:5bc91bd44c77 11 PinName const mosiPin,
valavanisalex 29:5bc91bd44c77 12 PinName const sclkPin,
valavanisalex 29:5bc91bd44c77 13 PinName const ledPin)
valavanisalex 32:c9643726edca 14 :
valavanisalex 32:c9643726edca 15 _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
valavanisalex 32:c9643726edca 16 _led(new PwmOut(ledPin)),
valavanisalex 32:c9643726edca 17 _pwr(new DigitalOut(pwrPin)),
valavanisalex 32:c9643726edca 18 _sce(new DigitalOut(scePin)),
valavanisalex 32:c9643726edca 19 _rst(new DigitalOut(rstPin)),
valavanisalex 32:c9643726edca 20 _dc(new DigitalOut(dcPin))
valavanisalex 32:c9643726edca 21 {}
eencae 0:d563e74f0ae9 22
eencae 21:4cbdc20fea9f 23 // overloaded constructor does not include power pin - LCD Vcc must be tied to +3V3
eencae 21:4cbdc20fea9f 24 // Best to use this with K64F as the GPIO hasn't sufficient output current to reliably
eencae 21:4cbdc20fea9f 25 // drive the LCD.
valavanisalex 29:5bc91bd44c77 26 N5110::N5110(PinName const scePin,
valavanisalex 29:5bc91bd44c77 27 PinName const rstPin,
valavanisalex 29:5bc91bd44c77 28 PinName const dcPin,
valavanisalex 29:5bc91bd44c77 29 PinName const mosiPin,
valavanisalex 29:5bc91bd44c77 30 PinName const sclkPin,
valavanisalex 29:5bc91bd44c77 31 PinName const ledPin)
valavanisalex 32:c9643726edca 32 :
valavanisalex 32:c9643726edca 33 _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
valavanisalex 32:c9643726edca 34 _led(new PwmOut(ledPin)),
valavanisalex 32:c9643726edca 35 _pwr(NULL), // pwr not needed so null it to be safe
valavanisalex 32:c9643726edca 36 _sce(new DigitalOut(scePin)),
valavanisalex 32:c9643726edca 37 _rst(new DigitalOut(rstPin)),
valavanisalex 32:c9643726edca 38 _dc(new DigitalOut(dcPin))
valavanisalex 32:c9643726edca 39 {}
eencae 21:4cbdc20fea9f 40
valavanisalex 31:8a0c21042f82 41 N5110::~N5110()
valavanisalex 31:8a0c21042f82 42 {
valavanisalex 31:8a0c21042f82 43 delete _spi;
valavanisalex 31:8a0c21042f82 44
valavanisalex 31:8a0c21042f82 45 if(_pwr) {
valavanisalex 31:8a0c21042f82 46 delete _pwr;
valavanisalex 31:8a0c21042f82 47 }
valavanisalex 31:8a0c21042f82 48
valavanisalex 31:8a0c21042f82 49 delete _led;
valavanisalex 31:8a0c21042f82 50 delete _sce;
valavanisalex 31:8a0c21042f82 51 delete _rst;
valavanisalex 31:8a0c21042f82 52 delete _dc;
valavanisalex 31:8a0c21042f82 53 }
valavanisalex 31:8a0c21042f82 54
eencae 6:adb79338d40f 55 // initialise function - powers up and sends the initialisation commands
eencae 0:d563e74f0ae9 56 void N5110::init()
eencae 0:d563e74f0ae9 57 {
eencae 24:342bdb6679a1 58 turnOn(); // power up
eencae 24:342bdb6679a1 59 reset(); // reset LCD - must be done within 100 ms
eencae 0:d563e74f0ae9 60
eencae 24:342bdb6679a1 61 initSPI();
eencae 24:342bdb6679a1 62 // function set - extended
eencae 24:342bdb6679a1 63 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE);
eencae 24:342bdb6679a1 64 // Don't completely understand these parameters - they seem to work as they are
eencae 24:342bdb6679a1 65 // Consult the datasheet if you need to change them
eencae 24:342bdb6679a1 66 sendCommand(CMD_VOP_7V38); // operating voltage - these values are from Chris Yan's Library
eencae 24:342bdb6679a1 67 sendCommand(CMD_TC_TEMP_2); // temperature control
eencae 24:342bdb6679a1 68 sendCommand(CMD_BI_MUX_48); // changing this can sometimes improve the contrast on some displays
eencae 0:d563e74f0ae9 69
eencae 24:342bdb6679a1 70 // function set - basic
eencae 24:342bdb6679a1 71 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE);
eencae 24:342bdb6679a1 72 normalMode(); // normal video mode by default
eencae 24:342bdb6679a1 73 sendCommand(CMD_DC_NORMAL_MODE); // black on white
eencae 0:d563e74f0ae9 74
eencae 24:342bdb6679a1 75 clearRAM(); // RAM is undefined at power-up so clear
eencae 24:342bdb6679a1 76 clear(); // clear buffer
eencae 24:342bdb6679a1 77 setBrightness(0.5);
eencae 0:d563e74f0ae9 78 }
eencae 13:908644099648 79
eencae 13:908644099648 80 // sets normal video mode (black on white)
eencae 13:908644099648 81 void N5110::normalMode()
eencae 13:908644099648 82 {
eencae 24:342bdb6679a1 83 sendCommand(CMD_DC_NORMAL_MODE);
eencae 1:df68f34cd32d 84 }
eencae 1:df68f34cd32d 85
eencae 13:908644099648 86 // sets normal video mode (white on black)
eencae 13:908644099648 87 void N5110::inverseMode()
eencae 13:908644099648 88 {
eencae 24:342bdb6679a1 89 sendCommand(CMD_DC_INVERT_VIDEO);
eencae 1:df68f34cd32d 90 }
eencae 0:d563e74f0ae9 91
eencae 24:342bdb6679a1 92 // function to power up the LCD and backlight - only works when using GPIO to power
eencae 0:d563e74f0ae9 93 void N5110::turnOn()
eencae 0:d563e74f0ae9 94 {
valavanisalex 29:5bc91bd44c77 95 if (_pwr != NULL) {
valavanisalex 29:5bc91bd44c77 96 _pwr->write(1); // apply power
eencae 24:342bdb6679a1 97 }
eencae 0:d563e74f0ae9 98 }
eencae 0:d563e74f0ae9 99
eencae 0:d563e74f0ae9 100 // function to power down LCD
eencae 0:d563e74f0ae9 101 void N5110::turnOff()
eencae 0:d563e74f0ae9 102 {
eencae 24:342bdb6679a1 103 clear(); // clear buffer
eencae 24:342bdb6679a1 104 refresh();
eencae 24:342bdb6679a1 105 setBrightness(0.0); // turn backlight off
eencae 24:342bdb6679a1 106 clearRAM(); // clear RAM to ensure specified current consumption
eencae 24:342bdb6679a1 107 // send command to ensure we are in basic mode
eencae 24:342bdb6679a1 108 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE);
eencae 24:342bdb6679a1 109 // clear the display
eencae 24:342bdb6679a1 110 sendCommand(CMD_DC_CLEAR_DISPLAY);
eencae 24:342bdb6679a1 111 // enter the extended mode and power down
eencae 24:342bdb6679a1 112 sendCommand(0x20 | CMD_FS_POWER_DOWN_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE);
eencae 24:342bdb6679a1 113 // small delay and then turn off the power pin
eencae 24:342bdb6679a1 114 wait_ms(10);
eencae 23:eb7e6632fc9e 115
eencae 24:342bdb6679a1 116 // if we are powering the LCD using the GPIO then make it low to turn off
valavanisalex 29:5bc91bd44c77 117 if (_pwr != NULL) {
valavanisalex 29:5bc91bd44c77 118 _pwr->write(0); // turn off power
eencae 24:342bdb6679a1 119 }
eencae 0:d563e74f0ae9 120
eencae 0:d563e74f0ae9 121 }
eencae 0:d563e74f0ae9 122
eencae 0:d563e74f0ae9 123 // function to change LED backlight brightness
eencae 0:d563e74f0ae9 124 void N5110::setBrightness(float brightness)
eencae 0:d563e74f0ae9 125 {
eencae 24:342bdb6679a1 126 // check whether brightness is within range
eencae 24:342bdb6679a1 127 if (brightness < 0.0f)
eencae 24:342bdb6679a1 128 brightness = 0.0f;
eencae 24:342bdb6679a1 129 if (brightness > 1.0f)
eencae 24:342bdb6679a1 130 brightness = 1.0f;
eencae 24:342bdb6679a1 131 // set PWM duty cycle
valavanisalex 29:5bc91bd44c77 132 _led->write(brightness);
eencae 0:d563e74f0ae9 133 }
eencae 0:d563e74f0ae9 134
eencae 0:d563e74f0ae9 135
eencae 0:d563e74f0ae9 136 // pulse the active low reset line
eencae 0:d563e74f0ae9 137 void N5110::reset()
eencae 0:d563e74f0ae9 138 {
valavanisalex 29:5bc91bd44c77 139 _rst->write(0); // reset the LCD
valavanisalex 29:5bc91bd44c77 140 _rst->write(1);
eencae 0:d563e74f0ae9 141 }
eencae 0:d563e74f0ae9 142
eencae 0:d563e74f0ae9 143 // function to initialise SPI peripheral
eencae 0:d563e74f0ae9 144 void N5110::initSPI()
eencae 0:d563e74f0ae9 145 {
valavanisalex 29:5bc91bd44c77 146 _spi->format(8,1); // 8 bits, Mode 1 - polarity 0, phase 1 - base value of clock is 0, data captured on falling edge/propagated on rising edge
valavanisalex 29:5bc91bd44c77 147 _spi->frequency(4000000); // maximum of screen is 4 MHz
eencae 0:d563e74f0ae9 148 }
eencae 0:d563e74f0ae9 149
eencae 6:adb79338d40f 150 // send a command to the display
eencae 0:d563e74f0ae9 151 void N5110::sendCommand(unsigned char command)
eencae 0:d563e74f0ae9 152 {
valavanisalex 29:5bc91bd44c77 153 _dc->write(0); // set DC low for command
valavanisalex 29:5bc91bd44c77 154 _sce->write(0); // set CE low to begin frame
valavanisalex 29:5bc91bd44c77 155 _spi->write(command); // send command
valavanisalex 29:5bc91bd44c77 156 _dc->write(1); // turn back to data by default
valavanisalex 29:5bc91bd44c77 157 _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
eencae 0:d563e74f0ae9 158 }
eencae 0:d563e74f0ae9 159
eencae 6:adb79338d40f 160 // send data to the display at the current XY address
eencae 6:adb79338d40f 161 // dc is set to 1 (i.e. data) after sending a command and so should
eencae 6:adb79338d40f 162 // be the default mode.
eencae 0:d563e74f0ae9 163 void N5110::sendData(unsigned char data)
eencae 0:d563e74f0ae9 164 {
valavanisalex 29:5bc91bd44c77 165 _sce->write(0); // set CE low to begin frame
valavanisalex 29:5bc91bd44c77 166 _spi->write(data);
valavanisalex 29:5bc91bd44c77 167 _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
eencae 0:d563e74f0ae9 168 }
eencae 0:d563e74f0ae9 169
eencae 0:d563e74f0ae9 170 // this function writes 0 to the 504 bytes to clear the RAM
eencae 0:d563e74f0ae9 171 void N5110::clearRAM()
eencae 0:d563e74f0ae9 172 {
valavanisalex 29:5bc91bd44c77 173 _sce->write(0); //set CE low to begin frame
eencae 24:342bdb6679a1 174 for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
valavanisalex 29:5bc91bd44c77 175 _spi->write(0x00); // send 0's
eencae 24:342bdb6679a1 176 }
valavanisalex 29:5bc91bd44c77 177 _sce->write(1); // set CE high to end frame
eencae 0:d563e74f0ae9 178 }
eencae 0:d563e74f0ae9 179
eencae 13:908644099648 180 // function to set the XY address in RAM for subsequenct data write
valavanisalex 29:5bc91bd44c77 181 void N5110::setXYAddress(unsigned int const x,
valavanisalex 29:5bc91bd44c77 182 unsigned int const y)
eencae 0:d563e74f0ae9 183 {
valavanisalex 29:5bc91bd44c77 184 if (x<WIDTH && y<HEIGHT) { // check within range
eencae 24:342bdb6679a1 185 sendCommand(0x80 | x); // send addresses to display with relevant mask
eencae 24:342bdb6679a1 186 sendCommand(0x40 | y);
eencae 24:342bdb6679a1 187 }
eencae 0:d563e74f0ae9 188 }
eencae 0:d563e74f0ae9 189
eencae 6:adb79338d40f 190 // These functions are used to set, clear and get the value of pixels in the display
eencae 6:adb79338d40f 191 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh()
eencae 6:adb79338d40f 192 // function must be called after set and clear in order to update the display
valavanisalex 29:5bc91bd44c77 193 void N5110::setPixel(unsigned int const x,
valavanisalex 42:596c207519de 194 unsigned int const y,
valavanisalex 42:596c207519de 195 bool const state)
eencae 0:d563e74f0ae9 196 {
valavanisalex 29:5bc91bd44c77 197 if (x<WIDTH && y<HEIGHT) { // check within range
eencae 24:342bdb6679a1 198 // calculate bank and shift 1 to required position in the data byte
valavanisalex 42:596c207519de 199 if(state) buffer[x][y/8] |= (1 << y%8);
valavanisalex 42:596c207519de 200 else buffer[x][y/8] &= ~(1 << y%8);
eencae 24:342bdb6679a1 201 }
eencae 0:d563e74f0ae9 202 }
eencae 0:d563e74f0ae9 203
valavanisalex 29:5bc91bd44c77 204 void N5110::clearPixel(unsigned int const x,
valavanisalex 29:5bc91bd44c77 205 unsigned int const y)
eencae 0:d563e74f0ae9 206 {
valavanisalex 29:5bc91bd44c77 207 if (x<WIDTH && y<HEIGHT) { // check within range
eencae 24:342bdb6679a1 208 // calculate bank and shift 1 to required position (using bit clear)
eencae 24:342bdb6679a1 209 buffer[x][y/8] &= ~(1 << y%8);
eencae 24:342bdb6679a1 210 }
eencae 0:d563e74f0ae9 211 }
eencae 0:d563e74f0ae9 212
valavanisalex 29:5bc91bd44c77 213 int N5110::getPixel(unsigned int const x,
valavanisalex 29:5bc91bd44c77 214 unsigned int const y) const
eencae 0:d563e74f0ae9 215 {
valavanisalex 29:5bc91bd44c77 216 if (x<WIDTH && y<HEIGHT) { // check within range
eencae 24:342bdb6679a1 217 // return relevant bank and mask required bit
eencae 24:342bdb6679a1 218
eencae 24:342bdb6679a1 219 int pixel = (int) buffer[x][y/8] & (1 << y%8);
eencae 24:342bdb6679a1 220
eencae 24:342bdb6679a1 221 if (pixel)
eencae 24:342bdb6679a1 222 return 1;
eencae 24:342bdb6679a1 223 else
eencae 24:342bdb6679a1 224 return 0;
eencae 24:342bdb6679a1 225 }
eencae 24:342bdb6679a1 226
eencae 23:eb7e6632fc9e 227 return 0;
eencae 24:342bdb6679a1 228
eencae 0:d563e74f0ae9 229 }
eencae 0:d563e74f0ae9 230
eencae 6:adb79338d40f 231 // function to refresh the display
eencae 6:adb79338d40f 232 void N5110::refresh()
eencae 0:d563e74f0ae9 233 {
eencae 24:342bdb6679a1 234 setXYAddress(0,0); // important to set address back to 0,0 before refreshing display
eencae 24:342bdb6679a1 235 // address auto increments after printing string, so buffer[0][0] will not coincide
eencae 24:342bdb6679a1 236 // with top-left pixel after priting string
eencae 13:908644099648 237
valavanisalex 29:5bc91bd44c77 238 _sce->write(0); //set CE low to begin frame
eencae 13:908644099648 239
eencae 24:342bdb6679a1 240 for(int j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing
eencae 24:342bdb6679a1 241 for(int i = 0; i < WIDTH; i++) {
valavanisalex 29:5bc91bd44c77 242 _spi->write(buffer[i][j]); // send buffer
eencae 24:342bdb6679a1 243 }
eencae 0:d563e74f0ae9 244 }
valavanisalex 29:5bc91bd44c77 245 _sce->write(1); // set CE high to end frame
eencae 0:d563e74f0ae9 246
eencae 0:d563e74f0ae9 247 }
eencae 0:d563e74f0ae9 248
eencae 6:adb79338d40f 249 // fills the buffer with random bytes. Can be used to test the display.
eencae 6:adb79338d40f 250 // The rand() function isn't seeded so it probably creates the same pattern everytime
eencae 0:d563e74f0ae9 251 void N5110::randomiseBuffer()
eencae 0:d563e74f0ae9 252 {
eencae 24:342bdb6679a1 253 int i,j;
eencae 24:342bdb6679a1 254 for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing
eencae 24:342bdb6679a1 255 for(i = 0; i < WIDTH; i++) {
eencae 24:342bdb6679a1 256 buffer[i][j] = rand()%256; // generate random byte
eencae 24:342bdb6679a1 257 }
eencae 0:d563e74f0ae9 258 }
eencae 0:d563e74f0ae9 259
eencae 0:d563e74f0ae9 260 }
eencae 0:d563e74f0ae9 261
eencae 0:d563e74f0ae9 262 // function to print 5x7 font
valavanisalex 29:5bc91bd44c77 263 void N5110::printChar(char const c,
valavanisalex 29:5bc91bd44c77 264 unsigned int const x,
valavanisalex 29:5bc91bd44c77 265 unsigned int const y)
eencae 0:d563e74f0ae9 266 {
valavanisalex 29:5bc91bd44c77 267 if (y<BANKS) { // check if printing in range of y banks
eencae 18:1af393359298 268
eencae 24:342bdb6679a1 269 for (int i = 0; i < 5 ; i++ ) {
eencae 24:342bdb6679a1 270 int pixel_x = x+i;
eencae 24:342bdb6679a1 271 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83)
eencae 24:342bdb6679a1 272 break;
eencae 24:342bdb6679a1 273 buffer[pixel_x][y] = font5x7[(c - 32)*5 + i];
eencae 24:342bdb6679a1 274 // array is offset by 32 relative to ASCII, each character is 5 pixels wide
eencae 24:342bdb6679a1 275 }
valavanisalex 29:5bc91bd44c77 276
eencae 23:eb7e6632fc9e 277 }
eencae 0:d563e74f0ae9 278 }
eencae 0:d563e74f0ae9 279
eencae 0:d563e74f0ae9 280 // function to print string at specified position
valavanisalex 29:5bc91bd44c77 281 void N5110::printString(const char *str,
valavanisalex 29:5bc91bd44c77 282 unsigned int const x,
valavanisalex 29:5bc91bd44c77 283 unsigned int const y)
eencae 0:d563e74f0ae9 284 {
valavanisalex 29:5bc91bd44c77 285 if (y<BANKS) { // check if printing in range of y banks
eencae 18:1af393359298 286
eencae 24:342bdb6679a1 287 int n = 0 ; // counter for number of characters in string
eencae 24:342bdb6679a1 288 // loop through string and print character
eencae 24:342bdb6679a1 289 while(*str) {
eencae 0:d563e74f0ae9 290
eencae 24:342bdb6679a1 291 // writes the character bitmap data to the buffer, so that
eencae 24:342bdb6679a1 292 // text and pixels can be displayed at the same time
eencae 24:342bdb6679a1 293 for (int i = 0; i < 5 ; i++ ) {
eencae 24:342bdb6679a1 294 int pixel_x = x+i+n*6;
eencae 24:342bdb6679a1 295 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83)
eencae 24:342bdb6679a1 296 break;
eencae 24:342bdb6679a1 297 buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i];
eencae 24:342bdb6679a1 298 }
eencae 24:342bdb6679a1 299 str++; // go to next character in string
eencae 24:342bdb6679a1 300 n++; // increment index
eencae 24:342bdb6679a1 301 }
eencae 23:eb7e6632fc9e 302 }
eencae 0:d563e74f0ae9 303 }
eencae 0:d563e74f0ae9 304
eencae 24:342bdb6679a1 305 // function to clear the screen buffer
eencae 0:d563e74f0ae9 306 void N5110::clear()
eencae 0:d563e74f0ae9 307 {
eencae 24:342bdb6679a1 308 memset(buffer,0,sizeof(buffer));
eencae 8:40abe5736eca 309 }
eencae 8:40abe5736eca 310
eencae 8:40abe5736eca 311 // function to plot array on display
valavanisalex 29:5bc91bd44c77 312 void N5110::plotArray(float const array[])
eencae 13:908644099648 313 {
eencae 24:342bdb6679a1 314 for (int i=0; i<WIDTH; i++) { // loop through array
eencae 24:342bdb6679a1 315 // elements are normalised from 0.0 to 1.0, so multiply
eencae 24:342bdb6679a1 316 // by 47 to convert to pixel range, and subtract from 47
eencae 24:342bdb6679a1 317 // since top-left is 0,0 in the display geometry
eencae 24:342bdb6679a1 318 setPixel(i,47 - int(array[i]*47.0f));
eencae 24:342bdb6679a1 319 }
eencae 13:908644099648 320
eencae 17:780a542d5f8b 321 }
eencae 13:908644099648 322
eencae 17:780a542d5f8b 323 // function to draw circle
valavanisalex 29:5bc91bd44c77 324 void N5110:: drawCircle(unsigned int const x0,
valavanisalex 29:5bc91bd44c77 325 unsigned int const y0,
valavanisalex 29:5bc91bd44c77 326 unsigned int const radius,
valavanisalex 33:d80e568a2e18 327 FillType const fill)
eencae 17:780a542d5f8b 328 {
eencae 24:342bdb6679a1 329 // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
eencae 24:342bdb6679a1 330 int x = radius;
eencae 24:342bdb6679a1 331 int y = 0;
eencae 24:342bdb6679a1 332 int radiusError = 1-x;
eencae 17:780a542d5f8b 333
eencae 24:342bdb6679a1 334 while(x >= y) {
eencae 17:780a542d5f8b 335
eencae 24:342bdb6679a1 336 // if transparent, just draw outline
valavanisalex 33:d80e568a2e18 337 if (fill == FILL_TRANSPARENT) {
eencae 24:342bdb6679a1 338 setPixel( x + x0, y + y0);
eencae 24:342bdb6679a1 339 setPixel(-x + x0, y + y0);
eencae 24:342bdb6679a1 340 setPixel( y + x0, x + y0);
eencae 24:342bdb6679a1 341 setPixel(-y + x0, x + y0);
eencae 24:342bdb6679a1 342 setPixel(-y + x0, -x + y0);
eencae 24:342bdb6679a1 343 setPixel( y + x0, -x + y0);
eencae 24:342bdb6679a1 344 setPixel( x + x0, -y + y0);
eencae 24:342bdb6679a1 345 setPixel(-x + x0, -y + y0);
eencae 24:342bdb6679a1 346 } else { // drawing filled circle, so draw lines between points at same y value
eencae 17:780a542d5f8b 347
valavanisalex 33:d80e568a2e18 348 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill
eencae 17:780a542d5f8b 349
eencae 24:342bdb6679a1 350 drawLine(x+x0,y+y0,-x+x0,y+y0,type);
eencae 24:342bdb6679a1 351 drawLine(y+x0,x+y0,-y+x0,x+y0,type);
eencae 24:342bdb6679a1 352 drawLine(y+x0,-x+y0,-y+x0,-x+y0,type);
eencae 24:342bdb6679a1 353 drawLine(x+x0,-y+y0,-x+x0,-y+y0,type);
eencae 24:342bdb6679a1 354 }
eencae 17:780a542d5f8b 355
eencae 24:342bdb6679a1 356 y++;
eencae 24:342bdb6679a1 357 if (radiusError<0) {
eencae 24:342bdb6679a1 358 radiusError += 2 * y + 1;
eencae 24:342bdb6679a1 359 } else {
eencae 24:342bdb6679a1 360 x--;
eencae 24:342bdb6679a1 361 radiusError += 2 * (y - x) + 1;
eencae 24:342bdb6679a1 362 }
eencae 17:780a542d5f8b 363 }
eencae 17:780a542d5f8b 364
eencae 17:780a542d5f8b 365 }
eencae 17:780a542d5f8b 366
valavanisalex 29:5bc91bd44c77 367 void N5110::drawLine(unsigned int const x0,
valavanisalex 29:5bc91bd44c77 368 unsigned int const y0,
valavanisalex 29:5bc91bd44c77 369 unsigned int const x1,
valavanisalex 29:5bc91bd44c77 370 unsigned int const y1,
valavanisalex 29:5bc91bd44c77 371 unsigned int const type)
eencae 17:780a542d5f8b 372 {
eencae 24:342bdb6679a1 373 int y_range = y1-y0; // calc range of y and x
eencae 24:342bdb6679a1 374 int x_range = x1-x0;
eencae 24:342bdb6679a1 375 int start,stop,step;
eencae 17:780a542d5f8b 376
eencae 24:342bdb6679a1 377 // if dotted line, set step to 2, else step is 1
eencae 24:342bdb6679a1 378 step = (type==2) ? 2:1;
eencae 17:780a542d5f8b 379
eencae 24:342bdb6679a1 380 // make sure we loop over the largest range to get the most pixels on the display
eencae 24:342bdb6679a1 381 // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
eencae 24:342bdb6679a1 382 // or else we'll only end up with 1 pixel in the x column
eencae 24:342bdb6679a1 383 if ( abs(x_range) > abs(y_range) ) {
eencae 17:780a542d5f8b 384
eencae 24:342bdb6679a1 385 // ensure we loop from smallest to largest or else for-loop won't run as expected
eencae 24:342bdb6679a1 386 start = x1>x0 ? x0:x1;
eencae 24:342bdb6679a1 387 stop = x1>x0 ? x1:x0;
eencae 17:780a542d5f8b 388
eencae 24:342bdb6679a1 389 // loop between x pixels
eencae 24:342bdb6679a1 390 for (int x = start; x<= stop ; x+=step) {
eencae 24:342bdb6679a1 391 // do linear interpolation
eencae 24:342bdb6679a1 392 int y = y0 + (y1-y0)*(x-x0)/(x1-x0);
eencae 17:780a542d5f8b 393
valavanisalex 42:596c207519de 394 // If the line type is '0', this will clear the pixel
valavanisalex 42:596c207519de 395 // If it is '1' or '2', the pixel will be set
valavanisalex 42:596c207519de 396 setPixel(x,y, type);
eencae 24:342bdb6679a1 397 }
eencae 24:342bdb6679a1 398 } else {
eencae 17:780a542d5f8b 399
eencae 24:342bdb6679a1 400 // ensure we loop from smallest to largest or else for-loop won't run as expected
eencae 24:342bdb6679a1 401 start = y1>y0 ? y0:y1;
eencae 24:342bdb6679a1 402 stop = y1>y0 ? y1:y0;
eencae 17:780a542d5f8b 403
eencae 24:342bdb6679a1 404 for (int y = start; y<= stop ; y+=step) {
eencae 24:342bdb6679a1 405 // do linear interpolation
eencae 24:342bdb6679a1 406 int x = x0 + (x1-x0)*(y-y0)/(y1-y0);
eencae 17:780a542d5f8b 407
valavanisalex 42:596c207519de 408 // If the line type is '0', this will clear the pixel
valavanisalex 42:596c207519de 409 // If it is '1' or '2', the pixel will be set
valavanisalex 42:596c207519de 410 setPixel(x,y, type);
eencae 24:342bdb6679a1 411 }
eencae 17:780a542d5f8b 412 }
eencae 17:780a542d5f8b 413
eencae 17:780a542d5f8b 414 }
eencae 17:780a542d5f8b 415
valavanisalex 29:5bc91bd44c77 416 void N5110::drawRect(unsigned int const x0,
valavanisalex 29:5bc91bd44c77 417 unsigned int const y0,
valavanisalex 29:5bc91bd44c77 418 unsigned int const width,
valavanisalex 29:5bc91bd44c77 419 unsigned int const height,
valavanisalex 33:d80e568a2e18 420 FillType const fill)
eencae 17:780a542d5f8b 421 {
valavanisalex 33:d80e568a2e18 422 if (fill == FILL_TRANSPARENT) { // transparent, just outline
eencae 27:0d8d90936b4c 423 drawLine(x0,y0,x0+(width-1),y0,1); // top
eencae 27:0d8d90936b4c 424 drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),1); // bottom
eencae 27:0d8d90936b4c 425 drawLine(x0,y0,x0,y0+(height-1),1); // left
eencae 27:0d8d90936b4c 426 drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),1); // right
eencae 24:342bdb6679a1 427 } else { // filled rectangle
valavanisalex 33:d80e568a2e18 428 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill
eencae 27:0d8d90936b4c 429 for (int y = y0; y<y0+height; y++) { // loop through rows of rectangle
eencae 27:0d8d90936b4c 430 drawLine(x0,y,x0+(width-1),y,type); // draw line across screen
eencae 24:342bdb6679a1 431 }
eencae 17:780a542d5f8b 432 }
eencae 35:2d5931a66fba 433 }
eencae 35:2d5931a66fba 434
eencae 36:00ebd449b6f3 435 void N5110::drawSprite(int x0,
valavanisalex 42:596c207519de 436 int y0,
valavanisalex 42:596c207519de 437 int nrows,
valavanisalex 42:596c207519de 438 int ncols,
valavanisalex 42:596c207519de 439 int *sprite)
eencae 36:00ebd449b6f3 440 {
eencae 36:00ebd449b6f3 441 for (int i = 0; i < nrows; i++) {
eencae 36:00ebd449b6f3 442 for (int j = 0 ; j < ncols ; j++) {
eencae 35:2d5931a66fba 443
eencae 36:00ebd449b6f3 444 int pixel = *((sprite+i*ncols)+j);
valavanisalex 42:596c207519de 445 setPixel(x0+j,y0+i, pixel);
eencae 35:2d5931a66fba 446 }
eencae 35:2d5931a66fba 447 }
valavanisalex 29:5bc91bd44c77 448 }