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.
Dependencies: USBDevice mbed-rtos mbed
Fork of JoyStick by
main.cpp@2:ae7a31a3c618, 2013-08-30 (annotated)
- Committer:
- rvt
- Date:
- Fri Aug 30 01:37:49 2013 +0000
- Revision:
- 2:ae7a31a3c618
- Parent:
- 1:5b2ab44eb31f
- Child:
- 3:0742b0b42ac9
Better PushButton handling
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| rvt | 0:33bc88c4ab31 | 1 | #include "mbed.h" |
| rvt | 0:33bc88c4ab31 | 2 | #include "USBHID.h" |
| rvt | 0:33bc88c4ab31 | 3 | #include "USBJoystick.h" |
| rvt | 0:33bc88c4ab31 | 4 | #include "LowPassFilter.h" |
| rvt | 0:33bc88c4ab31 | 5 | #include "AnalogInFiltered.h" |
| rvt | 2:ae7a31a3c618 | 6 | #include "SimpleButtonDecoder.h" |
| rvt | 0:33bc88c4ab31 | 7 | #include "rtos.h" |
| rvt | 0:33bc88c4ab31 | 8 | |
| rvt | 1:5b2ab44eb31f | 9 | // When set, it will send debug data over USB serial |
| rvt | 0:33bc88c4ab31 | 10 | #define TTY_DEBUG |
| rvt | 0:33bc88c4ab31 | 11 | |
| rvt | 0:33bc88c4ab31 | 12 | // Value that defines when to start sending data this prevents the noise sending loads's of data over HID |
| rvt | 0:33bc88c4ab31 | 13 | #define DATA_CHANGE_TRIGGER 64 |
| rvt | 0:33bc88c4ab31 | 14 | |
| rvt | 1:5b2ab44eb31f | 15 | // Activity LED for HID data |
| rvt | 1:5b2ab44eb31f | 16 | #define HIDACTIVITYLED LED3 |
| rvt | 0:33bc88c4ab31 | 17 | |
| rvt | 2:ae7a31a3c618 | 18 | // Number of samples taken before a buttons as set to be pressed. |
| rvt | 2:ae7a31a3c618 | 19 | // It essentually wait's untel the value is stable enough to be said to be pressed |
| rvt | 2:ae7a31a3c618 | 20 | #define DEBOUNCERUNS 10 |
| rvt | 2:ae7a31a3c618 | 21 | |
| rvt | 0:33bc88c4ab31 | 22 | |
| rvt | 0:33bc88c4ab31 | 23 | // Structure that hold's the dataset of the input's |
| rvt | 0:33bc88c4ab31 | 24 | Mutex analogValueMutex; |
| rvt | 0:33bc88c4ab31 | 25 | struct AnalogData { |
| rvt | 2:ae7a31a3c618 | 26 | bool button1; |
| rvt | 2:ae7a31a3c618 | 27 | bool button2; |
| rvt | 2:ae7a31a3c618 | 28 | bool button3; |
| rvt | 2:ae7a31a3c618 | 29 | bool button4; |
| rvt | 2:ae7a31a3c618 | 30 | bool button5; |
| rvt | 0:33bc88c4ab31 | 31 | long value1; |
| rvt | 0:33bc88c4ab31 | 32 | long value2; |
| rvt | 0:33bc88c4ab31 | 33 | long value3; |
| rvt | 0:33bc88c4ab31 | 34 | long value4; |
| rvt | 0:33bc88c4ab31 | 35 | long value5; |
| rvt | 0:33bc88c4ab31 | 36 | } analogData; |
| rvt | 0:33bc88c4ab31 | 37 | |
| rvt | 1:5b2ab44eb31f | 38 | #ifdef TTY_DEBUG |
| rvt | 1:5b2ab44eb31f | 39 | |
| rvt | 1:5b2ab44eb31f | 40 | |
| rvt | 1:5b2ab44eb31f | 41 | /** |
| rvt | 1:5b2ab44eb31f | 42 | Debug thread to show some values from the system over USB serial. |
| rvt | 1:5b2ab44eb31f | 43 | Ensure that TTY_DEBUG is defined so that these routines will get activated. |
| rvt | 1:5b2ab44eb31f | 44 | This is what I do to view the values on OSX within a terminal |
| rvt | 1:5b2ab44eb31f | 45 | $ cd /dev |
| rvt | 1:5b2ab44eb31f | 46 | $ ls | grep usbmodem |
| rvt | 1:5b2ab44eb31f | 47 | cu.usbmodemfa1232 |
| rvt | 1:5b2ab44eb31f | 48 | tty.usbmodemfa1232 |
| rvt | 1:5b2ab44eb31f | 49 | $ screen tty.usbmodemfa1232 |
| rvt | 1:5b2ab44eb31f | 50 | */ |
| rvt | 2:ae7a31a3c618 | 51 | const char *byte_to_binary16(int x) |
| rvt | 2:ae7a31a3c618 | 52 | { |
| rvt | 2:ae7a31a3c618 | 53 | static char b[17]; |
| rvt | 2:ae7a31a3c618 | 54 | b[0] = '\0'; |
| rvt | 2:ae7a31a3c618 | 55 | |
| rvt | 2:ae7a31a3c618 | 56 | int z; |
| rvt | 2:ae7a31a3c618 | 57 | for (z = 32768; z > 0; z >>= 1) |
| rvt | 2:ae7a31a3c618 | 58 | { |
| rvt | 2:ae7a31a3c618 | 59 | strcat(b, ((x & z) == z) ? "1" : "0"); |
| rvt | 2:ae7a31a3c618 | 60 | } |
| rvt | 2:ae7a31a3c618 | 61 | |
| rvt | 2:ae7a31a3c618 | 62 | return b; |
| rvt | 2:ae7a31a3c618 | 63 | } |
| rvt | 2:ae7a31a3c618 | 64 | const char *byte_to_binary8(int x) |
| rvt | 2:ae7a31a3c618 | 65 | { |
| rvt | 2:ae7a31a3c618 | 66 | static char b[9]; |
| rvt | 2:ae7a31a3c618 | 67 | b[0] = '\0'; |
| rvt | 2:ae7a31a3c618 | 68 | |
| rvt | 2:ae7a31a3c618 | 69 | int z; |
| rvt | 2:ae7a31a3c618 | 70 | for (z = 128; z > 0; z >>= 1) |
| rvt | 2:ae7a31a3c618 | 71 | { |
| rvt | 2:ae7a31a3c618 | 72 | strcat(b, ((x & z) == z) ? "1" : "0"); |
| rvt | 2:ae7a31a3c618 | 73 | } |
| rvt | 2:ae7a31a3c618 | 74 | |
| rvt | 2:ae7a31a3c618 | 75 | return b; |
| rvt | 2:ae7a31a3c618 | 76 | } |
| rvt | 2:ae7a31a3c618 | 77 | |
| rvt | 0:33bc88c4ab31 | 78 | void debug_thread(void const *args) |
| rvt | 0:33bc88c4ab31 | 79 | { |
| rvt | 2:ae7a31a3c618 | 80 | // Serial port for debug data |
| rvt | 2:ae7a31a3c618 | 81 | Serial pc(USBTX, USBRX); // tx, rx |
| rvt | 2:ae7a31a3c618 | 82 | |
| rvt | 1:5b2ab44eb31f | 83 | // Make a local copy |
| rvt | 1:5b2ab44eb31f | 84 | AnalogData localCopy; |
| rvt | 1:5b2ab44eb31f | 85 | AnalogData previous; |
| rvt | 0:33bc88c4ab31 | 86 | while (true) { |
| rvt | 1:5b2ab44eb31f | 87 | // Lock and copy input values |
| rvt | 0:33bc88c4ab31 | 88 | analogValueMutex.lock(); |
| rvt | 0:33bc88c4ab31 | 89 | memcpy (&localCopy, &analogData, sizeof(AnalogData)); |
| rvt | 0:33bc88c4ab31 | 90 | analogValueMutex.unlock(); |
| rvt | 0:33bc88c4ab31 | 91 | |
| rvt | 0:33bc88c4ab31 | 92 | // Send to USB |
| rvt | 0:33bc88c4ab31 | 93 | pc.printf("\x1B[0;0H"); |
| rvt | 0:33bc88c4ab31 | 94 | pc.printf("Yoke and Pedals!\n\r"); |
| rvt | 2:ae7a31a3c618 | 95 | pc.printf("Analog in p20: %s %d \n\r",byte_to_binary16((localCopy.value1 + 32768)),localCopy.value1 + 32768); |
| rvt | 0:33bc88c4ab31 | 96 | pc.printf("Analog in p19: %d diff: %d \n\r",localCopy.value2,localCopy.value2-previous.value2); |
| rvt | 0:33bc88c4ab31 | 97 | pc.printf("Analog in p18: %d diff: %d \n\r",localCopy.value3,localCopy.value3-previous.value3); |
| rvt | 0:33bc88c4ab31 | 98 | pc.printf("Analog in p17: %d diff: %d \n\r",localCopy.value4,localCopy.value4-previous.value4); |
| rvt | 0:33bc88c4ab31 | 99 | pc.printf("Analog in p16: %d diff: %d \n\r",localCopy.value5,localCopy.value5-previous.value5); |
| rvt | 2:ae7a31a3c618 | 100 | pc.printf("Button 1: %d \n\r",localCopy.button1); |
| rvt | 2:ae7a31a3c618 | 101 | pc.printf("Button 2: %d \n\r",localCopy.button2); |
| rvt | 2:ae7a31a3c618 | 102 | pc.printf("Button 3: %d \n\r",localCopy.button3); |
| rvt | 2:ae7a31a3c618 | 103 | pc.printf("Button 4: %d \n\r",localCopy.button4); |
| rvt | 2:ae7a31a3c618 | 104 | pc.printf("Button 5: %d \n\r",localCopy.button5); |
| rvt | 1:5b2ab44eb31f | 105 | |
| rvt | 1:5b2ab44eb31f | 106 | // Make local copy so we can show diff version |
| rvt | 0:33bc88c4ab31 | 107 | memcpy (&previous, &localCopy, sizeof(AnalogData)); |
| rvt | 0:33bc88c4ab31 | 108 | Thread::wait(1000); |
| rvt | 0:33bc88c4ab31 | 109 | } |
| rvt | 0:33bc88c4ab31 | 110 | } |
| rvt | 1:5b2ab44eb31f | 111 | #endif |
| rvt | 0:33bc88c4ab31 | 112 | |
| rvt | 2:ae7a31a3c618 | 113 | |
| rvt | 0:33bc88c4ab31 | 114 | void hid_thread(void const *args) |
| rvt | 0:33bc88c4ab31 | 115 | { |
| rvt | 1:5b2ab44eb31f | 116 | //USB HID JoyStick |
| rvt | 1:5b2ab44eb31f | 117 | USBJoystick joystick; |
| rvt | 1:5b2ab44eb31f | 118 | |
| rvt | 1:5b2ab44eb31f | 119 | // Activity led for HID data transmissions |
| rvt | 1:5b2ab44eb31f | 120 | DigitalOut hIDActivity(HIDACTIVITYLED); |
| rvt | 2:ae7a31a3c618 | 121 | |
| rvt | 2:ae7a31a3c618 | 122 | // Locla copy of analog data |
| rvt | 2:ae7a31a3c618 | 123 | AnalogData localCopy; |
| rvt | 1:5b2ab44eb31f | 124 | |
| rvt | 2:ae7a31a3c618 | 125 | uint8_t buttons=0; |
| rvt | 0:33bc88c4ab31 | 126 | while (true) { |
| rvt | 0:33bc88c4ab31 | 127 | |
| rvt | 0:33bc88c4ab31 | 128 | |
| rvt | 0:33bc88c4ab31 | 129 | // Wait for analog in to have some data |
| rvt | 1:5b2ab44eb31f | 130 | hIDActivity=false; |
| rvt | 0:33bc88c4ab31 | 131 | Thread::signal_wait(0x1); |
| rvt | 1:5b2ab44eb31f | 132 | hIDActivity=true; |
| rvt | 0:33bc88c4ab31 | 133 | |
| rvt | 0:33bc88c4ab31 | 134 | // Make a local copy of the data |
| rvt | 0:33bc88c4ab31 | 135 | analogValueMutex.lock(); |
| rvt | 0:33bc88c4ab31 | 136 | memcpy (&localCopy, &analogData, sizeof(AnalogData)); |
| rvt | 0:33bc88c4ab31 | 137 | analogValueMutex.unlock(); |
| rvt | 0:33bc88c4ab31 | 138 | |
| rvt | 2:ae7a31a3c618 | 139 | // TODO read buttons |
| rvt | 2:ae7a31a3c618 | 140 | buttons=0; |
| rvt | 2:ae7a31a3c618 | 141 | if (localCopy.button1==true) { |
| rvt | 2:ae7a31a3c618 | 142 | buttons=buttons | 0x01; |
| rvt | 2:ae7a31a3c618 | 143 | } |
| rvt | 2:ae7a31a3c618 | 144 | if (localCopy.button2) { |
| rvt | 2:ae7a31a3c618 | 145 | buttons=buttons | 0x02; |
| rvt | 2:ae7a31a3c618 | 146 | } |
| rvt | 2:ae7a31a3c618 | 147 | if (localCopy.button3) { |
| rvt | 2:ae7a31a3c618 | 148 | buttons=buttons | 0x04; |
| rvt | 2:ae7a31a3c618 | 149 | } |
| rvt | 2:ae7a31a3c618 | 150 | if (localCopy.button4) { |
| rvt | 2:ae7a31a3c618 | 151 | buttons=buttons | 0x08; |
| rvt | 2:ae7a31a3c618 | 152 | } |
| rvt | 2:ae7a31a3c618 | 153 | if (localCopy.button5) { |
| rvt | 2:ae7a31a3c618 | 154 | buttons=buttons | 0x10; |
| rvt | 2:ae7a31a3c618 | 155 | } |
| rvt | 2:ae7a31a3c618 | 156 | |
| rvt | 0:33bc88c4ab31 | 157 | // Update joystick's info |
| rvt | 0:33bc88c4ab31 | 158 | joystick.update( |
| rvt | 0:33bc88c4ab31 | 159 | localCopy.value2, |
| rvt | 0:33bc88c4ab31 | 160 | localCopy.value3, |
| rvt | 0:33bc88c4ab31 | 161 | localCopy.value4, |
| rvt | 0:33bc88c4ab31 | 162 | localCopy.value5, |
| rvt | 2:ae7a31a3c618 | 163 | buttons); |
| rvt | 0:33bc88c4ab31 | 164 | |
| rvt | 0:33bc88c4ab31 | 165 | // Wait 50 ms to send a other USB update |
| rvt | 0:33bc88c4ab31 | 166 | Thread::wait(50); |
| rvt | 0:33bc88c4ab31 | 167 | } |
| rvt | 0:33bc88c4ab31 | 168 | } |
| rvt | 0:33bc88c4ab31 | 169 | |
| rvt | 0:33bc88c4ab31 | 170 | |
| rvt | 0:33bc88c4ab31 | 171 | |
| rvt | 0:33bc88c4ab31 | 172 | int main() |
| rvt | 0:33bc88c4ab31 | 173 | { |
| rvt | 0:33bc88c4ab31 | 174 | analogData.value1=0; |
| rvt | 0:33bc88c4ab31 | 175 | analogData.value2=0; |
| rvt | 0:33bc88c4ab31 | 176 | analogData.value3=0; |
| rvt | 0:33bc88c4ab31 | 177 | analogData.value4=0; |
| rvt | 0:33bc88c4ab31 | 178 | analogData.value5=0; |
| rvt | 0:33bc88c4ab31 | 179 | |
| rvt | 0:33bc88c4ab31 | 180 | #ifdef TTY_DEBUG |
| rvt | 0:33bc88c4ab31 | 181 | Thread _debugThread(debug_thread); |
| rvt | 0:33bc88c4ab31 | 182 | #endif |
| rvt | 0:33bc88c4ab31 | 183 | Thread _hid_thread(hid_thread); |
| rvt | 0:33bc88c4ab31 | 184 | |
| rvt | 0:33bc88c4ab31 | 185 | // Initialise moving average filters |
| rvt | 2:ae7a31a3c618 | 186 | LowPassFilter lowPassFilter1(new AnalogFilterInterface(),0.5f); // The close the alpha value is to 1, the lower the cut-off frequency |
| rvt | 1:5b2ab44eb31f | 187 | LowPassFilter lowPassFilter2(new AnalogFilterInterface(),0.95f); |
| rvt | 1:5b2ab44eb31f | 188 | LowPassFilter lowPassFilter3(new AnalogFilterInterface(),0.95f); |
| rvt | 1:5b2ab44eb31f | 189 | LowPassFilter lowPassFilter4(new AnalogFilterInterface(),0.95f); |
| rvt | 1:5b2ab44eb31f | 190 | LowPassFilter lowPassFilter5(new AnalogFilterInterface(),0.95f); |
| rvt | 0:33bc88c4ab31 | 191 | |
| rvt | 0:33bc88c4ab31 | 192 | // Initialise analog input and tell it what fulters to use |
| rvt | 2:ae7a31a3c618 | 193 | AnalogInFiltered ai1(&lowPassFilter1, p20, DATA_CHANGE_TRIGGER*4); |
| rvt | 2:ae7a31a3c618 | 194 | AnalogInFiltered ai2(&lowPassFilter2, p19, DATA_CHANGE_TRIGGER); |
| rvt | 2:ae7a31a3c618 | 195 | AnalogInFiltered ai3(&lowPassFilter3, p18, DATA_CHANGE_TRIGGER); |
| rvt | 2:ae7a31a3c618 | 196 | AnalogInFiltered ai4(&lowPassFilter4, p17, DATA_CHANGE_TRIGGER); |
| rvt | 2:ae7a31a3c618 | 197 | AnalogInFiltered ai5(&lowPassFilter5, p16, DATA_CHANGE_TRIGGER); |
| rvt | 2:ae7a31a3c618 | 198 | |
| rvt | 2:ae7a31a3c618 | 199 | SimpleButtonDecoder but1(&ai1, 49300, DEBOUNCERUNS); |
| rvt | 2:ae7a31a3c618 | 200 | SimpleButtonDecoder but2(&ai1, 46800, DEBOUNCERUNS); |
| rvt | 2:ae7a31a3c618 | 201 | SimpleButtonDecoder but3(&ai1, 43650, DEBOUNCERUNS); |
| rvt | 2:ae7a31a3c618 | 202 | SimpleButtonDecoder but4(&ai1, 32500, DEBOUNCERUNS); |
| rvt | 2:ae7a31a3c618 | 203 | SimpleButtonDecoder but5(&ai1, 39100, DEBOUNCERUNS); |
| rvt | 0:33bc88c4ab31 | 204 | |
| rvt | 0:33bc88c4ab31 | 205 | while (true) { |
| rvt | 0:33bc88c4ab31 | 206 | // Measure analog in's |
| rvt | 0:33bc88c4ab31 | 207 | ai1.measure(); |
| rvt | 0:33bc88c4ab31 | 208 | ai2.measure(); |
| rvt | 0:33bc88c4ab31 | 209 | ai3.measure(); |
| rvt | 0:33bc88c4ab31 | 210 | ai4.measure(); |
| rvt | 0:33bc88c4ab31 | 211 | ai5.measure(); |
| rvt | 2:ae7a31a3c618 | 212 | |
| rvt | 2:ae7a31a3c618 | 213 | but1.process(); |
| rvt | 2:ae7a31a3c618 | 214 | but2.process(); |
| rvt | 2:ae7a31a3c618 | 215 | but3.process(); |
| rvt | 2:ae7a31a3c618 | 216 | but4.process(); |
| rvt | 2:ae7a31a3c618 | 217 | but5.process(); |
| rvt | 0:33bc88c4ab31 | 218 | |
| rvt | 0:33bc88c4ab31 | 219 | // test of any of the values have been changed, so we only update when data was actually changed |
| rvt | 0:33bc88c4ab31 | 220 | if ( |
| rvt | 0:33bc88c4ab31 | 221 | false |
| rvt | 2:ae7a31a3c618 | 222 | || ai2.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 223 | || ai3.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 224 | || ai4.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 225 | // || ai5.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 226 | || but1.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 227 | || but2.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 228 | || but3.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 229 | || but4.getIsChanged() |
| rvt | 2:ae7a31a3c618 | 230 | || but5.getIsChanged() |
| rvt | 0:33bc88c4ab31 | 231 | ) { |
| rvt | 0:33bc88c4ab31 | 232 | // Copy analog data to global data |
| rvt | 0:33bc88c4ab31 | 233 | analogValueMutex.lock(); |
| rvt | 2:ae7a31a3c618 | 234 | analogData.button1 = but1.getIsPressed(); |
| rvt | 2:ae7a31a3c618 | 235 | analogData.button2 = but2.getIsPressed(); |
| rvt | 2:ae7a31a3c618 | 236 | analogData.button3 = but3.getIsPressed(); |
| rvt | 2:ae7a31a3c618 | 237 | analogData.button4 = but4.getIsPressed(); |
| rvt | 2:ae7a31a3c618 | 238 | analogData.button5 = but5.getIsPressed(); |
| rvt | 2:ae7a31a3c618 | 239 | analogData.value1 = ai1.getData(); |
| rvt | 2:ae7a31a3c618 | 240 | analogData.value2 = ai2.getData(); |
| rvt | 2:ae7a31a3c618 | 241 | analogData.value3 = ai3.getData(); |
| rvt | 2:ae7a31a3c618 | 242 | analogData.value4 = ai4.getData(); |
| rvt | 2:ae7a31a3c618 | 243 | analogData.value5 = ai5.getData(); |
| rvt | 0:33bc88c4ab31 | 244 | analogValueMutex.unlock(); |
| rvt | 0:33bc88c4ab31 | 245 | |
| rvt | 0:33bc88c4ab31 | 246 | // Signal that data has been changed |
| rvt | 0:33bc88c4ab31 | 247 | _hid_thread.signal_set(0x1); |
| rvt | 0:33bc88c4ab31 | 248 | } |
| rvt | 0:33bc88c4ab31 | 249 | Thread::wait(1); |
| rvt | 0:33bc88c4ab31 | 250 | } |
| rvt | 0:33bc88c4ab31 | 251 | } |
| rvt | 0:33bc88c4ab31 | 252 |
