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.
main.cpp@0:3dbb22992c94, 2011-07-02 (annotated)
- Committer:
- j3sq
- Date:
- Sat Jul 02 17:27:05 2011 +0000
- Revision:
- 0:3dbb22992c94
Revision 0.0 (This is just a demonstration)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
j3sq | 0:3dbb22992c94 | 1 | #include "mbed.h" |
j3sq | 0:3dbb22992c94 | 2 | #include "usbhid.h" |
j3sq | 0:3dbb22992c94 | 3 | |
j3sq | 0:3dbb22992c94 | 4 | |
j3sq | 0:3dbb22992c94 | 5 | /* RC_Simulator.....By Jafar Qutteineh*/ |
j3sq | 0:3dbb22992c94 | 6 | /* This program takes the PPM Singal(Pulse Position Modulation) from your RC transmitter |
j3sq | 0:3dbb22992c94 | 7 | and emulate it as a USB HID Joystick. |
j3sq | 0:3dbb22992c94 | 8 | Currently, program configured to accept Throttle, Rudder, Elevator, Ailerons and |
j3sq | 0:3dbb22992c94 | 9 | 2 buttons. It can be adjusted easily to read other channels as well. |
j3sq | 0:3dbb22992c94 | 10 | The current state of code is just a proof of concept. It's rough and not clean, |
j3sq | 0:3dbb22992c94 | 11 | once you understand how it work, customize to your like*/ |
j3sq | 0:3dbb22992c94 | 12 | |
j3sq | 0:3dbb22992c94 | 13 | /*Credit goes to Phil Wright for USB HID code and to Shinichiro Oba Joystiq work*/ |
j3sq | 0:3dbb22992c94 | 14 | |
j3sq | 0:3dbb22992c94 | 15 | /*Setup: Just connect the GND and PPM singal of your transmitter to the GND and P5 respectivly.*/ |
j3sq | 0:3dbb22992c94 | 16 | |
j3sq | 0:3dbb22992c94 | 17 | /*How it works: |
j3sq | 0:3dbb22992c94 | 18 | -P5 is configured as InturreptIn pin. whenever the PPM signal goes down Inturrept SignalFall() is fired. |
j3sq | 0:3dbb22992c94 | 19 | -SignalFall keep track of timing: |
j3sq | 0:3dbb22992c94 | 20 | a) If Pulse width is <300 uS it's most probably a glitch. |
j3sq | 0:3dbb22992c94 | 21 | b) If pulse width is >300 uS but less than < 2000 uS this is a correct channel. Read it and wait for next channel |
j3sq | 0:3dbb22992c94 | 22 | c) If Pulse width is >8000 uS this is a new frame, start again. |
j3sq | 0:3dbb22992c94 | 23 | d) Timing will be different from transmitter to another, you may want to play a little bit here |
j3sq | 0:3dbb22992c94 | 24 | -Once a complete frame is read the values are feedback to our USB HID Joysick class. |
j3sq | 0:3dbb22992c94 | 25 | */ |
j3sq | 0:3dbb22992c94 | 26 | |
j3sq | 0:3dbb22992c94 | 27 | |
j3sq | 0:3dbb22992c94 | 28 | |
j3sq | 0:3dbb22992c94 | 29 | InterruptIn PPMsignal(p5); // connect PPM signal to this, you can change to anyother pin |
j3sq | 0:3dbb22992c94 | 30 | Serial PC(USBTX,USBRX); // I used this for debuging |
j3sq | 0:3dbb22992c94 | 31 | USBJoystick joystick; /* This is basicly Shinichiro joystiq, I've only adjusted the Report descriptor to my needs. |
j3sq | 0:3dbb22992c94 | 32 | for more help on this check: |
j3sq | 0:3dbb22992c94 | 33 | -http://frank.circleofcurrent.com/cache/hid_tutorial_1.htm |
j3sq | 0:3dbb22992c94 | 34 | -http://helmpcb.com/electronics/usb-joystick */ |
j3sq | 0:3dbb22992c94 | 35 | |
j3sq | 0:3dbb22992c94 | 36 | |
j3sq | 0:3dbb22992c94 | 37 | int TimeElapsed =0; //Keeps track of time between inturrepts |
j3sq | 0:3dbb22992c94 | 38 | Timer timer; |
j3sq | 0:3dbb22992c94 | 39 | unsigned char CurChannel=0; //This will point to the current channel in PPM frame. My PPM signal looks like 10 channels and 1 start frame |
j3sq | 0:3dbb22992c94 | 40 | // yours could be different |
j3sq | 0:3dbb22992c94 | 41 | unsigned char Channels[11]={0,0,0,0,0,0,0,0,0,0,0}; //This where channels value is stored until frame is complete. |
j3sq | 0:3dbb22992c94 | 42 | bool CanUpdate=false; // Once PPM frame is complete this will be true |
j3sq | 0:3dbb22992c94 | 43 | |
j3sq | 0:3dbb22992c94 | 44 | //Raise_Error is just a function that helped me in development process. You can ignore it all togather. |
j3sq | 0:3dbb22992c94 | 45 | void Raise_Error (unsigned char Err_Code, int info) { |
j3sq | 0:3dbb22992c94 | 46 | switch (Err_Code) { |
j3sq | 0:3dbb22992c94 | 47 | case 0: |
j3sq | 0:3dbb22992c94 | 48 | PC.printf ("%i\n",info); |
j3sq | 0:3dbb22992c94 | 49 | break; |
j3sq | 0:3dbb22992c94 | 50 | case 1: |
j3sq | 0:3dbb22992c94 | 51 | PC.printf ("Broke@ %i\n",info); |
j3sq | 0:3dbb22992c94 | 52 | break; |
j3sq | 0:3dbb22992c94 | 53 | case 2: |
j3sq | 0:3dbb22992c94 | 54 | PC.printf ("Set ok\n"); |
j3sq | 0:3dbb22992c94 | 55 | break; |
j3sq | 0:3dbb22992c94 | 56 | case 3: |
j3sq | 0:3dbb22992c94 | 57 | PC.printf ("%i\n",info); |
j3sq | 0:3dbb22992c94 | 58 | break; |
j3sq | 0:3dbb22992c94 | 59 | case 255: |
j3sq | 0:3dbb22992c94 | 60 | PC.printf("Initalized sucessfully \n"); |
j3sq | 0:3dbb22992c94 | 61 | break; |
j3sq | 0:3dbb22992c94 | 62 | default: |
j3sq | 0:3dbb22992c94 | 63 | PC.printf("I shouldn't be here \n"); |
j3sq | 0:3dbb22992c94 | 64 | } |
j3sq | 0:3dbb22992c94 | 65 | |
j3sq | 0:3dbb22992c94 | 66 | } |
j3sq | 0:3dbb22992c94 | 67 | |
j3sq | 0:3dbb22992c94 | 68 | //Here were all the work takeplace |
j3sq | 0:3dbb22992c94 | 69 | void SignalFall() { |
j3sq | 0:3dbb22992c94 | 70 | TimeElapsed = timer.read_us(); |
j3sq | 0:3dbb22992c94 | 71 | if (TimeElapsed <300) { |
j3sq | 0:3dbb22992c94 | 72 | //Raise_Error(0,TimeElapsed); |
j3sq | 0:3dbb22992c94 | 73 | return; //ignore, it's a glitch. Dont move to the next channel |
j3sq | 0:3dbb22992c94 | 74 | } |
j3sq | 0:3dbb22992c94 | 75 | __disable_irq(); |
j3sq | 0:3dbb22992c94 | 76 | timer.reset(); |
j3sq | 0:3dbb22992c94 | 77 | //Raise_Error(0,TimeElapsed); |
j3sq | 0:3dbb22992c94 | 78 | if ((TimeElapsed > 8000 ) && (CurChannel != 0)) { //somehow before reaching the end of PPM frame you read "New" frame signal??? |
j3sq | 0:3dbb22992c94 | 79 | //Ok, it happens. Just ignore this frame and start a new one |
j3sq | 0:3dbb22992c94 | 80 | // Raise_Error (1,CurChannel); //incomplete channels set |
j3sq | 0:3dbb22992c94 | 81 | CurChannel=0; |
j3sq | 0:3dbb22992c94 | 82 | } |
j3sq | 0:3dbb22992c94 | 83 | if ((TimeElapsed < 8000 ) && (CurChannel == 0)) { |
j3sq | 0:3dbb22992c94 | 84 | // Raise_Error (1,CurChannel); //incomplete channels set |
j3sq | 0:3dbb22992c94 | 85 | __enable_irq(); // This is good. You've received "New" frame signal as expected |
j3sq | 0:3dbb22992c94 | 86 | return; |
j3sq | 0:3dbb22992c94 | 87 | } |
j3sq | 0:3dbb22992c94 | 88 | |
j3sq | 0:3dbb22992c94 | 89 | // Process current channel. This is a correct channel in a correct frame so far |
j3sq | 0:3dbb22992c94 | 90 | //if (CurChannel==4) Raise_Error(3,TimeElapsed); |
j3sq | 0:3dbb22992c94 | 91 | Channels[CurChannel]= (TimeElapsed-900)*255/1100; // Normalize reading (Min: 900us Max: 1900 us). This is my readings, yours can be different |
j3sq | 0:3dbb22992c94 | 92 | CurChannel+=1; |
j3sq | 0:3dbb22992c94 | 93 | |
j3sq | 0:3dbb22992c94 | 94 | if (CurChannel==11 ) { // great!, you've a complete correct frame. Update Joystick and star a new frame |
j3sq | 0:3dbb22992c94 | 95 | CurChannel=0; |
j3sq | 0:3dbb22992c94 | 96 | // Raise_Error(3,0); |
j3sq | 0:3dbb22992c94 | 97 | CanUpdate= true; |
j3sq | 0:3dbb22992c94 | 98 | } |
j3sq | 0:3dbb22992c94 | 99 | __enable_irq(); |
j3sq | 0:3dbb22992c94 | 100 | } |
j3sq | 0:3dbb22992c94 | 101 | |
j3sq | 0:3dbb22992c94 | 102 | void Initalize () { |
j3sq | 0:3dbb22992c94 | 103 | __disable_irq(); |
j3sq | 0:3dbb22992c94 | 104 | PC.baud(115200); // set baude rate |
j3sq | 0:3dbb22992c94 | 105 | PPMsignal.mode (PullUp); |
j3sq | 0:3dbb22992c94 | 106 | PPMsignal.fall(&SignalFall); //Attach SignalFall routine to handle PPMsignal fall |
j3sq | 0:3dbb22992c94 | 107 | timer.start(); |
j3sq | 0:3dbb22992c94 | 108 | Raise_Error(255,0); // return successful |
j3sq | 0:3dbb22992c94 | 109 | timer.reset(); |
j3sq | 0:3dbb22992c94 | 110 | __enable_irq(); |
j3sq | 0:3dbb22992c94 | 111 | |
j3sq | 0:3dbb22992c94 | 112 | } |
j3sq | 0:3dbb22992c94 | 113 | |
j3sq | 0:3dbb22992c94 | 114 | int main() { |
j3sq | 0:3dbb22992c94 | 115 | |
j3sq | 0:3dbb22992c94 | 116 | Initalize(); |
j3sq | 0:3dbb22992c94 | 117 | wait(5); |
j3sq | 0:3dbb22992c94 | 118 | |
j3sq | 0:3dbb22992c94 | 119 | |
j3sq | 0:3dbb22992c94 | 120 | while (1) { |
j3sq | 0:3dbb22992c94 | 121 | if (CanUpdate) { // update joystick here |
j3sq | 0:3dbb22992c94 | 122 | CanUpdate=false; |
j3sq | 0:3dbb22992c94 | 123 | joystick.joystick(Channels[1],Channels[4],Channels[3],Channels[2],Channels[7],Channels[8]); //update joystick state (Throttle, Rudder, X,Y, Button 1, Button 2) |
j3sq | 0:3dbb22992c94 | 124 | // Raise_Error(3,Channels[1]); |
j3sq | 0:3dbb22992c94 | 125 | //Channel 5 : PIT |
j3sq | 0:3dbb22992c94 | 126 | //Channel 6: PLT |
j3sq | 0:3dbb22992c94 | 127 | } |
j3sq | 0:3dbb22992c94 | 128 | } |
j3sq | 0:3dbb22992c94 | 129 | |
j3sq | 0:3dbb22992c94 | 130 | } |
j3sq | 0:3dbb22992c94 | 131 |