RC_Simulator.....By Jafar Qutteineh with mods to connect my Futaba 9C to \'RC Helicopter\' by http://www.alphamacsoftware.com/
main.cpp
- Committer:
- cbayley
- Date:
- 2011-12-15
- Revision:
- 0:65b9d8f621d2
File content as of revision 0:65b9d8f621d2:
#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 } } }