Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Gamepad.cpp
00001 #include "Gamepad.h" 00002 00003 #include "mbed.h" 00004 00005 //////////// constructor/destructor //////////// 00006 Gamepad::Gamepad() 00007 : 00008 _led1(new PwmOut(PTA1)), 00009 _led2(new PwmOut(PTA2)), 00010 _led3(new PwmOut(PTC2)), 00011 _led4(new PwmOut(PTC3)), 00012 _led5(new PwmOut(PTC4)), 00013 _led6(new PwmOut(PTD3)), 00014 00015 _button_A(new InterruptIn(PTB9)), 00016 _button_B(new InterruptIn(PTD0)), 00017 _button_X(new InterruptIn(PTC17)), 00018 _button_Y(new InterruptIn(PTC12)), 00019 _button_L(new InterruptIn(PTB18)), 00020 _button_R(new InterruptIn(PTB3)), 00021 _button_back(new InterruptIn(PTB19)), 00022 _button_start(new InterruptIn(PTC5)), 00023 _button_joystick(new InterruptIn(PTC16)), 00024 00025 _vert(new AnalogIn(PTB10)), 00026 _horiz(new AnalogIn(PTB11)), 00027 00028 _buzzer(new PwmOut(PTC10)), 00029 _pot(new AnalogIn(PTB2)), 00030 00031 _timeout(new Timeout()), 00032 00033 _event_state(0), 00034 00035 _x0(0), 00036 _y0(0) 00037 {} 00038 00039 Gamepad::~Gamepad() 00040 { 00041 delete _led1,_led2,_led3,_led4,_led5,_led6; 00042 delete _button_A,_button_B,_button_joystick,_vert,_horiz; 00043 delete _button_X,_button_Y,_button_back,_button_start; 00044 delete _button_L,_button_R, _buzzer, _pot, _timeout; 00045 } 00046 00047 ///////////////// public methods ///////////////// 00048 00049 void Gamepad::init() 00050 { 00051 leds_off(); 00052 init_buttons(); 00053 00054 // read centred values of joystick 00055 _x0 = _horiz->read(); 00056 _y0 = _vert->read(); 00057 00058 // clear all flags 00059 _event_state = 0; 00060 } 00061 00062 void Gamepad::leds_off() 00063 { 00064 leds(0.0); 00065 } 00066 00067 void Gamepad::leds_on() 00068 { 00069 leds(1.0); 00070 } 00071 00072 void Gamepad::leds(float val) const 00073 { 00074 if (val < 0.0f) { 00075 val = 0.0f; 00076 } 00077 if (val > 1.0f) { 00078 val = 1.0f; 00079 } 00080 00081 // leds are active-low, so subtract from 1.0 00082 // 0.0 corresponds to fully-off, 1.0 to fully-on 00083 val = 1.0f - val; 00084 00085 _led1->write(val); 00086 _led2->write(val); 00087 _led3->write(val); 00088 _led4->write(val); 00089 _led5->write(val); 00090 _led6->write(val); 00091 } 00092 00093 void Gamepad::led(int n,float val) const 00094 { 00095 // ensure they are within vlaid range 00096 if (val < 0.0f) { 00097 val = 0.0f; 00098 } 00099 if (val > 1.0f) { 00100 val = 1.0f; 00101 } 00102 00103 switch (n) { 00104 00105 // check for valid LED number and set value 00106 00107 case 1: 00108 _led1->write(1.0f-val); // active-low so subtract from 1 00109 break; 00110 case 2: 00111 _led2->write(1.0f-val); // active-low so subtract from 1 00112 break; 00113 case 3: 00114 _led3->write(1.0f-val); // active-low so subtract from 1 00115 break; 00116 case 4: 00117 _led4->write(1.0f-val); // active-low so subtract from 1 00118 break; 00119 case 5: 00120 _led5->write(1.0f-val); // active-low so subtract from 1 00121 break; 00122 case 6: 00123 _led6->write(1.0f-val); // active-low so subtract from 1 00124 break; 00125 00126 } 00127 } 00128 00129 float Gamepad::read_pot() const 00130 { 00131 return _pot->read(); 00132 } 00133 00134 void Gamepad::tone(float frequency, float duration) 00135 { 00136 _buzzer->period(1.0f/frequency); 00137 _buzzer->write(0.5); // 50% duty cycle - square wave 00138 _timeout->attach(callback(this, &Gamepad::tone_off), duration ); 00139 } 00140 00141 bool Gamepad::check_event(GamepadEvent const id) 00142 { 00143 // Check whether event flag is set 00144 if (_event_state[id]) { 00145 _event_state.reset(id); // clear flag 00146 return true; 00147 } else { 00148 return false; 00149 } 00150 } 00151 00152 void Gamepad::reset_flags() 00153 { 00154 // reset all button flags 00155 _event_state.reset(A_PRESSED); 00156 _event_state.reset(B_PRESSED); 00157 _event_state.reset(X_PRESSED); 00158 _event_state.reset(Y_PRESSED); 00159 _event_state.reset(START_PRESSED); 00160 _event_state.reset(BACK_PRESSED); 00161 _event_state.reset(L_PRESSED); 00162 _event_state.reset(R_PRESSED); 00163 } 00164 00165 // this method gets the magnitude of the joystick movement 00166 float Gamepad::get_mag() 00167 { 00168 Polar p = get_polar(); 00169 return p.mag; 00170 } 00171 00172 // this method gets the angle of joystick movement (0 to 360, 0 North) 00173 float Gamepad::get_angle() 00174 { 00175 Polar p = get_polar(); 00176 return p.angle; 00177 } 00178 00179 Direction Gamepad::get_direction() 00180 { 00181 float angle = get_angle(); // 0 to 360, -1 for centred 00182 00183 Direction d; 00184 // partition 360 into segments and check which segment the angle is in 00185 if (angle < 0.0f) { 00186 d = CENTRE; // check for -1.0 angle 00187 } else if (angle < 22.5f) { // then keep going in 45 degree increments 00188 d = N; 00189 } else if (angle < 67.5f) { 00190 d = NE; 00191 } else if (angle < 112.5f) { 00192 d = E; 00193 } else if (angle < 157.5f) { 00194 d = SE; 00195 } else if (angle < 202.5f) { 00196 d = S; 00197 } else if (angle < 247.5f) { 00198 d = SW; 00199 } else if (angle < 292.5f) { 00200 d = W; 00201 } else if (angle < 337.5f) { 00202 d = NW; 00203 } else { 00204 d = N; 00205 } 00206 00207 return d; 00208 } 00209 00210 ///////////////////// private methods //////////////////////// 00211 00212 void Gamepad::tone_off() 00213 { 00214 // called after timeout 00215 _buzzer->write(0.0); 00216 } 00217 00218 void Gamepad::init_buttons() 00219 { 00220 // turn on pull-downs as other side of button is connected to 3V3 00221 // button is 0 when not pressed and 1 when pressed 00222 _button_A->mode(PullDown); 00223 _button_B->mode(PullDown); 00224 _button_X->mode(PullDown); 00225 _button_Y->mode(PullDown); 00226 _button_back->mode(PullDown); 00227 _button_start->mode(PullDown); 00228 _button_L->mode(PullDown); 00229 _button_R->mode(PullDown); 00230 _button_joystick->mode(PullDown); 00231 // therefore setup rising edge interrupts 00232 _button_A->rise(callback(this,&Gamepad::a_isr)); 00233 _button_B->rise(callback(this,&Gamepad::b_isr)); 00234 _button_X->rise(callback(this,&Gamepad::x_isr)); 00235 _button_Y->rise(callback(this,&Gamepad::y_isr)); 00236 _button_L->rise(callback(this,&Gamepad::l_isr)); 00237 _button_R->rise(callback(this,&Gamepad::r_isr)); 00238 _button_start->rise(callback(this,&Gamepad::start_isr)); 00239 _button_back->rise(callback(this,&Gamepad::back_isr)); 00240 _button_joystick->rise(callback(this,&Gamepad::joy_isr)); 00241 } 00242 00243 // button interrupts ISRs 00244 // Each of these simply sets the appropriate event bit in the _event_state 00245 // variable 00246 void Gamepad::a_isr() 00247 { 00248 _event_state.set(A_PRESSED); 00249 } 00250 void Gamepad::b_isr() 00251 { 00252 _event_state.set(B_PRESSED); 00253 } 00254 void Gamepad::x_isr() 00255 { 00256 _event_state.set(X_PRESSED); 00257 } 00258 void Gamepad::y_isr() 00259 { 00260 _event_state.set(Y_PRESSED); 00261 } 00262 void Gamepad::l_isr() 00263 { 00264 _event_state.set(L_PRESSED); 00265 } 00266 void Gamepad::r_isr() 00267 { 00268 _event_state.set(R_PRESSED); 00269 } 00270 void Gamepad::back_isr() 00271 { 00272 _event_state.set(BACK_PRESSED); 00273 } 00274 void Gamepad::start_isr() 00275 { 00276 _event_state.set(START_PRESSED); 00277 } 00278 void Gamepad::joy_isr() 00279 { 00280 _event_state.set(JOY_PRESSED); 00281 } 00282 00283 // get raw joystick coordinate in range -1 to 1 00284 // Direction (x,y) 00285 // North (0,1) 00286 // East (1,0) 00287 // South (0,-1) 00288 // West (-1,0) 00289 Vector2D Gamepad::get_coord() 00290 { 00291 // read() returns value in range 0.0 to 1.0 so is scaled and centre value 00292 // substracted to get values in the range -1.0 to 1.0 00293 float x = 2.0f*( _horiz->read() - _x0 ); 00294 float y = 2.0f*( _vert->read() - _y0 ); 00295 00296 // Note: the x value here is inverted to ensure the positive x is to the 00297 // right. This is simply due to how the potentiometer on the joystick 00298 // I was using was connected up. It could have been corrected in hardware 00299 // by swapping the power supply pins. Instead it is done in software so may 00300 // need to be changed depending on your wiring setup 00301 00302 Vector2D coord = {-x,y}; 00303 return coord; 00304 } 00305 00306 // This maps the raw x,y coord onto a circular grid. 00307 // See: http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html 00308 Vector2D Gamepad::get_mapped_coord() 00309 { 00310 Vector2D coord = get_coord(); 00311 00312 // do the transformation 00313 float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f); 00314 float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f); 00315 00316 Vector2D mapped_coord = {x,y}; 00317 return mapped_coord; 00318 } 00319 00320 // this function converts the mapped coordinates into polar form 00321 Polar Gamepad::get_polar() 00322 { 00323 // get the mapped coordinate 00324 Vector2D coord = get_mapped_coord(); 00325 00326 // at this point, 0 degrees (i.e. x-axis) will be defined to the East. 00327 // We want 0 degrees to correspond to North and increase clockwise to 359 00328 // like a compass heading, so we need to swap the axis and invert y 00329 float x = coord.y; 00330 float y = coord.x; 00331 00332 float mag = sqrt(x*x+y*y); // pythagoras 00333 float angle = RAD2DEG*atan2(y,x); 00334 // angle will be in range -180 to 180, so add 360 to negative angles to 00335 // move to 0 to 360 range 00336 if (angle < 0.0f) { 00337 angle+=360.0f; 00338 } 00339 00340 // the noise on the ADC causes the values of x and y to fluctuate slightly 00341 // around the centred values. This causes the random angle values to get 00342 // calculated when the joystick is centred and untouched. This is also when 00343 // the magnitude is very small, so we can check for a small magnitude and then 00344 // set the angle to -1. This will inform us when the angle is invalid and the 00345 // joystick is centred 00346 00347 if (mag < TOL) { 00348 mag = 0.0f; 00349 angle = -1.0f; 00350 } 00351 00352 Polar p = {mag,angle}; 00353 return p; 00354 }
Generated on Wed Jul 13 2022 09:05:52 by
1.7.2