RC_Simulator.....By Jafar Qutteineh with mods to connect my Futaba 9C to \'RC Helicopter\' by http://www.alphamacsoftware.com/
Diff: main.cpp
- Revision:
- 0:65b9d8f621d2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Dec 15 03:24:33 2011 +0000 @@ -0,0 +1,135 @@ +#include "mbed.h" +#include "usbhid.h" + + +/* RC_Simulator.....By Jafar Qutteineh*/ +/* This program takes the PPM Singal(Pulse Position Modulation) from your RC transmitter + and emulate it as a USB HID Joystick. + Currently, program configured to accept Throttle, Rudder, Elevator, Ailerons and + 2 buttons. It can be adjusted easily to read other channels as well. + The current state of code is just a proof of concept. It's rough and not clean, + once you understand how it work, customize to your like*/ + +/*Credit goes to Phil Wright for USB HID code and to Shinichiro Oba Joystiq work*/ + +/*Setup: Just connect the GND and PPM singal of your transmitter to the GND and P5 respectivly.*/ + +/*How it works: + -P5 is configured as InturreptIn pin. whenever the PPM signal goes down Inturrept SignalFall() is fired. + -SignalFall keep track of timing: + a) If Pulse width is <300 uS it's most probably a glitch. + b) If pulse width is >300 uS but less than < 2000 uS this is a correct channel. Read it and wait for next channel + c) If Pulse width is >8000 uS this is a new frame, start again. + d) Timing will be different from transmitter to another, you may want to play a little bit here + -Once a complete frame is read the values are feedback to our USB HID Joysick class. +*/ + + + +InterruptIn PPMsignal(p5); // connect PPM signal to this, you can change to anyother pin +Serial PC(USBTX,USBRX); // I used this for debuging +USBJoystick joystick; /* This is basicly Shinichiro joystiq, I've only adjusted the Report descriptor to my needs. + for more help on this check: + -http://frank.circleofcurrent.com/cache/hid_tutorial_1.htm + -http://helmpcb.com/electronics/usb-joystick */ + + +int TimeElapsed =0; //Keeps track of time between inturrepts +Timer timer; +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 + // yours could be different +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. +unsigned short Times[11]={0,0,0,0,0,0,0,0,0,0,0}; //This where channels value is stored until frame is complete. +bool CanUpdate=false; // Once PPM frame is complete this will be true + +//Raise_Error is just a function that helped me in development process. You can ignore it all togather. +void Raise_Error (unsigned char Err_Code, int info) { + switch (Err_Code) { + case 0: + PC.printf ("%i\n",info); + break; + case 1: + PC.printf ("Broke@ %i\n",info); + break; + case 2: + PC.printf ("Set ok\n"); + break; + case 3: + PC.printf ("%i\n",info); + break; + case 255: + PC.printf("Initalized sucessfully \n"); + break; + default: + PC.printf("I shouldn't be here \n"); + } + +} + +//Here were all the work takeplace +void SignalFall() { + TimeElapsed = timer.read_us(); + if (TimeElapsed <300) { + //Raise_Error(0,TimeElapsed); + return; //ignore, it's a glitch. Dont move to the next channel + } + __disable_irq(); + timer.reset(); + //Raise_Error(0,TimeElapsed); + if ((TimeElapsed > 8000 ) && (CurChannel != 0)) { //somehow before reaching the end of PPM frame you read "New" frame signal??? + //Ok, it happens. Just ignore this frame and start a new one + //Raise_Error (1,CurChannel); //incomplete channels set + CurChannel=0; + } + if ((TimeElapsed < 8000 ) && (CurChannel == 0)) { + //Raise_Error (1,CurChannel); //incomplete channels set + __enable_irq(); // This is good. You've received "New" frame signal as expected + return; + } + + // Process current channel. This is a correct channel in a correct frame so far + //if (CurChannel==4) Raise_Error(3,TimeElapsed); + Channels[CurChannel]= (TimeElapsed-1000)*255/1000; // Normalize reading (Min: 900us Max: 1900 us). This is my readings, yours can be different + Times[CurChannel] = TimeElapsed; + CurChannel++; + + if (CurChannel==9 ) { // great!, you've a complete correct frame. Update Joystick and star a new frame + CurChannel=0; + //Raise_Error(3,0); + CanUpdate= true; + } + __enable_irq(); +} + +void Initalize () { + __disable_irq(); + PC.baud(115200); // set baude rate + PPMsignal.mode (PullUp); + PPMsignal.fall(&SignalFall); //Attach SignalFall routine to handle PPMsignal fall + timer.start(); + Raise_Error(255,0); // return successful + timer.reset(); + __enable_irq(); + +} + +int main() { + //unsigned short *pOut = Times; + unsigned char *pOut = Channels; + + Initalize(); + //wait(5); + + + while (1) { + if (CanUpdate) { // update joystick here + CanUpdate=false; + 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) + PC.printf("% 4d,% 4d,% 4d,% 4d\r",pOut[1],pOut[2],pOut[3],pOut[4]); // Raise_Error(3,Channels[1]); + //Channel 5 : PIT + //Channel 6: PLT + } + } + +} +