“Race Collision” is a one player game in which a truck has to avoid “particles” that appear on the road. By the use of the joystick, the player can guide themselves through the menu system to start the game. The truck is the main element of the game and it can be moved from side to side with the joystick. The road curves randomly from time to time and the player has to be careful to keep the truck within the road boundaries. Particles appear on the screen at random positions and 4 collisions lead to the end of the game.

Dependencies:   ELEC2645_JoystickLCD_LPC1768_2021

Committer:
alex_20
Date:
Sun Mar 21 17:03:59 2021 +0000
Revision:
4:def20a1665d1
Parent:
3:cbe2dcca5058
Child:
5:7930d289e7fc
before curve switched to one case

Who changed what in which revision?

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