This Class allows the joystick, buttons and petiometers to be implemented easily and coherently in other classes

Fork of Gamepad by Craig Evans

Committer:
domkay97
Date:
Wed Apr 12 22:19:48 2017 +0000
Revision:
21:99ec20695524
Child:
22:2f5a009a82a6
Moved methods from display to operator class

Who changed what in which revision?

UserRevisionLine numberNew contents of line
domkay97 21:99ec20695524 1 #include "Controller.h"
domkay97 21:99ec20695524 2
domkay97 21:99ec20695524 3 #include "mbed.h"
domkay97 21:99ec20695524 4
domkay97 21:99ec20695524 5 //////////// constructor/destructor ////////////
domkay97 21:99ec20695524 6 Controller::Controller()
domkay97 21:99ec20695524 7 :
domkay97 21:99ec20695524 8 _led1(new PwmOut(PTA1)),
domkay97 21:99ec20695524 9 _led2(new PwmOut(PTA2)),
domkay97 21:99ec20695524 10 _led3(new PwmOut(PTC2)),
domkay97 21:99ec20695524 11 _led4(new PwmOut(PTC3)),
domkay97 21:99ec20695524 12 _led5(new PwmOut(PTC4)),
domkay97 21:99ec20695524 13 _led6(new PwmOut(PTD3)),
domkay97 21:99ec20695524 14
domkay97 21:99ec20695524 15 _button_A(new InterruptIn(PTB9)),
domkay97 21:99ec20695524 16 _button_B(new InterruptIn(PTD0)),
domkay97 21:99ec20695524 17 _button_X(new InterruptIn(PTC17)),
domkay97 21:99ec20695524 18 _button_Y(new InterruptIn(PTC12)),
domkay97 21:99ec20695524 19 _button_L(new InterruptIn(PTB18)),
domkay97 21:99ec20695524 20 _button_R(new InterruptIn(PTB3)),
domkay97 21:99ec20695524 21 _button_back(new InterruptIn(PTB19)),
domkay97 21:99ec20695524 22 _button_start(new InterruptIn(PTC5)),
domkay97 21:99ec20695524 23 _button_joystick(new InterruptIn(PTC16)),
domkay97 21:99ec20695524 24
domkay97 21:99ec20695524 25 _vert(new AnalogIn(PTB10)),
domkay97 21:99ec20695524 26 _horiz(new AnalogIn(PTB11)),
domkay97 21:99ec20695524 27
domkay97 21:99ec20695524 28 _buzzer(new PwmOut(PTC10)),
domkay97 21:99ec20695524 29 _pot(new AnalogIn(PTB2)),
domkay97 21:99ec20695524 30
domkay97 21:99ec20695524 31 _timeout(new Timeout()),
domkay97 21:99ec20695524 32
domkay97 21:99ec20695524 33 _event_state(0),
domkay97 21:99ec20695524 34
domkay97 21:99ec20695524 35 _x0(0),
domkay97 21:99ec20695524 36 _y0(0)
domkay97 21:99ec20695524 37 {}
domkay97 21:99ec20695524 38
domkay97 21:99ec20695524 39 Controller::~Controller()
domkay97 21:99ec20695524 40 {
domkay97 21:99ec20695524 41 delete _led1,_led2,_led3,_led4,_led5,_led6;
domkay97 21:99ec20695524 42 delete _button_A,_button_B,_button_joystick,_vert,_horiz;
domkay97 21:99ec20695524 43 delete _button_X,_button_Y,_button_back,_button_start;
domkay97 21:99ec20695524 44 delete _button_L,_button_R, _buzzer, _pot, _timeout;
domkay97 21:99ec20695524 45 }
domkay97 21:99ec20695524 46
domkay97 21:99ec20695524 47 ///////////////// public methods /////////////////
domkay97 21:99ec20695524 48
domkay97 21:99ec20695524 49 void Controller::init()
domkay97 21:99ec20695524 50 {
domkay97 21:99ec20695524 51 leds_off();
domkay97 21:99ec20695524 52 init_buttons();
domkay97 21:99ec20695524 53
domkay97 21:99ec20695524 54 // read centred values of joystick
domkay97 21:99ec20695524 55 _x0 = _horiz->read();
domkay97 21:99ec20695524 56 _y0 = _vert->read();
domkay97 21:99ec20695524 57
domkay97 21:99ec20695524 58 // clear all flags
domkay97 21:99ec20695524 59 _event_state = 0;
domkay97 21:99ec20695524 60 }
domkay97 21:99ec20695524 61
domkay97 21:99ec20695524 62 void Controller::leds_off()
domkay97 21:99ec20695524 63 {
domkay97 21:99ec20695524 64 leds(0.0);
domkay97 21:99ec20695524 65 }
domkay97 21:99ec20695524 66
domkay97 21:99ec20695524 67 void Controller::leds_on()
domkay97 21:99ec20695524 68 {
domkay97 21:99ec20695524 69 leds(1.0);
domkay97 21:99ec20695524 70 }
domkay97 21:99ec20695524 71
domkay97 21:99ec20695524 72 void Controller::leds(float val) const
domkay97 21:99ec20695524 73 {
domkay97 21:99ec20695524 74 if (val < 0.0f) {
domkay97 21:99ec20695524 75 val = 0.0f;
domkay97 21:99ec20695524 76 }
domkay97 21:99ec20695524 77 if (val > 1.0f) {
domkay97 21:99ec20695524 78 val = 1.0f;
domkay97 21:99ec20695524 79 }
domkay97 21:99ec20695524 80
domkay97 21:99ec20695524 81 // leds are active-low, so subtract from 1.0
domkay97 21:99ec20695524 82 // 0.0 corresponds to fully-off, 1.0 to fully-on
domkay97 21:99ec20695524 83 val = 1.0f - val;
domkay97 21:99ec20695524 84
domkay97 21:99ec20695524 85 _led1->write(val);
domkay97 21:99ec20695524 86 _led2->write(val);
domkay97 21:99ec20695524 87 _led3->write(val);
domkay97 21:99ec20695524 88 _led4->write(val);
domkay97 21:99ec20695524 89 _led5->write(val);
domkay97 21:99ec20695524 90 _led6->write(val);
domkay97 21:99ec20695524 91 }
domkay97 21:99ec20695524 92
domkay97 21:99ec20695524 93 void Controller::led(int n,float val) const
domkay97 21:99ec20695524 94 {
domkay97 21:99ec20695524 95 // ensure they are within vlaid range
domkay97 21:99ec20695524 96 if (val < 0.0f) {
domkay97 21:99ec20695524 97 val = 0.0f;
domkay97 21:99ec20695524 98 }
domkay97 21:99ec20695524 99 if (val > 1.0f) {
domkay97 21:99ec20695524 100 val = 1.0f;
domkay97 21:99ec20695524 101 }
domkay97 21:99ec20695524 102
domkay97 21:99ec20695524 103 switch (n) {
domkay97 21:99ec20695524 104
domkay97 21:99ec20695524 105 // check for valid LED number and set value
domkay97 21:99ec20695524 106
domkay97 21:99ec20695524 107 case 1:
domkay97 21:99ec20695524 108 _led1->write(1.0f-val); // active-low so subtract from 1
domkay97 21:99ec20695524 109 break;
domkay97 21:99ec20695524 110 case 2:
domkay97 21:99ec20695524 111 _led2->write(1.0f-val); // active-low so subtract from 1
domkay97 21:99ec20695524 112 break;
domkay97 21:99ec20695524 113 case 3:
domkay97 21:99ec20695524 114 _led3->write(1.0f-val); // active-low so subtract from 1
domkay97 21:99ec20695524 115 break;
domkay97 21:99ec20695524 116 case 4:
domkay97 21:99ec20695524 117 _led4->write(1.0f-val); // active-low so subtract from 1
domkay97 21:99ec20695524 118 break;
domkay97 21:99ec20695524 119 case 5:
domkay97 21:99ec20695524 120 _led5->write(1.0f-val); // active-low so subtract from 1
domkay97 21:99ec20695524 121 break;
domkay97 21:99ec20695524 122 case 6:
domkay97 21:99ec20695524 123 _led6->write(1.0f-val); // active-low so subtract from 1
domkay97 21:99ec20695524 124 break;
domkay97 21:99ec20695524 125
domkay97 21:99ec20695524 126 }
domkay97 21:99ec20695524 127 }
domkay97 21:99ec20695524 128
domkay97 21:99ec20695524 129 float Controller::read_pot() const
domkay97 21:99ec20695524 130 {
domkay97 21:99ec20695524 131 return _pot->read();
domkay97 21:99ec20695524 132 }
domkay97 21:99ec20695524 133
domkay97 21:99ec20695524 134 void Controller::tone(float frequency, float duration)
domkay97 21:99ec20695524 135 {
domkay97 21:99ec20695524 136 _buzzer->period(1.0f/frequency);
domkay97 21:99ec20695524 137 _buzzer->write(0.5); // 50% duty cycle - square wave
domkay97 21:99ec20695524 138 _timeout->attach(callback(this, &Controller::tone_off), duration );
domkay97 21:99ec20695524 139 }
domkay97 21:99ec20695524 140
domkay97 21:99ec20695524 141 bool Controller::check_event(ControllerEvent const id)
domkay97 21:99ec20695524 142 {
domkay97 21:99ec20695524 143 // Check whether event flag is set
domkay97 21:99ec20695524 144 if (_event_state[id]) {
domkay97 21:99ec20695524 145 _event_state.reset(id); // clear flag
domkay97 21:99ec20695524 146 return true;
domkay97 21:99ec20695524 147 } else {
domkay97 21:99ec20695524 148 return false;
domkay97 21:99ec20695524 149 }
domkay97 21:99ec20695524 150 }
domkay97 21:99ec20695524 151
domkay97 21:99ec20695524 152 // this method gets the magnitude of the joystick movement
domkay97 21:99ec20695524 153 float Controller::get_mag()
domkay97 21:99ec20695524 154 {
domkay97 21:99ec20695524 155 Polar p = get_polar();
domkay97 21:99ec20695524 156 return p.mag;
domkay97 21:99ec20695524 157 }
domkay97 21:99ec20695524 158
domkay97 21:99ec20695524 159 // this method gets the angle of joystick movement (0 to 360, 0 North)
domkay97 21:99ec20695524 160 float Controller::get_angle()
domkay97 21:99ec20695524 161 {
domkay97 21:99ec20695524 162 Polar p = get_polar();
domkay97 21:99ec20695524 163 return p.angle;
domkay97 21:99ec20695524 164 }
domkay97 21:99ec20695524 165
domkay97 21:99ec20695524 166 Direction Controller::get_direction()
domkay97 21:99ec20695524 167 {
domkay97 21:99ec20695524 168 float angle = get_angle(); // 0 to 360, -1 for centred
domkay97 21:99ec20695524 169
domkay97 21:99ec20695524 170 Direction d;
domkay97 21:99ec20695524 171 // partition 360 into segments and check which segment the angle is in
domkay97 21:99ec20695524 172 if (angle < 0.0f) {
domkay97 21:99ec20695524 173 d = CENTRE; // check for -1.0 angle
domkay97 21:99ec20695524 174 } else if (angle < 22.5f) { // then keep going in 45 degree increments
domkay97 21:99ec20695524 175 d = N;
domkay97 21:99ec20695524 176 } else if (angle < 67.5f) {
domkay97 21:99ec20695524 177 d = NE;
domkay97 21:99ec20695524 178 } else if (angle < 112.5f) {
domkay97 21:99ec20695524 179 d = E;
domkay97 21:99ec20695524 180 } else if (angle < 157.5f) {
domkay97 21:99ec20695524 181 d = SE;
domkay97 21:99ec20695524 182 } else if (angle < 202.5f) {
domkay97 21:99ec20695524 183 d = S;
domkay97 21:99ec20695524 184 } else if (angle < 247.5f) {
domkay97 21:99ec20695524 185 d = SW;
domkay97 21:99ec20695524 186 } else if (angle < 292.5f) {
domkay97 21:99ec20695524 187 d = W;
domkay97 21:99ec20695524 188 } else if (angle < 337.5f) {
domkay97 21:99ec20695524 189 d = NW;
domkay97 21:99ec20695524 190 } else {
domkay97 21:99ec20695524 191 d = N;
domkay97 21:99ec20695524 192 }
domkay97 21:99ec20695524 193
domkay97 21:99ec20695524 194 return d;
domkay97 21:99ec20695524 195 }
domkay97 21:99ec20695524 196
domkay97 21:99ec20695524 197 ///////////////////// private methods ////////////////////////
domkay97 21:99ec20695524 198
domkay97 21:99ec20695524 199 void Controller::tone_off()
domkay97 21:99ec20695524 200 {
domkay97 21:99ec20695524 201 // called after timeout
domkay97 21:99ec20695524 202 _buzzer->write(0.0);
domkay97 21:99ec20695524 203 }
domkay97 21:99ec20695524 204
domkay97 21:99ec20695524 205 void Controller::init_buttons()
domkay97 21:99ec20695524 206 {
domkay97 21:99ec20695524 207 // turn on pull-downs as other side of button is connected to 3V3
domkay97 21:99ec20695524 208 // button is 0 when not pressed and 1 when pressed
domkay97 21:99ec20695524 209 _button_A->mode(PullDown);
domkay97 21:99ec20695524 210 _button_B->mode(PullDown);
domkay97 21:99ec20695524 211 _button_X->mode(PullDown);
domkay97 21:99ec20695524 212 _button_Y->mode(PullDown);
domkay97 21:99ec20695524 213 _button_back->mode(PullDown);
domkay97 21:99ec20695524 214 _button_start->mode(PullDown);
domkay97 21:99ec20695524 215 _button_L->mode(PullDown);
domkay97 21:99ec20695524 216 _button_R->mode(PullDown);
domkay97 21:99ec20695524 217 _button_joystick->mode(PullDown);
domkay97 21:99ec20695524 218 // therefore setup rising edge interrupts
domkay97 21:99ec20695524 219 _button_A->rise(callback(this,&Controller::a_isr));
domkay97 21:99ec20695524 220 _button_B->rise(callback(this,&Controller::b_isr));
domkay97 21:99ec20695524 221 _button_X->rise(callback(this,&Controller::x_isr));
domkay97 21:99ec20695524 222 _button_Y->rise(callback(this,&Controller::y_isr));
domkay97 21:99ec20695524 223 _button_L->rise(callback(this,&Controller::l_isr));
domkay97 21:99ec20695524 224 _button_R->rise(callback(this,&Controller::r_isr));
domkay97 21:99ec20695524 225 _button_start->rise(callback(this,&Controller::start_isr));
domkay97 21:99ec20695524 226 _button_back->rise(callback(this,&Controller::back_isr));
domkay97 21:99ec20695524 227 _button_joystick->rise(callback(this,&Controller::joy_isr));
domkay97 21:99ec20695524 228 }
domkay97 21:99ec20695524 229
domkay97 21:99ec20695524 230 // button interrupts ISRs
domkay97 21:99ec20695524 231 // Each of these simply sets the appropriate event bit in the _event_state
domkay97 21:99ec20695524 232 // variable
domkay97 21:99ec20695524 233 void Controller::a_isr()
domkay97 21:99ec20695524 234 {
domkay97 21:99ec20695524 235 _event_state.set(A_PRESSED);
domkay97 21:99ec20695524 236 }
domkay97 21:99ec20695524 237 void Controller::b_isr()
domkay97 21:99ec20695524 238 {
domkay97 21:99ec20695524 239 _event_state.set(B_PRESSED);
domkay97 21:99ec20695524 240 }
domkay97 21:99ec20695524 241 void Controller::x_isr()
domkay97 21:99ec20695524 242 {
domkay97 21:99ec20695524 243 _event_state.set(X_PRESSED);
domkay97 21:99ec20695524 244 }
domkay97 21:99ec20695524 245 void Controller::y_isr()
domkay97 21:99ec20695524 246 {
domkay97 21:99ec20695524 247 _event_state.set(Y_PRESSED);
domkay97 21:99ec20695524 248 }
domkay97 21:99ec20695524 249 void Controller::l_isr()
domkay97 21:99ec20695524 250 {
domkay97 21:99ec20695524 251 _event_state.set(L_PRESSED);
domkay97 21:99ec20695524 252 }
domkay97 21:99ec20695524 253 void Controller::r_isr()
domkay97 21:99ec20695524 254 {
domkay97 21:99ec20695524 255 _event_state.set(R_PRESSED);
domkay97 21:99ec20695524 256 }
domkay97 21:99ec20695524 257 void Controller::back_isr()
domkay97 21:99ec20695524 258 {
domkay97 21:99ec20695524 259 _event_state.set(BACK_PRESSED);
domkay97 21:99ec20695524 260 }
domkay97 21:99ec20695524 261 void Controller::start_isr()
domkay97 21:99ec20695524 262 {
domkay97 21:99ec20695524 263 _event_state.set(START_PRESSED);
domkay97 21:99ec20695524 264 }
domkay97 21:99ec20695524 265 void Controller::joy_isr()
domkay97 21:99ec20695524 266 {
domkay97 21:99ec20695524 267 _event_state.set(JOY_PRESSED);
domkay97 21:99ec20695524 268 }
domkay97 21:99ec20695524 269
domkay97 21:99ec20695524 270 // get raw joystick coordinate in range -1 to 1
domkay97 21:99ec20695524 271 // Direction (x,y)
domkay97 21:99ec20695524 272 // North (0,1)
domkay97 21:99ec20695524 273 // East (1,0)
domkay97 21:99ec20695524 274 // South (0,-1)
domkay97 21:99ec20695524 275 // West (-1,0)
domkay97 21:99ec20695524 276 Vector2D Controller::get_coord()
domkay97 21:99ec20695524 277 {
domkay97 21:99ec20695524 278 // read() returns value in range 0.0 to 1.0 so is scaled and centre value
domkay97 21:99ec20695524 279 // substracted to get values in the range -1.0 to 1.0
domkay97 21:99ec20695524 280 float x = 2.0f*( _horiz->read() - _x0 );
domkay97 21:99ec20695524 281 float y = 2.0f*( _vert->read() - _y0 );
domkay97 21:99ec20695524 282
domkay97 21:99ec20695524 283 // Note: the x value here is inverted to ensure the positive x is to the
domkay97 21:99ec20695524 284 // right. This is simply due to how the potentiometer on the joystick
domkay97 21:99ec20695524 285 // I was using was connected up. It could have been corrected in hardware
domkay97 21:99ec20695524 286 // by swapping the power supply pins. Instead it is done in software so may
domkay97 21:99ec20695524 287 // need to be changed depending on your wiring setup
domkay97 21:99ec20695524 288
domkay97 21:99ec20695524 289 Vector2D coord = {-x,y};
domkay97 21:99ec20695524 290 return coord;
domkay97 21:99ec20695524 291 }
domkay97 21:99ec20695524 292
domkay97 21:99ec20695524 293 // This maps the raw x,y coord onto a circular grid.
domkay97 21:99ec20695524 294 // See: http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html
domkay97 21:99ec20695524 295 Vector2D Controller::get_mapped_coord()
domkay97 21:99ec20695524 296 {
domkay97 21:99ec20695524 297 Vector2D coord = get_coord();
domkay97 21:99ec20695524 298
domkay97 21:99ec20695524 299 // do the transformation
domkay97 21:99ec20695524 300 float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f);
domkay97 21:99ec20695524 301 float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f);
domkay97 21:99ec20695524 302
domkay97 21:99ec20695524 303 Vector2D mapped_coord = {x,y};
domkay97 21:99ec20695524 304 return mapped_coord;
domkay97 21:99ec20695524 305 }
domkay97 21:99ec20695524 306
domkay97 21:99ec20695524 307 // this function converts the mapped coordinates into polar form
domkay97 21:99ec20695524 308 Polar Controller::get_polar()
domkay97 21:99ec20695524 309 {
domkay97 21:99ec20695524 310 // get the mapped coordinate
domkay97 21:99ec20695524 311 Vector2D coord = get_mapped_coord();
domkay97 21:99ec20695524 312
domkay97 21:99ec20695524 313 // at this point, 0 degrees (i.e. x-axis) will be defined to the East.
domkay97 21:99ec20695524 314 // We want 0 degrees to correspond to North and increase clockwise to 359
domkay97 21:99ec20695524 315 // like a compass heading, so we need to swap the axis and invert y
domkay97 21:99ec20695524 316 float x = coord.y;
domkay97 21:99ec20695524 317 float y = coord.x;
domkay97 21:99ec20695524 318
domkay97 21:99ec20695524 319 float mag = sqrt(x*x+y*y); // pythagoras
domkay97 21:99ec20695524 320 float angle = RAD2DEG*atan2(y,x);
domkay97 21:99ec20695524 321 // angle will be in range -180 to 180, so add 360 to negative angles to
domkay97 21:99ec20695524 322 // move to 0 to 360 range
domkay97 21:99ec20695524 323 if (angle < 0.0f) {
domkay97 21:99ec20695524 324 angle+=360.0f;
domkay97 21:99ec20695524 325 }
domkay97 21:99ec20695524 326
domkay97 21:99ec20695524 327 // the noise on the ADC causes the values of x and y to fluctuate slightly
domkay97 21:99ec20695524 328 // around the centred values. This causes the random angle values to get
domkay97 21:99ec20695524 329 // calculated when the joystick is centred and untouched. This is also when
domkay97 21:99ec20695524 330 // the magnitude is very small, so we can check for a small magnitude and then
domkay97 21:99ec20695524 331 // set the angle to -1. This will inform us when the angle is invalid and the
domkay97 21:99ec20695524 332 // joystick is centred
domkay97 21:99ec20695524 333
domkay97 21:99ec20695524 334 if (mag < TOL) {
domkay97 21:99ec20695524 335 mag = 0.0f;
domkay97 21:99ec20695524 336 angle = -1.0f;
domkay97 21:99ec20695524 337 }
domkay97 21:99ec20695524 338
domkay97 21:99ec20695524 339 Polar p = {mag,angle};
domkay97 21:99ec20695524 340 return p;
domkay97 21:99ec20695524 341 }
domkay97 21:99ec20695524 342 int Controller::check_for_buttons() {
domkay97 21:99ec20695524 343 if (check_event(A_PRESSED)) {
domkay97 21:99ec20695524 344 return 1; }
domkay97 21:99ec20695524 345 else if (check_event(B_PRESSED)) {
domkay97 21:99ec20695524 346 return 2; }
domkay97 21:99ec20695524 347 else if (check_event(X_PRESSED)) {
domkay97 21:99ec20695524 348 return 3; }
domkay97 21:99ec20695524 349 else if (check_event(Y_PRESSED)) {
domkay97 21:99ec20695524 350 return 4; }
domkay97 21:99ec20695524 351 else {
domkay97 21:99ec20695524 352 return 0; }
domkay97 21:99ec20695524 353 }