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:
Thu Feb 16 15:36:44 2017 +0000
Revision:
31:8a0c21042f82
Parent:
29:5bc91bd44c77
Child:
32:c9643726edca
Add a destructor to free allocated memory

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)
eencae 0:d563e74f0ae9 14 {
eencae 24:342bdb6679a1 15 // set up pins as required
valavanisalex 29:5bc91bd44c77 16 _spi = new SPI(mosiPin,NC,sclkPin); // create new SPI instance and initialise
valavanisalex 29:5bc91bd44c77 17 _led = new PwmOut(ledPin);
valavanisalex 29:5bc91bd44c77 18 _pwr = new DigitalOut(pwrPin);
valavanisalex 29:5bc91bd44c77 19 _sce = new DigitalOut(scePin);
valavanisalex 29:5bc91bd44c77 20 _rst = new DigitalOut(rstPin);
valavanisalex 29:5bc91bd44c77 21 _dc = new DigitalOut(dcPin);
eencae 0:d563e74f0ae9 22 }
eencae 0:d563e74f0ae9 23
eencae 21:4cbdc20fea9f 24 // overloaded constructor does not include power pin - LCD Vcc must be tied to +3V3
eencae 21:4cbdc20fea9f 25 // Best to use this with K64F as the GPIO hasn't sufficient output current to reliably
eencae 21:4cbdc20fea9f 26 // drive the LCD.
valavanisalex 29:5bc91bd44c77 27 N5110::N5110(PinName const scePin,
valavanisalex 29:5bc91bd44c77 28 PinName const rstPin,
valavanisalex 29:5bc91bd44c77 29 PinName const dcPin,
valavanisalex 29:5bc91bd44c77 30 PinName const mosiPin,
valavanisalex 29:5bc91bd44c77 31 PinName const sclkPin,
valavanisalex 29:5bc91bd44c77 32 PinName const ledPin)
eencae 21:4cbdc20fea9f 33 {
eencae 24:342bdb6679a1 34 // set up pins as required
valavanisalex 29:5bc91bd44c77 35 _spi = new SPI(mosiPin,NC,sclkPin); // create new SPI instance and initialise
valavanisalex 29:5bc91bd44c77 36 _pwr = NULL; // pwr not needed so null it to be safe
valavanisalex 29:5bc91bd44c77 37 _led = new PwmOut(ledPin);
valavanisalex 29:5bc91bd44c77 38 _sce = new DigitalOut(scePin);
valavanisalex 29:5bc91bd44c77 39 _rst = new DigitalOut(rstPin);
valavanisalex 29:5bc91bd44c77 40 _dc = new DigitalOut(dcPin);
eencae 21:4cbdc20fea9f 41 }
eencae 21:4cbdc20fea9f 42
valavanisalex 31:8a0c21042f82 43 N5110::~N5110()
valavanisalex 31:8a0c21042f82 44 {
valavanisalex 31:8a0c21042f82 45 delete _spi;
valavanisalex 31:8a0c21042f82 46
valavanisalex 31:8a0c21042f82 47 if(_pwr) {
valavanisalex 31:8a0c21042f82 48 delete _pwr;
valavanisalex 31:8a0c21042f82 49 }
valavanisalex 31:8a0c21042f82 50
valavanisalex 31:8a0c21042f82 51 delete _led;
valavanisalex 31:8a0c21042f82 52 delete _sce;
valavanisalex 31:8a0c21042f82 53 delete _rst;
valavanisalex 31:8a0c21042f82 54 delete _dc;
valavanisalex 31:8a0c21042f82 55 }
valavanisalex 31:8a0c21042f82 56
eencae 6:adb79338d40f 57 // initialise function - powers up and sends the initialisation commands
eencae 0:d563e74f0ae9 58 void N5110::init()
eencae 0:d563e74f0ae9 59 {
eencae 24:342bdb6679a1 60 turnOn(); // power up
eencae 24:342bdb6679a1 61 reset(); // reset LCD - must be done within 100 ms
eencae 0:d563e74f0ae9 62
eencae 24:342bdb6679a1 63 initSPI();
eencae 24:342bdb6679a1 64 // function set - extended
eencae 24:342bdb6679a1 65 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE);
eencae 24:342bdb6679a1 66 // Don't completely understand these parameters - they seem to work as they are
eencae 24:342bdb6679a1 67 // Consult the datasheet if you need to change them
eencae 24:342bdb6679a1 68 sendCommand(CMD_VOP_7V38); // operating voltage - these values are from Chris Yan's Library
eencae 24:342bdb6679a1 69 sendCommand(CMD_TC_TEMP_2); // temperature control
eencae 24:342bdb6679a1 70 sendCommand(CMD_BI_MUX_48); // changing this can sometimes improve the contrast on some displays
eencae 0:d563e74f0ae9 71
eencae 24:342bdb6679a1 72 // function set - basic
eencae 24:342bdb6679a1 73 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE);
eencae 24:342bdb6679a1 74 normalMode(); // normal video mode by default
eencae 24:342bdb6679a1 75 sendCommand(CMD_DC_NORMAL_MODE); // black on white
eencae 0:d563e74f0ae9 76
eencae 24:342bdb6679a1 77 clearRAM(); // RAM is undefined at power-up so clear
eencae 24:342bdb6679a1 78 clear(); // clear buffer
eencae 24:342bdb6679a1 79 setBrightness(0.5);
eencae 0:d563e74f0ae9 80 }
eencae 13:908644099648 81
eencae 13:908644099648 82 // sets normal video mode (black on white)
eencae 13:908644099648 83 void N5110::normalMode()
eencae 13:908644099648 84 {
eencae 24:342bdb6679a1 85 sendCommand(CMD_DC_NORMAL_MODE);
eencae 1:df68f34cd32d 86 }
eencae 1:df68f34cd32d 87
eencae 13:908644099648 88 // sets normal video mode (white on black)
eencae 13:908644099648 89 void N5110::inverseMode()
eencae 13:908644099648 90 {
eencae 24:342bdb6679a1 91 sendCommand(CMD_DC_INVERT_VIDEO);
eencae 1:df68f34cd32d 92 }
eencae 0:d563e74f0ae9 93
eencae 24:342bdb6679a1 94 // function to power up the LCD and backlight - only works when using GPIO to power
eencae 0:d563e74f0ae9 95 void N5110::turnOn()
eencae 0:d563e74f0ae9 96 {
valavanisalex 29:5bc91bd44c77 97 if (_pwr != NULL) {
valavanisalex 29:5bc91bd44c77 98 _pwr->write(1); // apply power
eencae 24:342bdb6679a1 99 }
eencae 0:d563e74f0ae9 100 }
eencae 0:d563e74f0ae9 101
eencae 0:d563e74f0ae9 102 // function to power down LCD
eencae 0:d563e74f0ae9 103 void N5110::turnOff()
eencae 0:d563e74f0ae9 104 {
eencae 24:342bdb6679a1 105 clear(); // clear buffer
eencae 24:342bdb6679a1 106 refresh();
eencae 24:342bdb6679a1 107 setBrightness(0.0); // turn backlight off
eencae 24:342bdb6679a1 108 clearRAM(); // clear RAM to ensure specified current consumption
eencae 24:342bdb6679a1 109 // send command to ensure we are in basic mode
eencae 24:342bdb6679a1 110 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE);
eencae 24:342bdb6679a1 111 // clear the display
eencae 24:342bdb6679a1 112 sendCommand(CMD_DC_CLEAR_DISPLAY);
eencae 24:342bdb6679a1 113 // enter the extended mode and power down
eencae 24:342bdb6679a1 114 sendCommand(0x20 | CMD_FS_POWER_DOWN_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE);
eencae 24:342bdb6679a1 115 // small delay and then turn off the power pin
eencae 24:342bdb6679a1 116 wait_ms(10);
eencae 23:eb7e6632fc9e 117
eencae 24:342bdb6679a1 118 // if we are powering the LCD using the GPIO then make it low to turn off
valavanisalex 29:5bc91bd44c77 119 if (_pwr != NULL) {
valavanisalex 29:5bc91bd44c77 120 _pwr->write(0); // turn off power
eencae 24:342bdb6679a1 121 }
eencae 0:d563e74f0ae9 122
eencae 0:d563e74f0ae9 123 }
eencae 0:d563e74f0ae9 124
eencae 0:d563e74f0ae9 125 // function to change LED backlight brightness
eencae 0:d563e74f0ae9 126 void N5110::setBrightness(float brightness)
eencae 0:d563e74f0ae9 127 {
eencae 24:342bdb6679a1 128 // check whether brightness is within range
eencae 24:342bdb6679a1 129 if (brightness < 0.0f)
eencae 24:342bdb6679a1 130 brightness = 0.0f;
eencae 24:342bdb6679a1 131 if (brightness > 1.0f)
eencae 24:342bdb6679a1 132 brightness = 1.0f;
eencae 24:342bdb6679a1 133 // set PWM duty cycle
valavanisalex 29:5bc91bd44c77 134 _led->write(brightness);
eencae 0:d563e74f0ae9 135 }
eencae 0:d563e74f0ae9 136
eencae 0:d563e74f0ae9 137
eencae 0:d563e74f0ae9 138 // pulse the active low reset line
eencae 0:d563e74f0ae9 139 void N5110::reset()
eencae 0:d563e74f0ae9 140 {
valavanisalex 29:5bc91bd44c77 141 _rst->write(0); // reset the LCD
valavanisalex 29:5bc91bd44c77 142 _rst->write(1);
eencae 0:d563e74f0ae9 143 }
eencae 0:d563e74f0ae9 144
eencae 0:d563e74f0ae9 145 // function to initialise SPI peripheral
eencae 0:d563e74f0ae9 146 void N5110::initSPI()
eencae 0:d563e74f0ae9 147 {
valavanisalex 29:5bc91bd44c77 148 _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 149 _spi->frequency(4000000); // maximum of screen is 4 MHz
eencae 0:d563e74f0ae9 150 }
eencae 0:d563e74f0ae9 151
eencae 6:adb79338d40f 152 // send a command to the display
eencae 0:d563e74f0ae9 153 void N5110::sendCommand(unsigned char command)
eencae 0:d563e74f0ae9 154 {
valavanisalex 29:5bc91bd44c77 155 _dc->write(0); // set DC low for command
valavanisalex 29:5bc91bd44c77 156 _sce->write(0); // set CE low to begin frame
valavanisalex 29:5bc91bd44c77 157 _spi->write(command); // send command
valavanisalex 29:5bc91bd44c77 158 _dc->write(1); // turn back to data by default
valavanisalex 29:5bc91bd44c77 159 _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
eencae 0:d563e74f0ae9 160 }
eencae 0:d563e74f0ae9 161
eencae 6:adb79338d40f 162 // send data to the display at the current XY address
eencae 6:adb79338d40f 163 // dc is set to 1 (i.e. data) after sending a command and so should
eencae 6:adb79338d40f 164 // be the default mode.
eencae 0:d563e74f0ae9 165 void N5110::sendData(unsigned char data)
eencae 0:d563e74f0ae9 166 {
valavanisalex 29:5bc91bd44c77 167 _sce->write(0); // set CE low to begin frame
valavanisalex 29:5bc91bd44c77 168 _spi->write(data);
valavanisalex 29:5bc91bd44c77 169 _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
eencae 0:d563e74f0ae9 170 }
eencae 0:d563e74f0ae9 171
eencae 0:d563e74f0ae9 172 // this function writes 0 to the 504 bytes to clear the RAM
eencae 0:d563e74f0ae9 173 void N5110::clearRAM()
eencae 0:d563e74f0ae9 174 {
valavanisalex 29:5bc91bd44c77 175 _sce->write(0); //set CE low to begin frame
eencae 24:342bdb6679a1 176 for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
valavanisalex 29:5bc91bd44c77 177 _spi->write(0x00); // send 0's
eencae 24:342bdb6679a1 178 }
valavanisalex 29:5bc91bd44c77 179 _sce->write(1); // set CE high to end frame
eencae 0:d563e74f0ae9 180 }
eencae 0:d563e74f0ae9 181
eencae 13:908644099648 182 // function to set the XY address in RAM for subsequenct data write
valavanisalex 29:5bc91bd44c77 183 void N5110::setXYAddress(unsigned int const x,
valavanisalex 29:5bc91bd44c77 184 unsigned int const y)
eencae 0:d563e74f0ae9 185 {
valavanisalex 29:5bc91bd44c77 186 if (x<WIDTH && y<HEIGHT) { // check within range
eencae 24:342bdb6679a1 187 sendCommand(0x80 | x); // send addresses to display with relevant mask
eencae 24:342bdb6679a1 188 sendCommand(0x40 | y);
eencae 24:342bdb6679a1 189 }
eencae 0:d563e74f0ae9 190 }
eencae 0:d563e74f0ae9 191
eencae 6:adb79338d40f 192 // These functions are used to set, clear and get the value of pixels in the display
eencae 6:adb79338d40f 193 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh()
eencae 6:adb79338d40f 194 // function must be called after set and clear in order to update the display
valavanisalex 29:5bc91bd44c77 195 void N5110::setPixel(unsigned int const x,
valavanisalex 29:5bc91bd44c77 196 unsigned int const y)
eencae 0:d563e74f0ae9 197 {
valavanisalex 29:5bc91bd44c77 198 if (x<WIDTH && y<HEIGHT) { // check within range
eencae 24:342bdb6679a1 199 // calculate bank and shift 1 to required position in the data byte
eencae 24:342bdb6679a1 200 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 29:5bc91bd44c77 327 unsigned int 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
eencae 24:342bdb6679a1 337 if (fill == 0) {
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
eencae 24:342bdb6679a1 348 int type = (fill==1) ? 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
eencae 24:342bdb6679a1 394 if (type == 0) // if 'white' line, turn off pixel
eencae 24:342bdb6679a1 395 clearPixel(x,y);
eencae 24:342bdb6679a1 396 else
eencae 24:342bdb6679a1 397 setPixel(x,y); // else if 'black' or 'dotted' turn on pixel
eencae 24:342bdb6679a1 398 }
eencae 24:342bdb6679a1 399 } else {
eencae 17:780a542d5f8b 400
eencae 24:342bdb6679a1 401 // ensure we loop from smallest to largest or else for-loop won't run as expected
eencae 24:342bdb6679a1 402 start = y1>y0 ? y0:y1;
eencae 24:342bdb6679a1 403 stop = y1>y0 ? y1:y0;
eencae 17:780a542d5f8b 404
eencae 24:342bdb6679a1 405 for (int y = start; y<= stop ; y+=step) {
eencae 24:342bdb6679a1 406 // do linear interpolation
eencae 24:342bdb6679a1 407 int x = x0 + (x1-x0)*(y-y0)/(y1-y0);
eencae 17:780a542d5f8b 408
eencae 24:342bdb6679a1 409 if (type == 0) // if 'white' line, turn off pixel
eencae 24:342bdb6679a1 410 clearPixel(x,y);
eencae 24:342bdb6679a1 411 else
eencae 24:342bdb6679a1 412 setPixel(x,y); // else if 'black' or 'dotted' turn on pixel
eencae 17:780a542d5f8b 413
eencae 24:342bdb6679a1 414 }
eencae 17:780a542d5f8b 415 }
eencae 17:780a542d5f8b 416
eencae 17:780a542d5f8b 417 }
eencae 17:780a542d5f8b 418
valavanisalex 29:5bc91bd44c77 419 void N5110::drawRect(unsigned int const x0,
valavanisalex 29:5bc91bd44c77 420 unsigned int const y0,
valavanisalex 29:5bc91bd44c77 421 unsigned int const width,
valavanisalex 29:5bc91bd44c77 422 unsigned int const height,
valavanisalex 29:5bc91bd44c77 423 unsigned int const fill)
eencae 17:780a542d5f8b 424 {
eencae 24:342bdb6679a1 425 if (fill == 0) { // transparent, just outline
eencae 27:0d8d90936b4c 426 drawLine(x0,y0,x0+(width-1),y0,1); // top
eencae 27:0d8d90936b4c 427 drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),1); // bottom
eencae 27:0d8d90936b4c 428 drawLine(x0,y0,x0,y0+(height-1),1); // left
eencae 27:0d8d90936b4c 429 drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),1); // right
eencae 24:342bdb6679a1 430 } else { // filled rectangle
eencae 24:342bdb6679a1 431 int type = (fill==1) ? 1:0; // black or white fill
eencae 27:0d8d90936b4c 432 for (int y = y0; y<y0+height; y++) { // loop through rows of rectangle
eencae 27:0d8d90936b4c 433 drawLine(x0,y,x0+(width-1),y,type); // draw line across screen
eencae 24:342bdb6679a1 434 }
eencae 17:780a542d5f8b 435 }
valavanisalex 29:5bc91bd44c77 436 }