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.
Diff: main.cpp
- Revision:
- 0:3dbb22992c94
diff -r 000000000000 -r 3dbb22992c94 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sat Jul 02 17:27:05 2011 +0000
@@ -0,0 +1,131 @@
+#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.
+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-900)*255/1100; // Normalize reading (Min: 900us Max: 1900 us). This is my readings, yours can be different
+ CurChannel+=1;
+
+ if (CurChannel==11 ) { // 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() {
+
+ 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)
+ // Raise_Error(3,Channels[1]);
+ //Channel 5 : PIT
+ //Channel 6: PLT
+ }
+ }
+
+}
+