“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 19 20:04:39 2021 +0000
Revision:
3:cbe2dcca5058
Parent:
1:2ae7a8b01771
Child:
4:def20a1665d1
everything in N5110

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