Ries Twisk / Mbed 2 deprecated JoyStick

Dependencies:   USBDevice mbed-rtos mbed

Fork of JoyStick by Ries Twisk

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?

UserRevisionLine numberNew 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