All there but errors need fixing

Dependencies:   mbed

Overview:

Rookie Tetris is a jigsaw style game based on the classic Tetris.

A block will appear at the top of the screen, you must move it (your options for movement are left, right and down - you cannot move up the board). The block will stop when it if placed either on the floor of the board or on-top of another block.

Your goal is to fill a complete row of the board with the blocks; when you do so the row will delete and the pattern above it will drop down. The game is over when your pattern is tall enough to reach to the top of the board!

Controls:

Use the joystick to move your block! Your block cannot move out of the parameters of the board.

Pot 2 controls the contrast of the screen.

Committer:
el18rs
Date:
Fri May 22 10:36:01 2020 +0000
Revision:
1:35dba0833c7d
Start

Who changed what in which revision?

UserRevisionLine numberNew contents of line
el18rs 1:35dba0833c7d 1 #include "Gamepad.h"
el18rs 1:35dba0833c7d 2
el18rs 1:35dba0833c7d 3 #include "mbed.h"
el18rs 1:35dba0833c7d 4
el18rs 1:35dba0833c7d 5 //////////// constructor/destructor ////////////
el18rs 1:35dba0833c7d 6 Gamepad::Gamepad()
el18rs 1:35dba0833c7d 7 :
el18rs 1:35dba0833c7d 8 _led1(new PwmOut(PTA2)),
el18rs 1:35dba0833c7d 9 _led2(new PwmOut(PTC2)),
el18rs 1:35dba0833c7d 10 _led3(new PwmOut(PTC3)),
el18rs 1:35dba0833c7d 11 _led4(new PwmOut(PTA1)),
el18rs 1:35dba0833c7d 12 _led5(new PwmOut(PTC10)),
el18rs 1:35dba0833c7d 13 _led6(new PwmOut(PTC11)),
el18rs 1:35dba0833c7d 14
el18rs 1:35dba0833c7d 15 _button_A(new InterruptIn(PTC7)),
el18rs 1:35dba0833c7d 16 _button_B(new InterruptIn(PTC9)),
el18rs 1:35dba0833c7d 17 _button_X(new InterruptIn(PTC5)),
el18rs 1:35dba0833c7d 18 _button_Y(new InterruptIn(PTC0)),
el18rs 1:35dba0833c7d 19 _button_start(new InterruptIn(PTC8)),
el18rs 1:35dba0833c7d 20
el18rs 1:35dba0833c7d 21 _vert(new AnalogIn(PTB11)),
el18rs 1:35dba0833c7d 22 _horiz(new AnalogIn(PTB10)),
el18rs 1:35dba0833c7d 23
el18rs 1:35dba0833c7d 24 _pot1(new AnalogIn(PTB2)),
el18rs 1:35dba0833c7d 25 _pot2(new AnalogIn(PTB3)),
el18rs 1:35dba0833c7d 26
el18rs 1:35dba0833c7d 27 dac(new AnalogOut(DAC0_OUT)),
el18rs 1:35dba0833c7d 28 ticker(new Ticker),
el18rs 1:35dba0833c7d 29 timeout(new Timeout),
el18rs 1:35dba0833c7d 30 note_timeout(new Timeout),
el18rs 1:35dba0833c7d 31
el18rs 1:35dba0833c7d 32 _x0(0),
el18rs 1:35dba0833c7d 33 _y0(0)
el18rs 1:35dba0833c7d 34 {}
el18rs 1:35dba0833c7d 35
el18rs 1:35dba0833c7d 36
el18rs 1:35dba0833c7d 37 ///////////////// public methods /////////////////
el18rs 1:35dba0833c7d 38
el18rs 1:35dba0833c7d 39 void Gamepad::init()
el18rs 1:35dba0833c7d 40 {
el18rs 1:35dba0833c7d 41 leds_off();
el18rs 1:35dba0833c7d 42
el18rs 1:35dba0833c7d 43 // read centred values of joystick
el18rs 1:35dba0833c7d 44 _x0 = _horiz->read();
el18rs 1:35dba0833c7d 45 _y0 = _vert->read();
el18rs 1:35dba0833c7d 46
el18rs 1:35dba0833c7d 47 // Set all buttons to PullUp
el18rs 1:35dba0833c7d 48 _button_A->mode(PullUp);
el18rs 1:35dba0833c7d 49 _button_B->mode(PullUp);
el18rs 1:35dba0833c7d 50 _button_X->mode(PullUp);
el18rs 1:35dba0833c7d 51 _button_Y->mode(PullUp);
el18rs 1:35dba0833c7d 52 _button_start->mode(PullUp);
el18rs 1:35dba0833c7d 53
el18rs 1:35dba0833c7d 54 // Set up interrupts for the fall of buttons
el18rs 1:35dba0833c7d 55 _button_A->fall(callback(this,&Gamepad::A_fall_interrupt));
el18rs 1:35dba0833c7d 56 _button_B->fall(callback(this,&Gamepad::B_fall_interrupt));
el18rs 1:35dba0833c7d 57 _button_X->fall(callback(this,&Gamepad::X_fall_interrupt));
el18rs 1:35dba0833c7d 58 _button_Y->fall(callback(this,&Gamepad::Y_fall_interrupt));
el18rs 1:35dba0833c7d 59 _button_start->fall(callback(this,&Gamepad::start_fall_interrupt));
el18rs 1:35dba0833c7d 60
el18rs 1:35dba0833c7d 61 // initalise button flags
el18rs 1:35dba0833c7d 62 reset_buttons();
el18rs 1:35dba0833c7d 63
el18rs 1:35dba0833c7d 64 // number of samples
el18rs 1:35dba0833c7d 65 _n = 16;
el18rs 1:35dba0833c7d 66 _sample_array = new float[_n];
el18rs 1:35dba0833c7d 67
el18rs 1:35dba0833c7d 68 // create sample array for one period between 0.0 and 1.0
el18rs 1:35dba0833c7d 69 for (int i = 0; i < _n ; i++) {
el18rs 1:35dba0833c7d 70 _sample_array[i] = 0.5f + 0.5f*sin(i*2*PI/_n);
el18rs 1:35dba0833c7d 71 //printf("y[%i] = %f\n",i,_sample_array[i]);
el18rs 1:35dba0833c7d 72 }
el18rs 1:35dba0833c7d 73
el18rs 1:35dba0833c7d 74 }
el18rs 1:35dba0833c7d 75
el18rs 1:35dba0833c7d 76 void Gamepad::leds_off()
el18rs 1:35dba0833c7d 77 {
el18rs 1:35dba0833c7d 78 leds(0.0);
el18rs 1:35dba0833c7d 79 }
el18rs 1:35dba0833c7d 80
el18rs 1:35dba0833c7d 81 void Gamepad::leds_on()
el18rs 1:35dba0833c7d 82 {
el18rs 1:35dba0833c7d 83 leds(1.0);
el18rs 1:35dba0833c7d 84 }
el18rs 1:35dba0833c7d 85
el18rs 1:35dba0833c7d 86 void Gamepad::leds(float val) const
el18rs 1:35dba0833c7d 87 {
el18rs 1:35dba0833c7d 88 if (val < 0.0f) {
el18rs 1:35dba0833c7d 89 val = 0.0f;
el18rs 1:35dba0833c7d 90 }
el18rs 1:35dba0833c7d 91 if (val > 1.0f) {
el18rs 1:35dba0833c7d 92 val = 1.0f;
el18rs 1:35dba0833c7d 93 }
el18rs 1:35dba0833c7d 94
el18rs 1:35dba0833c7d 95 // leds are active-low, so subtract from 1.0
el18rs 1:35dba0833c7d 96 // 0.0 corresponds to fully-off, 1.0 to fully-on
el18rs 1:35dba0833c7d 97 val = 1.0f - val;
el18rs 1:35dba0833c7d 98
el18rs 1:35dba0833c7d 99 _led1->write(val);
el18rs 1:35dba0833c7d 100 _led2->write(val);
el18rs 1:35dba0833c7d 101 _led3->write(val);
el18rs 1:35dba0833c7d 102 _led4->write(val);
el18rs 1:35dba0833c7d 103 _led5->write(val);
el18rs 1:35dba0833c7d 104 _led6->write(val);
el18rs 1:35dba0833c7d 105 }
el18rs 1:35dba0833c7d 106
el18rs 1:35dba0833c7d 107 void Gamepad::led(int n,float val) const
el18rs 1:35dba0833c7d 108 {
el18rs 1:35dba0833c7d 109 // ensure they are within valid range
el18rs 1:35dba0833c7d 110 if (val < 0.0f) {
el18rs 1:35dba0833c7d 111 val = 0.0f;
el18rs 1:35dba0833c7d 112 }
el18rs 1:35dba0833c7d 113 if (val > 1.0f) {
el18rs 1:35dba0833c7d 114 val = 1.0f;
el18rs 1:35dba0833c7d 115 }
el18rs 1:35dba0833c7d 116
el18rs 1:35dba0833c7d 117 switch (n) {
el18rs 1:35dba0833c7d 118
el18rs 1:35dba0833c7d 119 // check for valid LED number and set value
el18rs 1:35dba0833c7d 120
el18rs 1:35dba0833c7d 121 case 1:
el18rs 1:35dba0833c7d 122 _led1->write(1.0f-val); // active-low so subtract from 1
el18rs 1:35dba0833c7d 123 break;
el18rs 1:35dba0833c7d 124 case 2:
el18rs 1:35dba0833c7d 125 _led2->write(1.0f-val); // active-low so subtract from 1
el18rs 1:35dba0833c7d 126 break;
el18rs 1:35dba0833c7d 127 case 3:
el18rs 1:35dba0833c7d 128 _led3->write(1.0f-val); // active-low so subtract from 1
el18rs 1:35dba0833c7d 129 break;
el18rs 1:35dba0833c7d 130 case 4:
el18rs 1:35dba0833c7d 131 _led4->write(1.0f-val); // active-low so subtract from 1
el18rs 1:35dba0833c7d 132 break;
el18rs 1:35dba0833c7d 133 case 5:
el18rs 1:35dba0833c7d 134 _led5->write(1.0f-val); // active-low so subtract from 1
el18rs 1:35dba0833c7d 135 break;
el18rs 1:35dba0833c7d 136 case 6:
el18rs 1:35dba0833c7d 137 _led6->write(1.0f-val); // active-low so subtract from 1
el18rs 1:35dba0833c7d 138 break;
el18rs 1:35dba0833c7d 139
el18rs 1:35dba0833c7d 140 }
el18rs 1:35dba0833c7d 141 }
el18rs 1:35dba0833c7d 142
el18rs 1:35dba0833c7d 143 float Gamepad::read_pot1() const
el18rs 1:35dba0833c7d 144 {
el18rs 1:35dba0833c7d 145 return _pot1->read();
el18rs 1:35dba0833c7d 146 }
el18rs 1:35dba0833c7d 147
el18rs 1:35dba0833c7d 148 float Gamepad::read_pot2() const
el18rs 1:35dba0833c7d 149 {
el18rs 1:35dba0833c7d 150 return _pot2->read();
el18rs 1:35dba0833c7d 151 }
el18rs 1:35dba0833c7d 152
el18rs 1:35dba0833c7d 153
el18rs 1:35dba0833c7d 154 // this method gets the magnitude of the joystick movement
el18rs 1:35dba0833c7d 155 float Gamepad::get_mag()
el18rs 1:35dba0833c7d 156 {
el18rs 1:35dba0833c7d 157 Polar p = get_polar();
el18rs 1:35dba0833c7d 158 return p.mag;
el18rs 1:35dba0833c7d 159 }
el18rs 1:35dba0833c7d 160
el18rs 1:35dba0833c7d 161 // this method gets the angle of joystick movement (0 to 360, 0 North)
el18rs 1:35dba0833c7d 162 float Gamepad::get_angle()
el18rs 1:35dba0833c7d 163 {
el18rs 1:35dba0833c7d 164 Polar p = get_polar();
el18rs 1:35dba0833c7d 165 return p.angle;
el18rs 1:35dba0833c7d 166 }
el18rs 1:35dba0833c7d 167
el18rs 1:35dba0833c7d 168 Direction Gamepad::get_direction()
el18rs 1:35dba0833c7d 169 {
el18rs 1:35dba0833c7d 170 float angle = get_angle(); // 0 to 360, -1 for centred
el18rs 1:35dba0833c7d 171
el18rs 1:35dba0833c7d 172 Direction d;
el18rs 1:35dba0833c7d 173 // partition 360 into segments and check which segment the angle is in
el18rs 1:35dba0833c7d 174 if (angle < 0.0f) {
el18rs 1:35dba0833c7d 175 d = CENTRE; // check for -1.0 angle
el18rs 1:35dba0833c7d 176 } else if (angle < 22.5f) { // then keep going in 45 degree increments
el18rs 1:35dba0833c7d 177 d = N;
el18rs 1:35dba0833c7d 178 } else if (angle < 67.5f) {
el18rs 1:35dba0833c7d 179 d = NE;
el18rs 1:35dba0833c7d 180 } else if (angle < 112.5f) {
el18rs 1:35dba0833c7d 181 d = E;
el18rs 1:35dba0833c7d 182 } else if (angle < 157.5f) {
el18rs 1:35dba0833c7d 183 d = SE;
el18rs 1:35dba0833c7d 184 } else if (angle < 202.5f) {
el18rs 1:35dba0833c7d 185 d = S;
el18rs 1:35dba0833c7d 186 } else if (angle < 247.5f) {
el18rs 1:35dba0833c7d 187 d = SW;
el18rs 1:35dba0833c7d 188 } else if (angle < 292.5f) {
el18rs 1:35dba0833c7d 189 d = W;
el18rs 1:35dba0833c7d 190 } else if (angle < 337.5f) {
el18rs 1:35dba0833c7d 191 d = NW;
el18rs 1:35dba0833c7d 192 } else {
el18rs 1:35dba0833c7d 193 d = N;
el18rs 1:35dba0833c7d 194 }
el18rs 1:35dba0833c7d 195
el18rs 1:35dba0833c7d 196 return d;
el18rs 1:35dba0833c7d 197 }
el18rs 1:35dba0833c7d 198
el18rs 1:35dba0833c7d 199 void Gamepad::reset_buttons()
el18rs 1:35dba0833c7d 200 {
el18rs 1:35dba0833c7d 201 A_fall = B_fall = X_fall = Y_fall = start_fall = false;
el18rs 1:35dba0833c7d 202 }
el18rs 1:35dba0833c7d 203
el18rs 1:35dba0833c7d 204 bool Gamepad::A_pressed()
el18rs 1:35dba0833c7d 205 {
el18rs 1:35dba0833c7d 206 if (A_fall) {
el18rs 1:35dba0833c7d 207 A_fall = false;
el18rs 1:35dba0833c7d 208 return true;
el18rs 1:35dba0833c7d 209 } else {
el18rs 1:35dba0833c7d 210 return false;
el18rs 1:35dba0833c7d 211 }
el18rs 1:35dba0833c7d 212 }
el18rs 1:35dba0833c7d 213
el18rs 1:35dba0833c7d 214 bool Gamepad::B_pressed()
el18rs 1:35dba0833c7d 215 {
el18rs 1:35dba0833c7d 216 if (B_fall) {
el18rs 1:35dba0833c7d 217 B_fall = false;
el18rs 1:35dba0833c7d 218 return true;
el18rs 1:35dba0833c7d 219 } else {
el18rs 1:35dba0833c7d 220 return false;
el18rs 1:35dba0833c7d 221 }
el18rs 1:35dba0833c7d 222 }
el18rs 1:35dba0833c7d 223
el18rs 1:35dba0833c7d 224 bool Gamepad::X_pressed()
el18rs 1:35dba0833c7d 225 {
el18rs 1:35dba0833c7d 226 if (X_fall) {
el18rs 1:35dba0833c7d 227 X_fall = false;
el18rs 1:35dba0833c7d 228 return true;
el18rs 1:35dba0833c7d 229 } else {
el18rs 1:35dba0833c7d 230 return false;
el18rs 1:35dba0833c7d 231 }
el18rs 1:35dba0833c7d 232 }
el18rs 1:35dba0833c7d 233
el18rs 1:35dba0833c7d 234 bool Gamepad::Y_pressed()
el18rs 1:35dba0833c7d 235 {
el18rs 1:35dba0833c7d 236 if (Y_fall) {
el18rs 1:35dba0833c7d 237 Y_fall = false;
el18rs 1:35dba0833c7d 238 return true;
el18rs 1:35dba0833c7d 239 } else {
el18rs 1:35dba0833c7d 240 return false;
el18rs 1:35dba0833c7d 241 }
el18rs 1:35dba0833c7d 242 }
el18rs 1:35dba0833c7d 243
el18rs 1:35dba0833c7d 244 bool Gamepad::start_pressed()
el18rs 1:35dba0833c7d 245 {
el18rs 1:35dba0833c7d 246 if (start_fall) {
el18rs 1:35dba0833c7d 247 start_fall = false;
el18rs 1:35dba0833c7d 248 return true;
el18rs 1:35dba0833c7d 249 } else {
el18rs 1:35dba0833c7d 250 return false;
el18rs 1:35dba0833c7d 251 }
el18rs 1:35dba0833c7d 252 }
el18rs 1:35dba0833c7d 253
el18rs 1:35dba0833c7d 254 bool Gamepad::A_held()
el18rs 1:35dba0833c7d 255 {
el18rs 1:35dba0833c7d 256 // Buttons are configured as PullUp hence the not
el18rs 1:35dba0833c7d 257 return !_button_A->read();
el18rs 1:35dba0833c7d 258 }
el18rs 1:35dba0833c7d 259
el18rs 1:35dba0833c7d 260 bool Gamepad::B_held()
el18rs 1:35dba0833c7d 261 {
el18rs 1:35dba0833c7d 262 return !_button_B->read();
el18rs 1:35dba0833c7d 263 }
el18rs 1:35dba0833c7d 264
el18rs 1:35dba0833c7d 265 bool Gamepad::X_held()
el18rs 1:35dba0833c7d 266 {
el18rs 1:35dba0833c7d 267 return !_button_X->read();
el18rs 1:35dba0833c7d 268 }
el18rs 1:35dba0833c7d 269
el18rs 1:35dba0833c7d 270 bool Gamepad::Y_held()
el18rs 1:35dba0833c7d 271 {
el18rs 1:35dba0833c7d 272 return !_button_Y->read();
el18rs 1:35dba0833c7d 273 }
el18rs 1:35dba0833c7d 274
el18rs 1:35dba0833c7d 275 bool Gamepad::start_held()
el18rs 1:35dba0833c7d 276 {
el18rs 1:35dba0833c7d 277 return !_button_start->read();
el18rs 1:35dba0833c7d 278 }
el18rs 1:35dba0833c7d 279
el18rs 1:35dba0833c7d 280 ///////////////////// private methods ////////////////////////
el18rs 1:35dba0833c7d 281
el18rs 1:35dba0833c7d 282 // get raw joystick coordinate in range -1 to 1
el18rs 1:35dba0833c7d 283 // Direction (x,y)
el18rs 1:35dba0833c7d 284 // North (0,1)
el18rs 1:35dba0833c7d 285 // East (1,0)
el18rs 1:35dba0833c7d 286 // South (0,-1)
el18rs 1:35dba0833c7d 287 // West (-1,0)
el18rs 1:35dba0833c7d 288 Vector2D Gamepad::get_coord()
el18rs 1:35dba0833c7d 289 {
el18rs 1:35dba0833c7d 290 // read() returns value in range 0.0 to 1.0 so is scaled and centre value
el18rs 1:35dba0833c7d 291 // substracted to get values in the range -1.0 to 1.0
el18rs 1:35dba0833c7d 292 float x = 2.0f*( _horiz->read() - _x0 );
el18rs 1:35dba0833c7d 293 float y = 2.0f*( _vert->read() - _y0 );
el18rs 1:35dba0833c7d 294
el18rs 1:35dba0833c7d 295 // Note: the y value here is inverted to ensure the positive y is up
el18rs 1:35dba0833c7d 296
el18rs 1:35dba0833c7d 297 Vector2D coord = {x,-y};
el18rs 1:35dba0833c7d 298 return coord;
el18rs 1:35dba0833c7d 299 }
el18rs 1:35dba0833c7d 300
el18rs 1:35dba0833c7d 301 // This maps the raw x,y coord onto a circular grid.
el18rs 1:35dba0833c7d 302 // See: http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html
el18rs 1:35dba0833c7d 303 Vector2D Gamepad::get_mapped_coord()
el18rs 1:35dba0833c7d 304 {
el18rs 1:35dba0833c7d 305 Vector2D coord = get_coord();
el18rs 1:35dba0833c7d 306
el18rs 1:35dba0833c7d 307 // do the transformation
el18rs 1:35dba0833c7d 308 float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f);
el18rs 1:35dba0833c7d 309 float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f);
el18rs 1:35dba0833c7d 310
el18rs 1:35dba0833c7d 311 Vector2D mapped_coord = {x,y};
el18rs 1:35dba0833c7d 312 return mapped_coord;
el18rs 1:35dba0833c7d 313 }
el18rs 1:35dba0833c7d 314
el18rs 1:35dba0833c7d 315 // this function converts the mapped coordinates into polar form
el18rs 1:35dba0833c7d 316 Polar Gamepad::get_polar()
el18rs 1:35dba0833c7d 317 {
el18rs 1:35dba0833c7d 318 // get the mapped coordinate
el18rs 1:35dba0833c7d 319 Vector2D coord = get_mapped_coord();
el18rs 1:35dba0833c7d 320
el18rs 1:35dba0833c7d 321 // at this point, 0 degrees (i.e. x-axis) will be defined to the East.
el18rs 1:35dba0833c7d 322 // We want 0 degrees to correspond to North and increase clockwise to 359
el18rs 1:35dba0833c7d 323 // like a compass heading, so we need to swap the axis and invert y
el18rs 1:35dba0833c7d 324 float x = coord.y;
el18rs 1:35dba0833c7d 325 float y = coord.x;
el18rs 1:35dba0833c7d 326
el18rs 1:35dba0833c7d 327 float mag = sqrt(x*x+y*y); // pythagoras
el18rs 1:35dba0833c7d 328 float angle = RAD2DEG*atan2(y,x);
el18rs 1:35dba0833c7d 329 // angle will be in range -180 to 180, so add 360 to negative angles to
el18rs 1:35dba0833c7d 330 // move to 0 to 360 range
el18rs 1:35dba0833c7d 331 if (angle < 0.0f) {
el18rs 1:35dba0833c7d 332 angle+=360.0f;
el18rs 1:35dba0833c7d 333 }
el18rs 1:35dba0833c7d 334
el18rs 1:35dba0833c7d 335 // the noise on the ADC causes the values of x and y to fluctuate slightly
el18rs 1:35dba0833c7d 336 // around the centred values. This causes the random angle values to get
el18rs 1:35dba0833c7d 337 // calculated when the joystick is centred and untouched. This is also when
el18rs 1:35dba0833c7d 338 // the magnitude is very small, so we can check for a small magnitude and then
el18rs 1:35dba0833c7d 339 // set the angle to -1. This will inform us when the angle is invalid and the
el18rs 1:35dba0833c7d 340 // joystick is centred
el18rs 1:35dba0833c7d 341
el18rs 1:35dba0833c7d 342 if (mag < TOL) {
el18rs 1:35dba0833c7d 343 mag = 0.0f;
el18rs 1:35dba0833c7d 344 angle = -1.0f;
el18rs 1:35dba0833c7d 345 }
el18rs 1:35dba0833c7d 346
el18rs 1:35dba0833c7d 347 Polar p = {mag,angle};
el18rs 1:35dba0833c7d 348 return p;
el18rs 1:35dba0833c7d 349 }
el18rs 1:35dba0833c7d 350
el18rs 1:35dba0833c7d 351 // ISRs for buttons
el18rs 1:35dba0833c7d 352 void Gamepad::A_fall_interrupt()
el18rs 1:35dba0833c7d 353 {
el18rs 1:35dba0833c7d 354 A_fall = true;
el18rs 1:35dba0833c7d 355 }
el18rs 1:35dba0833c7d 356 void Gamepad::B_fall_interrupt()
el18rs 1:35dba0833c7d 357 {
el18rs 1:35dba0833c7d 358 B_fall = true;
el18rs 1:35dba0833c7d 359 }
el18rs 1:35dba0833c7d 360 void Gamepad::X_fall_interrupt()
el18rs 1:35dba0833c7d 361 {
el18rs 1:35dba0833c7d 362 X_fall = true;
el18rs 1:35dba0833c7d 363 }
el18rs 1:35dba0833c7d 364 void Gamepad::Y_fall_interrupt()
el18rs 1:35dba0833c7d 365 {
el18rs 1:35dba0833c7d 366 Y_fall = true;
el18rs 1:35dba0833c7d 367 }
el18rs 1:35dba0833c7d 368 void Gamepad::start_fall_interrupt()
el18rs 1:35dba0833c7d 369 {
el18rs 1:35dba0833c7d 370 start_fall = true;
el18rs 1:35dba0833c7d 371 }
el18rs 1:35dba0833c7d 372
el18rs 1:35dba0833c7d 373 void Gamepad::set_bpm(float bpm)
el18rs 1:35dba0833c7d 374 {
el18rs 1:35dba0833c7d 375 _bpm = bpm;
el18rs 1:35dba0833c7d 376 }
el18rs 1:35dba0833c7d 377
el18rs 1:35dba0833c7d 378 void Gamepad::tone(float frequency,float duration)
el18rs 1:35dba0833c7d 379 {
el18rs 1:35dba0833c7d 380 // calculate time step between samples
el18rs 1:35dba0833c7d 381 float dt = 1.0f/(frequency*_n);
el18rs 1:35dba0833c7d 382 // start from beginning of LUT
el18rs 1:35dba0833c7d 383 _sample = 0;
el18rs 1:35dba0833c7d 384
el18rs 1:35dba0833c7d 385 // setup ticker and timeout to stop ticker
el18rs 1:35dba0833c7d 386
el18rs 1:35dba0833c7d 387 // the ticker repeats every dt to plat each sample in turn
el18rs 1:35dba0833c7d 388 ticker->attach(callback(this, &Gamepad::ticker_isr), dt);
el18rs 1:35dba0833c7d 389 // the timeout stops the ticker after the required duration
el18rs 1:35dba0833c7d 390 timeout->attach(callback(this, &Gamepad::timeout_isr), duration );
el18rs 1:35dba0833c7d 391 }
el18rs 1:35dba0833c7d 392
el18rs 1:35dba0833c7d 393 void Gamepad::play_melody(int length,const int *notes,const int *durations,float bpm,bool repeat)
el18rs 1:35dba0833c7d 394 {
el18rs 1:35dba0833c7d 395 // copy arguments to member variables
el18rs 1:35dba0833c7d 396 _bpm = bpm;
el18rs 1:35dba0833c7d 397 _notes = notes; // pointer for array
el18rs 1:35dba0833c7d 398 _durations = durations; // pointer for array
el18rs 1:35dba0833c7d 399 _melody_length = length;
el18rs 1:35dba0833c7d 400 _repeat = repeat;
el18rs 1:35dba0833c7d 401
el18rs 1:35dba0833c7d 402 _note = 0; // start from first note
el18rs 1:35dba0833c7d 403
el18rs 1:35dba0833c7d 404 play_next_note(); // play the next note in the melody
el18rs 1:35dba0833c7d 405 }
el18rs 1:35dba0833c7d 406
el18rs 1:35dba0833c7d 407 void Gamepad::write_dac(float val)
el18rs 1:35dba0833c7d 408 {
el18rs 1:35dba0833c7d 409 if (val < 0.0f) {
el18rs 1:35dba0833c7d 410 val = 0.0f;
el18rs 1:35dba0833c7d 411 } else if (val > 1.0f) {
el18rs 1:35dba0833c7d 412 val = 1.0f;
el18rs 1:35dba0833c7d 413 }
el18rs 1:35dba0833c7d 414 dac->write(val);
el18rs 1:35dba0833c7d 415 }
el18rs 1:35dba0833c7d 416
el18rs 1:35dba0833c7d 417
el18rs 1:35dba0833c7d 418 void Gamepad::play_next_note()
el18rs 1:35dba0833c7d 419 {
el18rs 1:35dba0833c7d 420 // _note is the note index to play
el18rs 1:35dba0833c7d 421
el18rs 1:35dba0833c7d 422 // calculate the duration and frequency of the note
el18rs 1:35dba0833c7d 423 float duration = 60.0f/(_bpm*_durations[_note]);
el18rs 1:35dba0833c7d 424 float frequency = float(_notes[_note]);
el18rs 1:35dba0833c7d 425 //printf("[%i] f = %f d = %f\n",_note,frequency,duration);
el18rs 1:35dba0833c7d 426
el18rs 1:35dba0833c7d 427 // check if the note is not a space and if not then play the note
el18rs 1:35dba0833c7d 428 if (frequency > 0) {
el18rs 1:35dba0833c7d 429 tone(frequency,duration);
el18rs 1:35dba0833c7d 430 }
el18rs 1:35dba0833c7d 431
el18rs 1:35dba0833c7d 432 // the timeout goes to the next note in the melody
el18rs 1:35dba0833c7d 433 // double the duration to leave a bit of a gap in between notes to be better
el18rs 1:35dba0833c7d 434 // able to distinguish them
el18rs 1:35dba0833c7d 435 note_timeout->attach(callback(this, &Gamepad::note_timeout_isr), duration*2.0f );
el18rs 1:35dba0833c7d 436 }
el18rs 1:35dba0833c7d 437
el18rs 1:35dba0833c7d 438 // called when the next note needs playing
el18rs 1:35dba0833c7d 439 void Gamepad::note_timeout_isr()
el18rs 1:35dba0833c7d 440 {
el18rs 1:35dba0833c7d 441 _note++; // go onto next note
el18rs 1:35dba0833c7d 442
el18rs 1:35dba0833c7d 443 // if in repeat mode then reset the note counter when get to end of melody
el18rs 1:35dba0833c7d 444 if (_repeat && _note == _melody_length) {
el18rs 1:35dba0833c7d 445 _note=0;
el18rs 1:35dba0833c7d 446 }
el18rs 1:35dba0833c7d 447
el18rs 1:35dba0833c7d 448 // check if note is within the melody
el18rs 1:35dba0833c7d 449 if (_note < _melody_length) {
el18rs 1:35dba0833c7d 450 play_next_note();
el18rs 1:35dba0833c7d 451 }
el18rs 1:35dba0833c7d 452 }
el18rs 1:35dba0833c7d 453
el18rs 1:35dba0833c7d 454 void Gamepad::ticker_isr()
el18rs 1:35dba0833c7d 455 {
el18rs 1:35dba0833c7d 456 dac->write(_sample_array[_sample%_n]); // use modulo to get index to play
el18rs 1:35dba0833c7d 457 _sample++; // increment the sample ready for next time
el18rs 1:35dba0833c7d 458 }
el18rs 1:35dba0833c7d 459
el18rs 1:35dba0833c7d 460 void Gamepad::timeout_isr()
el18rs 1:35dba0833c7d 461 {
el18rs 1:35dba0833c7d 462 // stops the ticker to end the note
el18rs 1:35dba0833c7d 463 ticker->detach();
el18rs 1:35dba0833c7d 464 }