Simon Atkinson 201255483

Dependencies:   mbed

Snake Game

Summary

Hello and welcome to my Snake Game. Snake is a simple game where you control a snake and eat an apple which increases your size. Normally touching the walls will kill you, always touching yourself will make you die!

Controls

The Controls for this game are simple the Start button starts the game (who would have thought) this button is the left button on the bottom of the gamepad next to the two blue potentiometers. The Reset button on the right of the potentiometers resets the game. Once the game starts use the left thumbstick to control the movement of the snake.

If you hit the wall with your snake you will die and the game will end.

Bugs/Missing Features

Unfortunatley I wasn't able to get the game eating the apple to work, when I tried I could never get it to detect the collisions I tried a few different ways but ran out of time. Because that doesn't work the score doesn't increase and the apple doesn't spawn in a different place. I will try continue to work on this when I have time as I enjoyed doing this project even though it was very frustrating at times!

Committer:
Psy1990
Date:
Fri Jun 05 22:57:33 2020 +0000
Revision:
21:e8d66c5f68cc
Parent:
0:7423345f87c5
Final Submission. I have read and agreed with Statement of Academic Integrity.

Who changed what in which revision?

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