Library for communicating with a Wii classic controller using the I2C bus.
Dependents: WiiClassicControllerTest
Note that you will also need the CommonTypes library to use this.
Get it here:http://mbed.org/users/RichardE/code/CommonTypes/
WiiClassicControllerWithCalibration.cpp@4:79d04d737f02, 2013-06-30 (annotated)
- Committer:
- RichardE
- Date:
- Sun Jun 30 16:45:24 2013 +0000
- Revision:
- 4:79d04d737f02
- Parent:
- 3:ecae3d286a99
Slight documentation fix.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RichardE | 2:52c4a0b3a509 | 1 | /* |
RichardE | 2:52c4a0b3a509 | 2 | * SOURCE FILE : WiiClassicControllerWithCalibration.cpp |
RichardE | 2:52c4a0b3a509 | 3 | * |
RichardE | 2:52c4a0b3a509 | 4 | * Definition of class WiiClassicControllerWithCalibration. |
RichardE | 2:52c4a0b3a509 | 5 | * |
RichardE | 2:52c4a0b3a509 | 6 | */ |
RichardE | 2:52c4a0b3a509 | 7 | |
RichardE | 2:52c4a0b3a509 | 8 | #include "WiiClassicControllerWithCalibration.h" |
RichardE | 2:52c4a0b3a509 | 9 | |
RichardE | 2:52c4a0b3a509 | 10 | /** Constructor |
RichardE | 2:52c4a0b3a509 | 11 | * @param sda pin to use for SDA. |
RichardE | 2:52c4a0b3a509 | 12 | * @param scl pin to use for SCL. |
RichardE | 2:52c4a0b3a509 | 13 | */ |
RichardE | 2:52c4a0b3a509 | 14 | WiiClassicControllerWithCalibration::WiiClassicControllerWithCalibration( PinName sda, PinName scl ) : |
RichardE | 3:ecae3d286a99 | 15 | WiiClassicController( sda, scl ), |
RichardE | 3:ecae3d286a99 | 16 | calibrating( false ) |
RichardE | 2:52c4a0b3a509 | 17 | { |
RichardE | 2:52c4a0b3a509 | 18 | // Set default scaling factors. |
RichardE | 2:52c4a0b3a509 | 19 | // Left joystick is 6 bit reading. Raw reading of 0 gives -1. Raw reading of 63 gives +1. |
RichardE | 2:52c4a0b3a509 | 20 | SetScaling( LeftJoyX, (float)( 2.0 / 63.0 ), -1 ); |
RichardE | 2:52c4a0b3a509 | 21 | SetScaling( LeftJoyY, (float)( 2.0 / 63.0 ), -1 ); |
RichardE | 2:52c4a0b3a509 | 22 | // Right joystick is 5 bit reading. Raw reading of 0 gives -1. Raw reading of 31 gives +1. |
RichardE | 2:52c4a0b3a509 | 23 | SetScaling( RightJoyX, (float)( 2.0 / 31.0 ), -1 ); |
RichardE | 2:52c4a0b3a509 | 24 | SetScaling( RightJoyY, (float)( 2.0 / 31.0 ), -1 ); |
RichardE | 2:52c4a0b3a509 | 25 | // Left trigger is 5 bit reading. Raw reading of 0 gives 0. Raw reading of 31 gives +1. |
RichardE | 2:52c4a0b3a509 | 26 | SetScaling( LeftTrigger, (float)( 1.0 / 31.0 ), 0 ); |
RichardE | 2:52c4a0b3a509 | 27 | // Right trigger is 5 bit reading. Raw reading of 0 gives 0. Raw reading of 31 gives +1. |
RichardE | 2:52c4a0b3a509 | 28 | SetScaling( RightTrigger, (float)( 1.0 / 31.0 ), 0 ); |
RichardE | 2:52c4a0b3a509 | 29 | } |
RichardE | 2:52c4a0b3a509 | 30 | |
RichardE | 2:52c4a0b3a509 | 31 | /** Destructor |
RichardE | 2:52c4a0b3a509 | 32 | */ |
RichardE | 2:52c4a0b3a509 | 33 | WiiClassicControllerWithCalibration::~WiiClassicControllerWithCalibration() { |
RichardE | 2:52c4a0b3a509 | 34 | } |
RichardE | 2:52c4a0b3a509 | 35 | |
RichardE | 2:52c4a0b3a509 | 36 | /** Set scaling for a particular analogue input. |
RichardE | 4:79d04d737f02 | 37 | * @param input channel to change. |
RichardE | 2:52c4a0b3a509 | 38 | * @param m scale (multiplier) for this analogue input. |
RichardE | 2:52c4a0b3a509 | 39 | * @param c offset for this analogue input. |
RichardE | 2:52c4a0b3a509 | 40 | */ |
RichardE | 2:52c4a0b3a509 | 41 | void WiiClassicControllerWithCalibration::SetScaling( AnaIn input, float m, float c ) { |
RichardE | 2:52c4a0b3a509 | 42 | if( ( (int)input >= 0 ) && ( (int)input < (int)AnaInCount ) ) { |
RichardE | 2:52c4a0b3a509 | 43 | AnaInRec *ptr = records + (int)input; |
RichardE | 2:52c4a0b3a509 | 44 | ptr->Scale = m; |
RichardE | 2:52c4a0b3a509 | 45 | ptr->Offset = c; |
RichardE | 2:52c4a0b3a509 | 46 | } |
RichardE | 2:52c4a0b3a509 | 47 | } |
RichardE | 2:52c4a0b3a509 | 48 | |
RichardE | 3:ecae3d286a99 | 49 | /** Get scaling for a particular analogue input. |
RichardE | 3:ecae3d286a99 | 50 | * @param input channel to read. |
RichardE | 3:ecae3d286a99 | 51 | * @param m scale (multiplier) for this analogue input return here. |
RichardE | 3:ecae3d286a99 | 52 | * @param c offset for this analogue input returned here. |
RichardE | 3:ecae3d286a99 | 53 | */ |
RichardE | 3:ecae3d286a99 | 54 | void WiiClassicControllerWithCalibration::GetScaling( AnaIn input, float *m, float *c ) const { |
RichardE | 3:ecae3d286a99 | 55 | if( ( (int)input >= 0 ) && ( (int)input < (int)AnaInCount ) ) { |
RichardE | 3:ecae3d286a99 | 56 | const AnaInRec *ptr = records + (int)input; |
RichardE | 3:ecae3d286a99 | 57 | *m = ptr->Scale; |
RichardE | 3:ecae3d286a99 | 58 | *c = ptr->Offset; |
RichardE | 3:ecae3d286a99 | 59 | } |
RichardE | 3:ecae3d286a99 | 60 | } |
RichardE | 3:ecae3d286a99 | 61 | |
RichardE | 3:ecae3d286a99 | 62 | /** Read from the controller. |
RichardE | 3:ecae3d286a99 | 63 | * This override will also update calibration information |
RichardE | 3:ecae3d286a99 | 64 | * when calibration is in progress. |
RichardE | 3:ecae3d286a99 | 65 | * @returns true on success, false on failure. |
RichardE | 3:ecae3d286a99 | 66 | */ |
RichardE | 3:ecae3d286a99 | 67 | bool WiiClassicControllerWithCalibration::Read( void ) { |
RichardE | 3:ecae3d286a99 | 68 | // Call base class method to do the actual reading. |
RichardE | 3:ecae3d286a99 | 69 | if( WiiClassicController::Read() ) { |
RichardE | 3:ecae3d286a99 | 70 | // That worked so update calibration information if |
RichardE | 3:ecae3d286a99 | 71 | // calibration is in progress. |
RichardE | 3:ecae3d286a99 | 72 | if( calibrating ) { |
RichardE | 3:ecae3d286a99 | 73 | UpdateCalibration(); |
RichardE | 3:ecae3d286a99 | 74 | } |
RichardE | 3:ecae3d286a99 | 75 | return true; |
RichardE | 3:ecae3d286a99 | 76 | } |
RichardE | 3:ecae3d286a99 | 77 | else { |
RichardE | 3:ecae3d286a99 | 78 | return false; |
RichardE | 3:ecae3d286a99 | 79 | } |
RichardE | 3:ecae3d286a99 | 80 | } |
RichardE | 3:ecae3d286a99 | 81 | |
RichardE | 2:52c4a0b3a509 | 82 | /** Get calibrated left joystick X reading. |
RichardE | 2:52c4a0b3a509 | 83 | * @returns a reading between -1 and +1. |
RichardE | 2:52c4a0b3a509 | 84 | */ |
RichardE | 2:52c4a0b3a509 | 85 | float WiiClassicControllerWithCalibration::GetCalLJoyX( void ) const { |
RichardE | 3:ecae3d286a99 | 86 | return GetScaled( LeftJoyX, GetLJoyX(), -1, 1 ); |
RichardE | 2:52c4a0b3a509 | 87 | } |
RichardE | 2:52c4a0b3a509 | 88 | |
RichardE | 2:52c4a0b3a509 | 89 | /** Get calibrated left joystick Y reading. |
RichardE | 2:52c4a0b3a509 | 90 | * @returns a reading between -1 and +1. |
RichardE | 2:52c4a0b3a509 | 91 | */ |
RichardE | 2:52c4a0b3a509 | 92 | float WiiClassicControllerWithCalibration::GetCalLJoyY( void ) const { |
RichardE | 3:ecae3d286a99 | 93 | return GetScaled( LeftJoyY, GetLJoyY(), -1, 1 ); |
RichardE | 2:52c4a0b3a509 | 94 | } |
RichardE | 2:52c4a0b3a509 | 95 | |
RichardE | 2:52c4a0b3a509 | 96 | /** Get calibrated right joystick X reading. |
RichardE | 2:52c4a0b3a509 | 97 | * @returns a reading between -1 and +1. |
RichardE | 2:52c4a0b3a509 | 98 | */ |
RichardE | 2:52c4a0b3a509 | 99 | float WiiClassicControllerWithCalibration::GetCalRJoyX( void ) const { |
RichardE | 3:ecae3d286a99 | 100 | return GetScaled( RightJoyX, GetRJoyX(), -1, 1 ); |
RichardE | 2:52c4a0b3a509 | 101 | } |
RichardE | 2:52c4a0b3a509 | 102 | |
RichardE | 2:52c4a0b3a509 | 103 | /** Get calibrated right joystick Y reading. |
RichardE | 2:52c4a0b3a509 | 104 | * @returns a reading between -1 and +1. |
RichardE | 2:52c4a0b3a509 | 105 | */ |
RichardE | 2:52c4a0b3a509 | 106 | float WiiClassicControllerWithCalibration::GetCalRJoyY( void ) const { |
RichardE | 3:ecae3d286a99 | 107 | return GetScaled( RightJoyY, GetRJoyY(), -1, 1 ); |
RichardE | 2:52c4a0b3a509 | 108 | } |
RichardE | 2:52c4a0b3a509 | 109 | |
RichardE | 2:52c4a0b3a509 | 110 | /** Get calibrated left trigger reading. |
RichardE | 2:52c4a0b3a509 | 111 | * @returns a reading between 0 and +1. |
RichardE | 2:52c4a0b3a509 | 112 | */ |
RichardE | 2:52c4a0b3a509 | 113 | float WiiClassicControllerWithCalibration::GetCalLeftTrigger( void ) const { |
RichardE | 3:ecae3d286a99 | 114 | return GetScaled( LeftTrigger, GetLeftTrigger(), 0, 1 ); |
RichardE | 2:52c4a0b3a509 | 115 | } |
RichardE | 2:52c4a0b3a509 | 116 | |
RichardE | 2:52c4a0b3a509 | 117 | /** Get calibrated right trigger reading. |
RichardE | 2:52c4a0b3a509 | 118 | * @returns a reading between 0 and +1. |
RichardE | 2:52c4a0b3a509 | 119 | */ |
RichardE | 2:52c4a0b3a509 | 120 | float WiiClassicControllerWithCalibration::GetCalRightTrigger( void ) const { |
RichardE | 3:ecae3d286a99 | 121 | return GetScaled( RightTrigger, GetRightTrigger(), 0, 1 ); |
RichardE | 2:52c4a0b3a509 | 122 | } |
RichardE | 2:52c4a0b3a509 | 123 | |
RichardE | 2:52c4a0b3a509 | 124 | /** Get scaled reading. |
RichardE | 2:52c4a0b3a509 | 125 | * @param input analogue input to scale. |
RichardE | 2:52c4a0b3a509 | 126 | * @param raw raw readings in counts. |
RichardE | 3:ecae3d286a99 | 127 | * @param min minimum permitted value. |
RichardE | 3:ecae3d286a99 | 128 | * @param max maximum permited value. |
RichardE | 2:52c4a0b3a509 | 129 | * @returns scaled reading. |
RichardE | 2:52c4a0b3a509 | 130 | */ |
RichardE | 3:ecae3d286a99 | 131 | float WiiClassicControllerWithCalibration::GetScaled( AnaIn input, UInt8 raw, float min, float max ) const { |
RichardE | 2:52c4a0b3a509 | 132 | if( ( (int)input >= 0 ) && ( (int)input < (int)AnaInCount ) ) { |
RichardE | 2:52c4a0b3a509 | 133 | const AnaInRec *ptr = records + (int)input; |
RichardE | 3:ecae3d286a99 | 134 | float y = (float)raw * ptr->Scale + ptr->Offset; |
RichardE | 3:ecae3d286a99 | 135 | if( y < min ) { |
RichardE | 3:ecae3d286a99 | 136 | y = min; |
RichardE | 3:ecae3d286a99 | 137 | } |
RichardE | 3:ecae3d286a99 | 138 | else if( y > max ) { |
RichardE | 3:ecae3d286a99 | 139 | y = max; |
RichardE | 3:ecae3d286a99 | 140 | } |
RichardE | 3:ecae3d286a99 | 141 | return y; |
RichardE | 2:52c4a0b3a509 | 142 | } |
RichardE | 2:52c4a0b3a509 | 143 | else { |
RichardE | 2:52c4a0b3a509 | 144 | return (float)0; |
RichardE | 2:52c4a0b3a509 | 145 | } |
RichardE | 2:52c4a0b3a509 | 146 | } |
RichardE | 3:ecae3d286a99 | 147 | |
RichardE | 3:ecae3d286a99 | 148 | /** Start calibrating. |
RichardE | 3:ecae3d286a99 | 149 | * Every call to Read method updates calibration until StopCalibrating is called. |
RichardE | 3:ecae3d286a99 | 150 | */ |
RichardE | 3:ecae3d286a99 | 151 | void WiiClassicControllerWithCalibration::StartCalibrating( void ) { |
RichardE | 3:ecae3d286a99 | 152 | if( ! calibrating ) { |
RichardE | 3:ecae3d286a99 | 153 | // Initialise all records so that the minimum count is very large, |
RichardE | 3:ecae3d286a99 | 154 | // the maximum count is very small and the zero count is whatever |
RichardE | 3:ecae3d286a99 | 155 | // the joystick is reading right now. |
RichardE | 3:ecae3d286a99 | 156 | AnaInRec *rec; |
RichardE | 3:ecae3d286a99 | 157 | for( int i = 0; i < (int)AnaInCount; ++i ) { |
RichardE | 3:ecae3d286a99 | 158 | rec = records + i; |
RichardE | 3:ecae3d286a99 | 159 | rec->MinCount = 255; |
RichardE | 3:ecae3d286a99 | 160 | rec->MaxCount = 0; |
RichardE | 3:ecae3d286a99 | 161 | rec->ZeroCount = GetAnaIn( (AnaIn)i ); |
RichardE | 3:ecae3d286a99 | 162 | } |
RichardE | 3:ecae3d286a99 | 163 | calibrating = true; |
RichardE | 3:ecae3d286a99 | 164 | } |
RichardE | 3:ecae3d286a99 | 165 | } |
RichardE | 3:ecae3d286a99 | 166 | |
RichardE | 3:ecae3d286a99 | 167 | /** Get the raw counts for one of the analogue inputs. |
RichardE | 3:ecae3d286a99 | 168 | * @param input analogue input to read. |
RichardE | 3:ecae3d286a99 | 169 | * @returns raw counts for input. |
RichardE | 3:ecae3d286a99 | 170 | */ |
RichardE | 3:ecae3d286a99 | 171 | UInt8 WiiClassicControllerWithCalibration::GetAnaIn( AnaIn input ) const { |
RichardE | 3:ecae3d286a99 | 172 | switch( input ) { |
RichardE | 3:ecae3d286a99 | 173 | case LeftJoyX : |
RichardE | 3:ecae3d286a99 | 174 | return GetLJoyX(); |
RichardE | 3:ecae3d286a99 | 175 | case LeftJoyY : |
RichardE | 3:ecae3d286a99 | 176 | return GetLJoyY(); |
RichardE | 3:ecae3d286a99 | 177 | case RightJoyX : |
RichardE | 3:ecae3d286a99 | 178 | return GetRJoyX(); |
RichardE | 3:ecae3d286a99 | 179 | case RightJoyY : |
RichardE | 3:ecae3d286a99 | 180 | return GetRJoyY(); |
RichardE | 3:ecae3d286a99 | 181 | case LeftTrigger : |
RichardE | 3:ecae3d286a99 | 182 | return GetLeftTrigger(); |
RichardE | 3:ecae3d286a99 | 183 | case RightTrigger : |
RichardE | 3:ecae3d286a99 | 184 | return GetRightTrigger(); |
RichardE | 3:ecae3d286a99 | 185 | default : |
RichardE | 3:ecae3d286a99 | 186 | return 0; |
RichardE | 3:ecae3d286a99 | 187 | } |
RichardE | 3:ecae3d286a99 | 188 | } |
RichardE | 3:ecae3d286a99 | 189 | |
RichardE | 3:ecae3d286a99 | 190 | /** Stop calibrating. |
RichardE | 3:ecae3d286a99 | 191 | */ |
RichardE | 3:ecae3d286a99 | 192 | void WiiClassicControllerWithCalibration::StopCalibrating( void ) { |
RichardE | 3:ecae3d286a99 | 193 | if( calibrating ) { |
RichardE | 3:ecae3d286a99 | 194 | AnaInRec *rec; |
RichardE | 3:ecae3d286a99 | 195 | for( int i = 0; i < (int)AnaInCount; ++i ) { |
RichardE | 3:ecae3d286a99 | 196 | rec = records + i; |
RichardE | 3:ecae3d286a99 | 197 | switch( (AnaIn)i ) { |
RichardE | 3:ecae3d286a99 | 198 | case LeftJoyX : |
RichardE | 3:ecae3d286a99 | 199 | case LeftJoyY : |
RichardE | 3:ecae3d286a99 | 200 | case RightJoyX : |
RichardE | 3:ecae3d286a99 | 201 | case RightJoyY : |
RichardE | 3:ecae3d286a99 | 202 | rec->CalculateScaleAndOffsetBiPolar( -1, 1 ); |
RichardE | 3:ecae3d286a99 | 203 | break; |
RichardE | 3:ecae3d286a99 | 204 | case LeftTrigger : |
RichardE | 3:ecae3d286a99 | 205 | case RightTrigger : |
RichardE | 3:ecae3d286a99 | 206 | rec->CalculateScaleAndOffsetUniPolar( 1 ); |
RichardE | 3:ecae3d286a99 | 207 | break; |
RichardE | 3:ecae3d286a99 | 208 | } |
RichardE | 3:ecae3d286a99 | 209 | } |
RichardE | 3:ecae3d286a99 | 210 | calibrating = false; |
RichardE | 3:ecae3d286a99 | 211 | } |
RichardE | 3:ecae3d286a99 | 212 | } |
RichardE | 3:ecae3d286a99 | 213 | |
RichardE | 3:ecae3d286a99 | 214 | |
RichardE | 3:ecae3d286a99 | 215 | /** Update calibration information. |
RichardE | 3:ecae3d286a99 | 216 | */ |
RichardE | 3:ecae3d286a99 | 217 | void WiiClassicControllerWithCalibration::UpdateCalibration( void ) { |
RichardE | 3:ecae3d286a99 | 218 | AnaInRec *rec; |
RichardE | 3:ecae3d286a99 | 219 | UInt8 count; |
RichardE | 3:ecae3d286a99 | 220 | for( int i = 0; i < (int)AnaInCount; ++i ) { |
RichardE | 3:ecae3d286a99 | 221 | count = GetAnaIn( (AnaIn)i ); |
RichardE | 3:ecae3d286a99 | 222 | rec = records + i; |
RichardE | 3:ecae3d286a99 | 223 | if( count < rec->MinCount ) { |
RichardE | 3:ecae3d286a99 | 224 | rec->MinCount = count; |
RichardE | 3:ecae3d286a99 | 225 | } |
RichardE | 3:ecae3d286a99 | 226 | if( count > rec->MaxCount ) { |
RichardE | 3:ecae3d286a99 | 227 | rec->MaxCount = count; |
RichardE | 3:ecae3d286a99 | 228 | } |
RichardE | 3:ecae3d286a99 | 229 | } |
RichardE | 3:ecae3d286a99 | 230 | } |
RichardE | 3:ecae3d286a99 | 231 | |
RichardE | 3:ecae3d286a99 | 232 | /** Calculate scale and offset for a bipolar reading. |
RichardE | 3:ecae3d286a99 | 233 | * @param minValue minimum value to read. |
RichardE | 3:ecae3d286a99 | 234 | * @param maxValue maximum value to read. |
RichardE | 3:ecae3d286a99 | 235 | */ |
RichardE | 3:ecae3d286a99 | 236 | void WiiClassicControllerWithCalibration::AnaInRec::CalculateScaleAndOffsetBiPolar( float minValue, float maxValue ) { |
RichardE | 3:ecae3d286a99 | 237 | UInt8 a; |
RichardE | 3:ecae3d286a99 | 238 | float b; |
RichardE | 3:ecae3d286a99 | 239 | if( ( ZeroCount - MinCount ) < ( MaxCount - ZeroCount ) ) { |
RichardE | 3:ecae3d286a99 | 240 | a = MinCount; |
RichardE | 3:ecae3d286a99 | 241 | b = minValue; |
RichardE | 3:ecae3d286a99 | 242 | } |
RichardE | 3:ecae3d286a99 | 243 | else { |
RichardE | 3:ecae3d286a99 | 244 | a = MaxCount; |
RichardE | 3:ecae3d286a99 | 245 | b = maxValue; |
RichardE | 3:ecae3d286a99 | 246 | } |
RichardE | 3:ecae3d286a99 | 247 | // Prevent a division by zero, but still a nonsense result. |
RichardE | 3:ecae3d286a99 | 248 | if( a == ZeroCount ) { |
RichardE | 3:ecae3d286a99 | 249 | a++; |
RichardE | 3:ecae3d286a99 | 250 | } |
RichardE | 3:ecae3d286a99 | 251 | Scale = ( b - (float)0 ) / (float)( a - ZeroCount ); |
RichardE | 3:ecae3d286a99 | 252 | Offset = -Scale * (float)ZeroCount; |
RichardE | 3:ecae3d286a99 | 253 | } |
RichardE | 3:ecae3d286a99 | 254 | |
RichardE | 3:ecae3d286a99 | 255 | /** Calculate scale and offset for a unipolar reading. |
RichardE | 3:ecae3d286a99 | 256 | * Minimum value is assumed to be zero. |
RichardE | 3:ecae3d286a99 | 257 | * @param maxValue maximum value to read. |
RichardE | 3:ecae3d286a99 | 258 | */ |
RichardE | 3:ecae3d286a99 | 259 | void WiiClassicControllerWithCalibration::AnaInRec::CalculateScaleAndOffsetUniPolar( float maxValue ) { |
RichardE | 3:ecae3d286a99 | 260 | UInt8 a = MaxCount; |
RichardE | 3:ecae3d286a99 | 261 | float b = maxValue; |
RichardE | 3:ecae3d286a99 | 262 | // Prevent a division by zero, but still a nonsense result. |
RichardE | 3:ecae3d286a99 | 263 | if( a == MinCount ) { |
RichardE | 3:ecae3d286a99 | 264 | a++; |
RichardE | 3:ecae3d286a99 | 265 | } |
RichardE | 3:ecae3d286a99 | 266 | Scale = ( b - (float)0 ) / (float)( a - MinCount ); |
RichardE | 3:ecae3d286a99 | 267 | Offset = -Scale * (float)MinCount; |
RichardE | 3:ecae3d286a99 | 268 | } |
RichardE | 3:ecae3d286a99 | 269 |