“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:
Fri Mar 26 15:21:07 2021 +0000
Revision:
5:7930d289e7fc
Parent:
4:def20a1665d1
Child:
6:40ef2030334c
Road complete.; Start Car

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 5:7930d289e7fc 417 void N5110::drawCurve(std::vector<Vector2Df> curve_points, float 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 5:7930d289e7fc 428 for(int i = curve_points.size()-1; i > 0 ; i--){
alex_20 4:def20a1665d1 429 int x0 = static_cast<int>(curve_points[i].x);
alex_20 5:7930d289e7fc 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 5:7930d289e7fc 432 int y1 = static_cast<int>(curve_points[i-1].y);
alex_20 4:def20a1665d1 433
alex_20 5:7930d289e7fc 434 int const y_range = y0 - y1;
alex_20 5:7930d289e7fc 435 int const x_range = x1 - x0;
alex_20 5:7930d289e7fc 436
alex_20 5:7930d289e7fc 437 // ensure we loop from smallest to largest or else for-loop won't run as expected
alex_20 5:7930d289e7fc 438 //unsigned int const start = y_range > 0 ? y0:y1;
alex_20 5:7930d289e7fc 439 //unsigned int const stop = y_range > 0 ? y1:y0;
alex_20 5:7930d289e7fc 440
alex_20 5:7930d289e7fc 441 for (unsigned int y = y0; y <= y1 ; y++) {
alex_20 5:7930d289e7fc 442 // do linear interpolation
alex_20 5:7930d289e7fc 443 int const dy = y0 - y;
alex_20 5:7930d289e7fc 444 unsigned int const x = x0 + (x_range * (dy / (float)y_range));
alex_20 5:7930d289e7fc 445
alex_20 5:7930d289e7fc 446 // If the line type is '0', this will clear the pixel
alex_20 5:7930d289e7fc 447 // If it is '1' or '2', the pixel will be set
alex_20 5:7930d289e7fc 448 setPixel(x,y, fmod(pow(counter, 0.55) - fmod(offset, (2 * dash_len)), (2 * dash_len)) < dash_len);
alex_20 5:7930d289e7fc 449 counter++;
alex_20 5:7930d289e7fc 450 }
alex_20 4:def20a1665d1 451 }
alex_20 4:def20a1665d1 452 }
alex_20 4:def20a1665d1 453 }
alex_20 3:cbe2dcca5058 454
eencae 0:be41a15e7a86 455 void N5110::drawLine(unsigned int const x0,
eencae 0:be41a15e7a86 456 unsigned int const y0,
eencae 0:be41a15e7a86 457 unsigned int const x1,
eencae 0:be41a15e7a86 458 unsigned int const y1,
alex_20 4:def20a1665d1 459 unsigned int const offset,
alex_20 4:def20a1665d1 460 unsigned int const step)
eencae 0:be41a15e7a86 461 {
eencae 0:be41a15e7a86 462 // Note that the ranges can be negative so we have to turn the input values
eencae 0:be41a15e7a86 463 // into signed integers first
eencae 0:be41a15e7a86 464 int const y_range = static_cast<int>(y1) - static_cast<int>(y0);
eencae 0:be41a15e7a86 465 int const x_range = static_cast<int>(x1) - static_cast<int>(x0);
eencae 0:be41a15e7a86 466
eencae 0:be41a15e7a86 467 // make sure we loop over the largest range to get the most pixels on the display
eencae 0:be41a15e7a86 468 // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
eencae 0:be41a15e7a86 469 // or else we'll only end up with 1 pixel in the x column
eencae 0:be41a15e7a86 470 if ( abs(x_range) > abs(y_range) ) {
eencae 0:be41a15e7a86 471
eencae 0:be41a15e7a86 472 // ensure we loop from smallest to largest or else for-loop won't run as expected
eencae 0:be41a15e7a86 473 unsigned int const start = x_range > 0 ? x0:x1;
eencae 0:be41a15e7a86 474 unsigned int const stop = x_range > 0 ? x1:x0;
eencae 0:be41a15e7a86 475
eencae 0:be41a15e7a86 476 // loop between x pixels
eencae 0:be41a15e7a86 477 for (unsigned int x = start; x<= stop ; x+=step) {
eencae 0:be41a15e7a86 478 // do linear interpolation
alex_20 4:def20a1665d1 479 int const dx = static_cast<int>(x) - static_cast<int>(x0);
eencae 0:be41a15e7a86 480 unsigned int const y = y0 + y_range * dx / x_range;
eencae 0:be41a15e7a86 481
eencae 0:be41a15e7a86 482 // If the line type is '0', this will clear the pixel
eencae 0:be41a15e7a86 483 // If it is '1' or '2', the pixel will be set
alex_20 4:def20a1665d1 484 setPixel(x,y, FILL_BLACK);
eencae 0:be41a15e7a86 485 }
eencae 0:be41a15e7a86 486 } else {
eencae 0:be41a15e7a86 487
eencae 0:be41a15e7a86 488 // ensure we loop from smallest to largest or else for-loop won't run as expected
eencae 0:be41a15e7a86 489 unsigned int const start = y_range > 0 ? y0:y1;
eencae 0:be41a15e7a86 490 unsigned int const stop = y_range > 0 ? y1:y0;
eencae 0:be41a15e7a86 491
eencae 0:be41a15e7a86 492 for (unsigned int y = start; y<= stop ; y+=step) {
eencae 0:be41a15e7a86 493 // do linear interpolation
eencae 0:be41a15e7a86 494 int const dy = static_cast<int>(y)-static_cast<int>(y0);
eencae 0:be41a15e7a86 495 unsigned int const x = x0 + x_range * dy / y_range;
eencae 0:be41a15e7a86 496
eencae 0:be41a15e7a86 497 // If the line type is '0', this will clear the pixel
eencae 0:be41a15e7a86 498 // If it is '1' or '2', the pixel will be set
alex_20 4:def20a1665d1 499 setPixel(x,y, FILL_BLACK);
eencae 0:be41a15e7a86 500 }
eencae 0:be41a15e7a86 501 }
eencae 0:be41a15e7a86 502
eencae 0:be41a15e7a86 503 }
eencae 0:be41a15e7a86 504
eencae 0:be41a15e7a86 505 void N5110::drawRect(unsigned int const x0,
eencae 0:be41a15e7a86 506 unsigned int const y0,
eencae 0:be41a15e7a86 507 unsigned int const width,
eencae 0:be41a15e7a86 508 unsigned int const height,
eencae 0:be41a15e7a86 509 FillType const fill)
eencae 0:be41a15e7a86 510 {
eencae 0:be41a15e7a86 511 if (fill == FILL_TRANSPARENT) { // transparent, just outline
alex_20 4:def20a1665d1 512 drawLine(x0,y0,x0+(width-1),y0,0,1); // top
alex_20 4:def20a1665d1 513 drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),0,1); // bottom
alex_20 4:def20a1665d1 514 drawLine(x0,y0,x0,y0+(height-1),0,1); // left
alex_20 4:def20a1665d1 515 drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),0,1); // right
eencae 0:be41a15e7a86 516 } else { // filled rectangle
alex_20 4:def20a1665d1 517 int step = (fill==FILL_BLACK) ? 1:0; // black or white fill
eencae 0:be41a15e7a86 518 for (int y = y0; y<y0+height; y++) { // loop through rows of rectangle
alex_20 4:def20a1665d1 519 drawLine(x0,y,x0+(width-1),y,0,step); // draw line across screen
eencae 0:be41a15e7a86 520 }
eencae 0:be41a15e7a86 521 }
eencae 0:be41a15e7a86 522 }
eencae 0:be41a15e7a86 523
eencae 0:be41a15e7a86 524 void N5110::drawSprite(int x0,
eencae 0:be41a15e7a86 525 int y0,
eencae 0:be41a15e7a86 526 int nrows,
eencae 0:be41a15e7a86 527 int ncols,
eencae 0:be41a15e7a86 528 int *sprite)
eencae 0:be41a15e7a86 529 {
eencae 0:be41a15e7a86 530 for (int i = 0; i < nrows; i++) {
eencae 0:be41a15e7a86 531 for (int j = 0 ; j < ncols ; j++) {
eencae 0:be41a15e7a86 532
eencae 0:be41a15e7a86 533 int pixel = *((sprite+i*ncols)+j);
eencae 0:be41a15e7a86 534 setPixel(x0+j,y0+i, pixel);
eencae 0:be41a15e7a86 535 }
eencae 0:be41a15e7a86 536 }
eencae 0:be41a15e7a86 537 }