Jafar Qutteineh / Mbed 2 deprecated RC_Simulator

Dependencies:   mbed

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?

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