Template for the ELEC1620 End of year exam

Dependencies:   mbed

Committer:
el16ttb
Date:
Fri Mar 22 13:11:07 2019 +0000
Revision:
0:54721f063ac8
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
el16ttb 0:54721f063ac8 1 #include "mbed.h"
el16ttb 0:54721f063ac8 2 #include "N5110.h"
el16ttb 0:54721f063ac8 3
el16ttb 0:54721f063ac8 4 // overloaded constructor includes power pin - LCD Vcc connected to GPIO pin
el16ttb 0:54721f063ac8 5 // this constructor works fine with LPC1768 - enough current sourced from GPIO
el16ttb 0:54721f063ac8 6 // to power LCD. Doesn't work well with K64F.
el16ttb 0:54721f063ac8 7 N5110::N5110(PinName const pwrPin,
el16ttb 0:54721f063ac8 8 PinName const scePin,
el16ttb 0:54721f063ac8 9 PinName const rstPin,
el16ttb 0:54721f063ac8 10 PinName const dcPin,
el16ttb 0:54721f063ac8 11 PinName const mosiPin,
el16ttb 0:54721f063ac8 12 PinName const sclkPin,
el16ttb 0:54721f063ac8 13 PinName const ledPin)
el16ttb 0:54721f063ac8 14 :
el16ttb 0:54721f063ac8 15 _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
el16ttb 0:54721f063ac8 16 _led(new PwmOut(ledPin)),
el16ttb 0:54721f063ac8 17 _pwr(new DigitalOut(pwrPin)),
el16ttb 0:54721f063ac8 18 _sce(new DigitalOut(scePin)),
el16ttb 0:54721f063ac8 19 _rst(new DigitalOut(rstPin)),
el16ttb 0:54721f063ac8 20 _dc(new DigitalOut(dcPin))
el16ttb 0:54721f063ac8 21 {}
el16ttb 0:54721f063ac8 22
el16ttb 0:54721f063ac8 23 // overloaded constructor does not include power pin - LCD Vcc must be tied to +3V3
el16ttb 0:54721f063ac8 24 // Best to use this with K64F as the GPIO hasn't sufficient output current to reliably
el16ttb 0:54721f063ac8 25 // drive the LCD.
el16ttb 0:54721f063ac8 26 N5110::N5110(PinName const scePin,
el16ttb 0:54721f063ac8 27 PinName const rstPin,
el16ttb 0:54721f063ac8 28 PinName const dcPin,
el16ttb 0:54721f063ac8 29 PinName const mosiPin,
el16ttb 0:54721f063ac8 30 PinName const sclkPin,
el16ttb 0:54721f063ac8 31 PinName const ledPin)
el16ttb 0:54721f063ac8 32 :
el16ttb 0:54721f063ac8 33 _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
el16ttb 0:54721f063ac8 34 _led(new PwmOut(ledPin)),
el16ttb 0:54721f063ac8 35 _pwr(NULL), // pwr not needed so null it to be safe
el16ttb 0:54721f063ac8 36 _sce(new DigitalOut(scePin)),
el16ttb 0:54721f063ac8 37 _rst(new DigitalOut(rstPin)),
el16ttb 0:54721f063ac8 38 _dc(new DigitalOut(dcPin))
el16ttb 0:54721f063ac8 39 {}
el16ttb 0:54721f063ac8 40
el16ttb 0:54721f063ac8 41 N5110::~N5110()
el16ttb 0:54721f063ac8 42 {
el16ttb 0:54721f063ac8 43 delete _spi;
el16ttb 0:54721f063ac8 44
el16ttb 0:54721f063ac8 45 if(_pwr) {
el16ttb 0:54721f063ac8 46 delete _pwr;
el16ttb 0:54721f063ac8 47 }
el16ttb 0:54721f063ac8 48
el16ttb 0:54721f063ac8 49 delete _led;
el16ttb 0:54721f063ac8 50 delete _sce;
el16ttb 0:54721f063ac8 51 delete _rst;
el16ttb 0:54721f063ac8 52 delete _dc;
el16ttb 0:54721f063ac8 53 }
el16ttb 0:54721f063ac8 54
el16ttb 0:54721f063ac8 55 // initialise function - powers up and sends the initialisation commands
el16ttb 0:54721f063ac8 56 void N5110::init()
el16ttb 0:54721f063ac8 57 {
el16ttb 0:54721f063ac8 58 turnOn(); // power up
el16ttb 0:54721f063ac8 59 reset(); // reset LCD - must be done within 100 ms
el16ttb 0:54721f063ac8 60 initSPI();
el16ttb 0:54721f063ac8 61
el16ttb 0:54721f063ac8 62 setContrast(0.55); // this may need tuning (say 0.4 to 0.6)
el16ttb 0:54721f063ac8 63 setBias(3); // datasheet - 48:1 mux - don't mess with if you don't know what you're doing! (0 to 7)
el16ttb 0:54721f063ac8 64 setTempCoefficient(0); // datasheet - may need increasing (range 0 to 3) at very low temperatures
el16ttb 0:54721f063ac8 65 normalMode(); // normal video mode by default
el16ttb 0:54721f063ac8 66
el16ttb 0:54721f063ac8 67 clearRAM(); // RAM is undefined at power-up so clear to be sure
el16ttb 0:54721f063ac8 68 clear(); // clear buffer
el16ttb 0:54721f063ac8 69 setBrightness(0.5);
el16ttb 0:54721f063ac8 70 _stream->writeMessage(0x1, 0x00);
el16ttb 0:54721f063ac8 71 _stream->sendMessages();
el16ttb 0:54721f063ac8 72 }
el16ttb 0:54721f063ac8 73
el16ttb 0:54721f063ac8 74 // sets normal video mode (black on white)
el16ttb 0:54721f063ac8 75 void N5110::normalMode()
el16ttb 0:54721f063ac8 76 {
el16ttb 0:54721f063ac8 77 sendCommand(0b00100000); // basic instruction
el16ttb 0:54721f063ac8 78 sendCommand(0b00001100); // normal video mode- datasheet
el16ttb 0:54721f063ac8 79 }
el16ttb 0:54721f063ac8 80
el16ttb 0:54721f063ac8 81 // sets normal video mode (white on black)
el16ttb 0:54721f063ac8 82 void N5110::inverseMode()
el16ttb 0:54721f063ac8 83 {
el16ttb 0:54721f063ac8 84 sendCommand(0b00100000); // basic instruction
el16ttb 0:54721f063ac8 85 sendCommand(0b00001101); // inverse video mode - datasheet
el16ttb 0:54721f063ac8 86 }
el16ttb 0:54721f063ac8 87
el16ttb 0:54721f063ac8 88 // function to power up the LCD and backlight - only works when using GPIO to power
el16ttb 0:54721f063ac8 89 void N5110::turnOn()
el16ttb 0:54721f063ac8 90 {
el16ttb 0:54721f063ac8 91 if (_pwr != NULL) {
el16ttb 0:54721f063ac8 92 _pwr->write(1); // apply power
el16ttb 0:54721f063ac8 93 }
el16ttb 0:54721f063ac8 94 }
el16ttb 0:54721f063ac8 95
el16ttb 0:54721f063ac8 96 // function to power down LCD
el16ttb 0:54721f063ac8 97 void N5110::turnOff()
el16ttb 0:54721f063ac8 98 {
el16ttb 0:54721f063ac8 99 clear(); // clear buffer
el16ttb 0:54721f063ac8 100 refresh();
el16ttb 0:54721f063ac8 101 setBrightness(0.0); // turn backlight off
el16ttb 0:54721f063ac8 102 clearRAM(); // clear RAM to ensure specified current consumption
el16ttb 0:54721f063ac8 103 // send command to ensure we are in basic mode
el16ttb 0:54721f063ac8 104
el16ttb 0:54721f063ac8 105 sendCommand(0b00100000); // basic mode
el16ttb 0:54721f063ac8 106 sendCommand(0b00001000); // clear display
el16ttb 0:54721f063ac8 107 sendCommand(0b00100001); // extended mode
el16ttb 0:54721f063ac8 108 sendCommand(0b00100100); // power down
el16ttb 0:54721f063ac8 109
el16ttb 0:54721f063ac8 110 // if we are powering the LCD using the GPIO then make it low to turn off
el16ttb 0:54721f063ac8 111 if (_pwr != NULL) {
el16ttb 0:54721f063ac8 112 wait_ms(10); // small delay and then turn off the power pin
el16ttb 0:54721f063ac8 113 _pwr->write(0); // turn off power
el16ttb 0:54721f063ac8 114 }
el16ttb 0:54721f063ac8 115 _stream->writeMessage(0x2, 0x00);
el16ttb 0:54721f063ac8 116 _stream->sendMessages();
el16ttb 0:54721f063ac8 117 }
el16ttb 0:54721f063ac8 118
el16ttb 0:54721f063ac8 119 // function to change LED backlight brightness
el16ttb 0:54721f063ac8 120 void N5110::setBrightness(float brightness)
el16ttb 0:54721f063ac8 121 {
el16ttb 0:54721f063ac8 122 // check whether brightness is within range
el16ttb 0:54721f063ac8 123 if (brightness < 0.0f)
el16ttb 0:54721f063ac8 124 brightness = 0.0f;
el16ttb 0:54721f063ac8 125 if (brightness > 1.0f)
el16ttb 0:54721f063ac8 126 brightness = 1.0f;
el16ttb 0:54721f063ac8 127 // set PWM duty cycle
el16ttb 0:54721f063ac8 128 _led->write(brightness);
el16ttb 0:54721f063ac8 129
el16ttb 0:54721f063ac8 130 _stream->writeMessage(0x3, (unsigned int)(brightness * 1000000));
el16ttb 0:54721f063ac8 131 _stream->sendMessages();
el16ttb 0:54721f063ac8 132 }
el16ttb 0:54721f063ac8 133
el16ttb 0:54721f063ac8 134 void N5110::setContrast(float contrast) {
el16ttb 0:54721f063ac8 135
el16ttb 0:54721f063ac8 136 // enforce limits
el16ttb 0:54721f063ac8 137 if (contrast > 1.0f)
el16ttb 0:54721f063ac8 138 contrast = 1.0f;
el16ttb 0:54721f063ac8 139 else if (contrast < 0.0f)
el16ttb 0:54721f063ac8 140 contrast = 0.0;
el16ttb 0:54721f063ac8 141
el16ttb 0:54721f063ac8 142 // convert to char in range 0 to 127 (i.e. 6 bits)
el16ttb 0:54721f063ac8 143 char ic = char(contrast*127.0f);
el16ttb 0:54721f063ac8 144
el16ttb 0:54721f063ac8 145 sendCommand(0b00100001); // extended instruction set
el16ttb 0:54721f063ac8 146 sendCommand(0b10000000 | ic); // set Vop (which controls contrast)
el16ttb 0:54721f063ac8 147 sendCommand(0b00100000); // back to basic instruction set
el16ttb 0:54721f063ac8 148 }
el16ttb 0:54721f063ac8 149
el16ttb 0:54721f063ac8 150 void N5110::setTempCoefficient(char tc) {
el16ttb 0:54721f063ac8 151
el16ttb 0:54721f063ac8 152 // enforce limits
el16ttb 0:54721f063ac8 153 if (tc>3) {
el16ttb 0:54721f063ac8 154 tc=3;
el16ttb 0:54721f063ac8 155 }
el16ttb 0:54721f063ac8 156
el16ttb 0:54721f063ac8 157 // temperature coefficient may need increasing at low temperatures
el16ttb 0:54721f063ac8 158
el16ttb 0:54721f063ac8 159 sendCommand(0b00100001); // extended instruction set
el16ttb 0:54721f063ac8 160 sendCommand(0b00000100 | tc);
el16ttb 0:54721f063ac8 161 sendCommand(0b00100000); // back to basic instruction set
el16ttb 0:54721f063ac8 162 }
el16ttb 0:54721f063ac8 163
el16ttb 0:54721f063ac8 164 void N5110::setBias(char bias) {
el16ttb 0:54721f063ac8 165
el16ttb 0:54721f063ac8 166 // from data sheet
el16ttb 0:54721f063ac8 167 // bias mux rate
el16ttb 0:54721f063ac8 168 // 0 1:100
el16ttb 0:54721f063ac8 169 // 1 1:80
el16ttb 0:54721f063ac8 170 // 2 1:65
el16ttb 0:54721f063ac8 171 // 3 1:48 (default)
el16ttb 0:54721f063ac8 172 // 4 1:40/1:34
el16ttb 0:54721f063ac8 173 // 5 1:24
el16ttb 0:54721f063ac8 174 // 6 1:18/1:16
el16ttb 0:54721f063ac8 175 // 7 1:10/1:9/1:8
el16ttb 0:54721f063ac8 176
el16ttb 0:54721f063ac8 177 // enforce limits
el16ttb 0:54721f063ac8 178 if (bias>7) {
el16ttb 0:54721f063ac8 179 bias=7;
el16ttb 0:54721f063ac8 180 }
el16ttb 0:54721f063ac8 181
el16ttb 0:54721f063ac8 182 sendCommand(0b00100001); // extended mode instruction
el16ttb 0:54721f063ac8 183 sendCommand(0b00010000 | bias);
el16ttb 0:54721f063ac8 184 sendCommand(0b00100000); // end of extended mode instruction
el16ttb 0:54721f063ac8 185 }
el16ttb 0:54721f063ac8 186
el16ttb 0:54721f063ac8 187 // pulse the active low reset line
el16ttb 0:54721f063ac8 188 void N5110::reset()
el16ttb 0:54721f063ac8 189 {
el16ttb 0:54721f063ac8 190 _rst->write(0); // reset the LCD
el16ttb 0:54721f063ac8 191 _rst->write(1);
el16ttb 0:54721f063ac8 192
el16ttb 0:54721f063ac8 193 _stream->writeMessage(0x4, 0x00);
el16ttb 0:54721f063ac8 194 _stream->sendMessages();
el16ttb 0:54721f063ac8 195 }
el16ttb 0:54721f063ac8 196
el16ttb 0:54721f063ac8 197 // function to initialise SPI peripheral
el16ttb 0:54721f063ac8 198 void N5110::initSPI()
el16ttb 0:54721f063ac8 199 {
el16ttb 0:54721f063ac8 200 _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
el16ttb 0:54721f063ac8 201 _spi->frequency(4000000); // maximum of screen is 4 MHz
el16ttb 0:54721f063ac8 202 }
el16ttb 0:54721f063ac8 203
el16ttb 0:54721f063ac8 204 // send a command to the display
el16ttb 0:54721f063ac8 205 void N5110::sendCommand(unsigned char command)
el16ttb 0:54721f063ac8 206 {
el16ttb 0:54721f063ac8 207 _dc->write(0); // set DC low for command
el16ttb 0:54721f063ac8 208 _sce->write(0); // set CE low to begin frame
el16ttb 0:54721f063ac8 209 _spi->write(command); // send command
el16ttb 0:54721f063ac8 210 _dc->write(1); // turn back to data by default
el16ttb 0:54721f063ac8 211 _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
el16ttb 0:54721f063ac8 212 }
el16ttb 0:54721f063ac8 213
el16ttb 0:54721f063ac8 214 // send data to the display at the current XY address
el16ttb 0:54721f063ac8 215 // dc is set to 1 (i.e. data) after sending a command and so should
el16ttb 0:54721f063ac8 216 // be the default mode.
el16ttb 0:54721f063ac8 217 void N5110::sendData(unsigned char data)
el16ttb 0:54721f063ac8 218 {
el16ttb 0:54721f063ac8 219 _sce->write(0); // set CE low to begin frame
el16ttb 0:54721f063ac8 220 _spi->write(data);
el16ttb 0:54721f063ac8 221 _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
el16ttb 0:54721f063ac8 222 }
el16ttb 0:54721f063ac8 223
el16ttb 0:54721f063ac8 224 // this function writes 0 to the 504 bytes to clear the RAM
el16ttb 0:54721f063ac8 225 void N5110::clearRAM()
el16ttb 0:54721f063ac8 226 {
el16ttb 0:54721f063ac8 227 _sce->write(0); //set CE low to begin frame
el16ttb 0:54721f063ac8 228 for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
el16ttb 0:54721f063ac8 229 _spi->write(0x00); // send 0's
el16ttb 0:54721f063ac8 230 }
el16ttb 0:54721f063ac8 231 _sce->write(1); // set CE high to end frame
el16ttb 0:54721f063ac8 232 }
el16ttb 0:54721f063ac8 233
el16ttb 0:54721f063ac8 234 // function to set the XY address in RAM for subsequenct data write
el16ttb 0:54721f063ac8 235 void N5110::setXYAddress(unsigned int const x,
el16ttb 0:54721f063ac8 236 unsigned int const y)
el16ttb 0:54721f063ac8 237 {
el16ttb 0:54721f063ac8 238 if (x<WIDTH && y<HEIGHT) { // check within range
el16ttb 0:54721f063ac8 239 sendCommand(0b00100000); // basic instruction
el16ttb 0:54721f063ac8 240 sendCommand(0b10000000 | x); // send addresses to display with relevant mask
el16ttb 0:54721f063ac8 241 sendCommand(0b01000000 | y);
el16ttb 0:54721f063ac8 242 }
el16ttb 0:54721f063ac8 243 }
el16ttb 0:54721f063ac8 244
el16ttb 0:54721f063ac8 245 // These functions are used to set, clear and get the value of pixels in the display
el16ttb 0:54721f063ac8 246 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh()
el16ttb 0:54721f063ac8 247 // function must be called after set and clear in order to update the display
el16ttb 0:54721f063ac8 248 void N5110::setPixel(unsigned int const x,
el16ttb 0:54721f063ac8 249 unsigned int const y,
el16ttb 0:54721f063ac8 250 bool const state)
el16ttb 0:54721f063ac8 251 {
el16ttb 0:54721f063ac8 252 if (x<WIDTH && y<HEIGHT) { // check within range
el16ttb 0:54721f063ac8 253 // calculate bank and shift 1 to required position in the data byte
el16ttb 0:54721f063ac8 254 if(state) buffer[x][y/8] |= (1 << y%8);
el16ttb 0:54721f063ac8 255 else buffer[x][y/8] &= ~(1 << y%8);
el16ttb 0:54721f063ac8 256
el16ttb 0:54721f063ac8 257 _stream->writeMessage(0x5, ((x & 0x7F) << 8) | ((y & 0x7F) << 1) | (state & 0x1));
el16ttb 0:54721f063ac8 258 }
el16ttb 0:54721f063ac8 259 }
el16ttb 0:54721f063ac8 260
el16ttb 0:54721f063ac8 261 void N5110::clearPixel(unsigned int const x,
el16ttb 0:54721f063ac8 262 unsigned int const y)
el16ttb 0:54721f063ac8 263 {
el16ttb 0:54721f063ac8 264 if (x<WIDTH && y<HEIGHT) { // check within range
el16ttb 0:54721f063ac8 265 // calculate bank and shift 1 to required position (using bit clear)
el16ttb 0:54721f063ac8 266 buffer[x][y/8] &= ~(1 << y%8);
el16ttb 0:54721f063ac8 267 _stream->writeMessage(0x6, ((x & 0x7F) << 7) | (y & 0x7F));
el16ttb 0:54721f063ac8 268 }
el16ttb 0:54721f063ac8 269 }
el16ttb 0:54721f063ac8 270
el16ttb 0:54721f063ac8 271 int N5110::getPixel(unsigned int const x,
el16ttb 0:54721f063ac8 272 unsigned int const y) const
el16ttb 0:54721f063ac8 273 {
el16ttb 0:54721f063ac8 274 if (x<WIDTH && y<HEIGHT) { // check within range
el16ttb 0:54721f063ac8 275 // return relevant bank and mask required bit
el16ttb 0:54721f063ac8 276
el16ttb 0:54721f063ac8 277 int pixel = (int) buffer[x][y/8] & (1 << y%8);
el16ttb 0:54721f063ac8 278
el16ttb 0:54721f063ac8 279 if (pixel)
el16ttb 0:54721f063ac8 280 return 1;
el16ttb 0:54721f063ac8 281 else
el16ttb 0:54721f063ac8 282 return 0;
el16ttb 0:54721f063ac8 283 }
el16ttb 0:54721f063ac8 284
el16ttb 0:54721f063ac8 285 return 0;
el16ttb 0:54721f063ac8 286
el16ttb 0:54721f063ac8 287 }
el16ttb 0:54721f063ac8 288
el16ttb 0:54721f063ac8 289 // function to refresh the display
el16ttb 0:54721f063ac8 290 void N5110::refresh()
el16ttb 0:54721f063ac8 291 {
el16ttb 0:54721f063ac8 292 setXYAddress(0,0); // important to set address back to 0,0 before refreshing display
el16ttb 0:54721f063ac8 293 // address auto increments after printing string, so buffer[0][0] will not coincide
el16ttb 0:54721f063ac8 294 // with top-left pixel after priting string
el16ttb 0:54721f063ac8 295
el16ttb 0:54721f063ac8 296 _sce->write(0); //set CE low to begin frame
el16ttb 0:54721f063ac8 297
el16ttb 0:54721f063ac8 298 for(int j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing
el16ttb 0:54721f063ac8 299 for(int i = 0; i < WIDTH; i++) {
el16ttb 0:54721f063ac8 300 _spi->write(buffer[i][j]); // send buffer
el16ttb 0:54721f063ac8 301 }
el16ttb 0:54721f063ac8 302 }
el16ttb 0:54721f063ac8 303 _sce->write(1); // set CE high to end frame
el16ttb 0:54721f063ac8 304
el16ttb 0:54721f063ac8 305 _stream->writeMessage(0x7, 0x00);
el16ttb 0:54721f063ac8 306 _stream->sendMessages();
el16ttb 0:54721f063ac8 307
el16ttb 0:54721f063ac8 308 }
el16ttb 0:54721f063ac8 309
el16ttb 0:54721f063ac8 310 // fills the buffer with random bytes. Can be used to test the display.
el16ttb 0:54721f063ac8 311 // The rand() function isn't seeded so it probably creates the same pattern everytime
el16ttb 0:54721f063ac8 312 void N5110::randomiseBuffer()
el16ttb 0:54721f063ac8 313 {
el16ttb 0:54721f063ac8 314 int i,j;
el16ttb 0:54721f063ac8 315 for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing
el16ttb 0:54721f063ac8 316 for(i = 0; i < WIDTH; i++) {
el16ttb 0:54721f063ac8 317 buffer[i][j] = rand()%256; // generate random byte
el16ttb 0:54721f063ac8 318 }
el16ttb 0:54721f063ac8 319 }
el16ttb 0:54721f063ac8 320
el16ttb 0:54721f063ac8 321 }
el16ttb 0:54721f063ac8 322
el16ttb 0:54721f063ac8 323 // function to print 5x7 font
el16ttb 0:54721f063ac8 324 void N5110::printChar(char const c,
el16ttb 0:54721f063ac8 325 unsigned int const x,
el16ttb 0:54721f063ac8 326 unsigned int const y)
el16ttb 0:54721f063ac8 327 {
el16ttb 0:54721f063ac8 328 if (y<BANKS) { // check if printing in range of y banks
el16ttb 0:54721f063ac8 329
el16ttb 0:54721f063ac8 330 for (int i = 0; i < 5 ; i++ ) {
el16ttb 0:54721f063ac8 331 int pixel_x = x+i;
el16ttb 0:54721f063ac8 332 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83)
el16ttb 0:54721f063ac8 333 break;
el16ttb 0:54721f063ac8 334 buffer[pixel_x][y] = font5x7[(c - 32)*5 + i];
el16ttb 0:54721f063ac8 335 // array is offset by 32 relative to ASCII, each character is 5 pixels wide
el16ttb 0:54721f063ac8 336 }
el16ttb 0:54721f063ac8 337 _stream->writeMessage(0x8, ((x & 0x7F) << 15) | ((y & 0x7F) << 8) | c);
el16ttb 0:54721f063ac8 338
el16ttb 0:54721f063ac8 339 }
el16ttb 0:54721f063ac8 340 }
el16ttb 0:54721f063ac8 341
el16ttb 0:54721f063ac8 342 // function to print string at specified position
el16ttb 0:54721f063ac8 343 void N5110::printString(const char *str,
el16ttb 0:54721f063ac8 344 unsigned int const x,
el16ttb 0:54721f063ac8 345 unsigned int const y)
el16ttb 0:54721f063ac8 346 {
el16ttb 0:54721f063ac8 347 if (y<BANKS) { // check if printing in range of y banks
el16ttb 0:54721f063ac8 348
el16ttb 0:54721f063ac8 349 int n = 0 ; // counter for number of characters in string
el16ttb 0:54721f063ac8 350 // loop through string and print character
el16ttb 0:54721f063ac8 351 while(*str) {
el16ttb 0:54721f063ac8 352
el16ttb 0:54721f063ac8 353 // writes the character bitmap data to the buffer, so that
el16ttb 0:54721f063ac8 354 // text and pixels can be displayed at the same time
el16ttb 0:54721f063ac8 355 for (int i = 0; i < 5 ; i++ ) {
el16ttb 0:54721f063ac8 356 int pixel_x = x+i+n*6;
el16ttb 0:54721f063ac8 357 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83)
el16ttb 0:54721f063ac8 358 break;
el16ttb 0:54721f063ac8 359 buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i];
el16ttb 0:54721f063ac8 360 }
el16ttb 0:54721f063ac8 361
el16ttb 0:54721f063ac8 362 _stream->writeMessage(0x8, (((x + n * 6) & 0x7F) << 15) | ((y & 0x7F) << 8) | *str);
el16ttb 0:54721f063ac8 363
el16ttb 0:54721f063ac8 364
el16ttb 0:54721f063ac8 365 str++; // go to next character in string
el16ttb 0:54721f063ac8 366 n++; // increment index
el16ttb 0:54721f063ac8 367 }
el16ttb 0:54721f063ac8 368 }
el16ttb 0:54721f063ac8 369 }
el16ttb 0:54721f063ac8 370
el16ttb 0:54721f063ac8 371 // function to clear the screen buffer
el16ttb 0:54721f063ac8 372 void N5110::clear()
el16ttb 0:54721f063ac8 373 {
el16ttb 0:54721f063ac8 374 memset(buffer,0,sizeof(buffer));
el16ttb 0:54721f063ac8 375 _stream->writeMessage(0x9, 0x00);
el16ttb 0:54721f063ac8 376 }
el16ttb 0:54721f063ac8 377
el16ttb 0:54721f063ac8 378 // function to plot array on display
el16ttb 0:54721f063ac8 379 void N5110::plotArray(float const array[])
el16ttb 0:54721f063ac8 380 {
el16ttb 0:54721f063ac8 381 for (int i=0; i<WIDTH; i++) { // loop through array
el16ttb 0:54721f063ac8 382 // elements are normalised from 0.0 to 1.0, so multiply
el16ttb 0:54721f063ac8 383 // by 47 to convert to pixel range, and subtract from 47
el16ttb 0:54721f063ac8 384 // since top-left is 0,0 in the display geometry
el16ttb 0:54721f063ac8 385 setPixel(i,47 - int(array[i]*47.0f),true);
el16ttb 0:54721f063ac8 386 }
el16ttb 0:54721f063ac8 387
el16ttb 0:54721f063ac8 388 }
el16ttb 0:54721f063ac8 389
el16ttb 0:54721f063ac8 390 // function to draw circle
el16ttb 0:54721f063ac8 391 void N5110:: drawCircle(unsigned int const x0,
el16ttb 0:54721f063ac8 392 unsigned int const y0,
el16ttb 0:54721f063ac8 393 unsigned int const radius,
el16ttb 0:54721f063ac8 394 FillType const fill)
el16ttb 0:54721f063ac8 395 {
el16ttb 0:54721f063ac8 396 // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
el16ttb 0:54721f063ac8 397 int x = radius;
el16ttb 0:54721f063ac8 398 int y = 0;
el16ttb 0:54721f063ac8 399 int radiusError = 1-x;
el16ttb 0:54721f063ac8 400 _stream->lock();
el16ttb 0:54721f063ac8 401 while(x >= y) {
el16ttb 0:54721f063ac8 402
el16ttb 0:54721f063ac8 403 // if transparent, just draw outline
el16ttb 0:54721f063ac8 404 if (fill == FILL_TRANSPARENT) {
el16ttb 0:54721f063ac8 405 setPixel( x + x0, y + y0,true);
el16ttb 0:54721f063ac8 406 setPixel(-x + x0, y + y0,true);
el16ttb 0:54721f063ac8 407 setPixel( y + x0, x + y0,true);
el16ttb 0:54721f063ac8 408 setPixel(-y + x0, x + y0,true);
el16ttb 0:54721f063ac8 409 setPixel(-y + x0, -x + y0,true);
el16ttb 0:54721f063ac8 410 setPixel( y + x0, -x + y0,true);
el16ttb 0:54721f063ac8 411 setPixel( x + x0, -y + y0,true);
el16ttb 0:54721f063ac8 412 setPixel(-x + x0, -y + y0,true);
el16ttb 0:54721f063ac8 413 } else { // drawing filled circle, so draw lines between points at same y value
el16ttb 0:54721f063ac8 414
el16ttb 0:54721f063ac8 415 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill
el16ttb 0:54721f063ac8 416
el16ttb 0:54721f063ac8 417 drawLine(x+x0, y+y0, -x+x0, y+y0, type);
el16ttb 0:54721f063ac8 418 drawLine(y+x0, x+y0, -y+x0, x+y0, type);
el16ttb 0:54721f063ac8 419 drawLine(y+x0, -x+y0, -y+x0, -x+y0, type);
el16ttb 0:54721f063ac8 420 drawLine(x+x0, -y+y0, -x+x0, -y+y0, type);
el16ttb 0:54721f063ac8 421 }
el16ttb 0:54721f063ac8 422
el16ttb 0:54721f063ac8 423 y++;
el16ttb 0:54721f063ac8 424 if (radiusError<0) {
el16ttb 0:54721f063ac8 425 radiusError += 2 * y + 1;
el16ttb 0:54721f063ac8 426 } else {
el16ttb 0:54721f063ac8 427 x--;
el16ttb 0:54721f063ac8 428 radiusError += 2 * (y - x) + 1;
el16ttb 0:54721f063ac8 429 }
el16ttb 0:54721f063ac8 430 }
el16ttb 0:54721f063ac8 431 _stream->unlock();
el16ttb 0:54721f063ac8 432 _stream->writeMessage(0xa,
el16ttb 0:54721f063ac8 433 ((x0 & 0x7F) << 16) |
el16ttb 0:54721f063ac8 434 ((y0 & 0x7F) << 9) |
el16ttb 0:54721f063ac8 435 ((radius & 0x7F) << 2) |
el16ttb 0:54721f063ac8 436 (fill==FILL_TRANSPARENT ? 0x00 : (fill==FILL_BLACK ? 0x01 : 0x02)));
el16ttb 0:54721f063ac8 437
el16ttb 0:54721f063ac8 438
el16ttb 0:54721f063ac8 439 }
el16ttb 0:54721f063ac8 440
el16ttb 0:54721f063ac8 441 void N5110::drawLine(unsigned int const x0,
el16ttb 0:54721f063ac8 442 unsigned int const y0,
el16ttb 0:54721f063ac8 443 unsigned int const x1,
el16ttb 0:54721f063ac8 444 unsigned int const y1,
el16ttb 0:54721f063ac8 445 unsigned int const type)
el16ttb 0:54721f063ac8 446 {
el16ttb 0:54721f063ac8 447 _stream->lock();
el16ttb 0:54721f063ac8 448 // Note that the ranges can be negative so we have to turn the input values
el16ttb 0:54721f063ac8 449 // into signed integers first
el16ttb 0:54721f063ac8 450 int const y_range = static_cast<int>(y1) - static_cast<int>(y0);
el16ttb 0:54721f063ac8 451 int const x_range = static_cast<int>(x1) - static_cast<int>(x0);
el16ttb 0:54721f063ac8 452
el16ttb 0:54721f063ac8 453 // if dotted line, set step to 2, else step is 1
el16ttb 0:54721f063ac8 454 unsigned int const step = (type==2) ? 2:1;
el16ttb 0:54721f063ac8 455
el16ttb 0:54721f063ac8 456 // make sure we loop over the largest range to get the most pixels on the display
el16ttb 0:54721f063ac8 457 // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
el16ttb 0:54721f063ac8 458 // or else we'll only end up with 1 pixel in the x column
el16ttb 0:54721f063ac8 459 if ( abs(x_range) > abs(y_range) ) {
el16ttb 0:54721f063ac8 460
el16ttb 0:54721f063ac8 461 // ensure we loop from smallest to largest or else for-loop won't run as expected
el16ttb 0:54721f063ac8 462 unsigned int const start = x_range > 0 ? x0:x1;
el16ttb 0:54721f063ac8 463 unsigned int const stop = x_range > 0 ? x1:x0;
el16ttb 0:54721f063ac8 464
el16ttb 0:54721f063ac8 465 // loop between x pixels
el16ttb 0:54721f063ac8 466 for (unsigned int x = start; x<= stop ; x+=step) {
el16ttb 0:54721f063ac8 467 // do linear interpolation
el16ttb 0:54721f063ac8 468 int const dx = static_cast<int>(x)-static_cast<int>(x0);
el16ttb 0:54721f063ac8 469 unsigned int const y = y0 + y_range * dx / x_range;
el16ttb 0:54721f063ac8 470
el16ttb 0:54721f063ac8 471 // If the line type is '0', this will clear the pixel
el16ttb 0:54721f063ac8 472 // If it is '1' or '2', the pixel will be set
el16ttb 0:54721f063ac8 473 setPixel(x,y, type);
el16ttb 0:54721f063ac8 474 }
el16ttb 0:54721f063ac8 475 } else {
el16ttb 0:54721f063ac8 476
el16ttb 0:54721f063ac8 477 // ensure we loop from smallest to largest or else for-loop won't run as expected
el16ttb 0:54721f063ac8 478 unsigned int const start = y_range > 0 ? y0:y1;
el16ttb 0:54721f063ac8 479 unsigned int const stop = y_range > 0 ? y1:y0;
el16ttb 0:54721f063ac8 480
el16ttb 0:54721f063ac8 481 for (unsigned int y = start; y<= stop ; y+=step) {
el16ttb 0:54721f063ac8 482 // do linear interpolation
el16ttb 0:54721f063ac8 483 int const dy = static_cast<int>(y)-static_cast<int>(y0);
el16ttb 0:54721f063ac8 484 unsigned int const x = x0 + x_range * dy / y_range;
el16ttb 0:54721f063ac8 485
el16ttb 0:54721f063ac8 486 // If the line type is '0', this will clear the pixel
el16ttb 0:54721f063ac8 487 // If it is '1' or '2', the pixel will be set
el16ttb 0:54721f063ac8 488 setPixel(x,y, type);
el16ttb 0:54721f063ac8 489 }
el16ttb 0:54721f063ac8 490 }
el16ttb 0:54721f063ac8 491 _stream->unlock();
el16ttb 0:54721f063ac8 492 _stream->writeMessage(0xb,
el16ttb 0:54721f063ac8 493 ((x0 & 0x7F) << 23) |
el16ttb 0:54721f063ac8 494 ((y0 & 0x7F) << 16) |
el16ttb 0:54721f063ac8 495 ((x1 & 0x7F) << 9) |
el16ttb 0:54721f063ac8 496 ((y1 & 0x7F) << 2) |
el16ttb 0:54721f063ac8 497 (type & 0x3));
el16ttb 0:54721f063ac8 498
el16ttb 0:54721f063ac8 499 }
el16ttb 0:54721f063ac8 500
el16ttb 0:54721f063ac8 501 void N5110::drawRect(unsigned int const x0,
el16ttb 0:54721f063ac8 502 unsigned int const y0,
el16ttb 0:54721f063ac8 503 unsigned int const width,
el16ttb 0:54721f063ac8 504 unsigned int const height,
el16ttb 0:54721f063ac8 505 FillType const fill)
el16ttb 0:54721f063ac8 506 {
el16ttb 0:54721f063ac8 507 _stream->lock();
el16ttb 0:54721f063ac8 508 if (fill == FILL_TRANSPARENT) { // transparent, just outline
el16ttb 0:54721f063ac8 509 drawLine(x0, y0, x0+(width-1), y0,1); // top
el16ttb 0:54721f063ac8 510 drawLine(x0, y0+(height-1),x0+(width-1), y0+(height-1),1); // bottom
el16ttb 0:54721f063ac8 511 drawLine(x0, y0, x0, y0+(height-1),1); // left
el16ttb 0:54721f063ac8 512 drawLine(x0+(width-1),y0, x0+(width-1), y0+(height-1),1); // right
el16ttb 0:54721f063ac8 513 } else { // filled rectangle
el16ttb 0:54721f063ac8 514 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill
el16ttb 0:54721f063ac8 515 for (int y = y0; y<y0+height; y++) { // loop through rows of rectangle
el16ttb 0:54721f063ac8 516 drawLine(x0,y,x0+(width-1),y,type); // draw line across screen
el16ttb 0:54721f063ac8 517 }
el16ttb 0:54721f063ac8 518 }
el16ttb 0:54721f063ac8 519 _stream->unlock();
el16ttb 0:54721f063ac8 520 _stream->writeMessage(0xc,
el16ttb 0:54721f063ac8 521 ((x0 & 0x7F) << 23) |
el16ttb 0:54721f063ac8 522 ((y0 & 0x7F) << 16) |
el16ttb 0:54721f063ac8 523 ((width & 0x7F) << 9) |
el16ttb 0:54721f063ac8 524 ((height & 0x7F) << 2) |
el16ttb 0:54721f063ac8 525 (fill==FILL_TRANSPARENT ? 0x00 : (fill==FILL_BLACK ? 0x01 : 0x02)));
el16ttb 0:54721f063ac8 526 }
el16ttb 0:54721f063ac8 527
el16ttb 0:54721f063ac8 528 void N5110::drawSprite(int x0,
el16ttb 0:54721f063ac8 529 int y0,
el16ttb 0:54721f063ac8 530 int nrows,
el16ttb 0:54721f063ac8 531 int ncols,
el16ttb 0:54721f063ac8 532 int *sprite)
el16ttb 0:54721f063ac8 533 {
el16ttb 0:54721f063ac8 534 for (int i = 0; i < nrows; i++) {
el16ttb 0:54721f063ac8 535 for (int j = 0 ; j < ncols ; j++) {
el16ttb 0:54721f063ac8 536
el16ttb 0:54721f063ac8 537 int pixel = *((sprite+i*ncols)+j);
el16ttb 0:54721f063ac8 538 setPixel(x0+j,y0+i, pixel);
el16ttb 0:54721f063ac8 539 }
el16ttb 0:54721f063ac8 540 }
el16ttb 0:54721f063ac8 541 }
el16ttb 0:54721f063ac8 542