After my work on the Syma 107G was featured on Hackaday, [Maksim] emailed me to talk about writing up a programming library for the Syma 107 control protocol that would allow someone to control an RC boat, car, etc… with the S107T2 controller. I thought this was a cool idea, so I gave it a shot — here’s the lowdown on SymaLib.

Download & Requirements
Get the SymaLib library (v0.1) here. The library was written for the Arduino IDE v1.1 and is designed for use with a sketch similar to Adafruit’s IR Commander sketch (reference, github).
Details
I started with the excellent Adafruit Industries IR Commander sketch as it is easy to understand and takes care of populating an array with the on/off pulse lengths for me. With this raw material, all the SymaLib library has to take care of is parse the received pulse lengths into their respective bit-wise values and provide a series of methods to get the parsed values of the handset’s controls.
Version 0.1 currently allows you to parse the 32-bit control packets from the S107T2 controller (described in my protocol spec: here) and return each control value as an integer.
Example
/*
SymaLib Library Example v0.1 by Jim Hung (www.jimhung.com)
This example code is designed to demonstrate the usage of the SymaLib
to decode control signals from a S107T2 RC helicopter controller.
Based on 'Raw IR commander' by Ladyada:
"This sketch/program uses the Arduno and a PNA4602 to
decode IR received. It then attempts to match it to a previously
recorded IR signal
Code is public domain, check out www.ladyada.net and adafruit.com
for more tutorials!"
*/
#include // include the SymaLib library
#define IRpin_PIN PIND
#define IRpin 2
#define MAXPULSE 2000
#define NUMPULSES 50
#define RESOLUTION 20
#define FUZZINESS 30
uint16_t pulses[NUMPULSES][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing
SymaLib protocolparser; // declare our SymaLib object
void setup(void) {
Serial.begin(9600);
Serial.println("Ready to decode IR!");
}
void loop(void) {
int numberpulses;
String ctrldata = "";
// Listen for IR signals and populate the array of pulse lengths
numberpulses = listenForIR();
// Give the SymaLib object the pulse array to parse. If it's a valid Syma107
// control packet, SymaLib returns boolean True.
boolean result = protocolparser.setPulseListParse(pulses,numberpulses,RESOLUTION,FUZZINESS);
if (result) {
// Read the controller values and do whatever you need to with them.
// This example prints out the integer values for each control:
Serial.print(" Yaw: ");
Serial.print(protocolparser.getYawDec());
Serial.print("\tPitch: ");
Serial.print(protocolparser.getPitchDec());
Serial.print("\tChannel: ");
Serial.print(protocolparser.getChanDec());
Serial.print("\tThrottle: ");
Serial.print(protocolparser.getThrottleDec());
Serial.print("\tTrim: ");
Serial.print(protocolparser.getTrimDec());
Serial.print("\n");
// This example prints out the binary values for the 32-bit control packet:
Serial.println(protocolparser.getCtrlPacketBin());
}
delay(100);
}
int listenForIR(void) {
currentpulse = 0;
while (1) {
uint16_t highpulse, lowpulse;
highpulse = lowpulse = 0;
while (IRpin_PIN & _BV(IRpin)) {
highpulse++;
delayMicroseconds(RESOLUTION);
if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][0] = highpulse;
while (! (IRpin_PIN & _BV(IRpin))) {
lowpulse++;
delayMicroseconds(RESOLUTION);
if (((lowpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
return currentpulse;
}
}
pulses[currentpulse][1] = lowpulse;
currentpulse++;
}
}
Library Reference
Here are the methods provided by the SymaLib library:
SymaLib()
Constructor. No arguments — initializes control byte array.
setPulseListParse()
Returns: Boolean
Arguments:
uint16_t pulses[][2] — The pulse array populated by the ‘listenForIR’-like method.
int& numpulses — The number of pulses heard by the ‘listenForIR’-like method.
int resolution — The RESOLUTION constant used to calibrate the IR listener.
int fuzziness — The FUZZINESS constant used to calibrate the IR listener.
Description:
This method parses the pulse-array and stores it as an array of integers, either 1 or 0. This array is the basis of the object’s Get methods.
getYawDec()
Returns: Int
Arguments: None.
Description:
Returns an integer of the decimal value of the Yaw control.
getPitchDec()
Returns: Int
Arguments: None.
Description:
Returns an integer of the decimal value of the Pitch control.
getChanDec()
Returns: Int
Arguments: None.
Description:
Returns an integer of the decimal value of the channel switch.
getThrottleDec()
Returns: Int
Arguments: None.
Description:
Returns an integer of the decimal value of the Throttle control.
getTrimDec()
Returns: Int
Arguments: None.
Description:
Returns an integer of the decimal value of the Trim control.
getCtrlPacketBin()
Returns: String
Arguments: None.
Description:
Returns a String of ‘1’ and ‘0’s representing the 32-bit control packet. Useful for debugging.
Conclusion
This is the first Arduino library I’ve ever written (hopefully not the last!) and I hope it is useful for other hackers. [Maksim]‘s idea was cool and I’d love to see any projects that end up using it. Let me know in the comments!
Take care,
Jim
Hello Jim
It is possible to see your arduino code with smooth equelizer — this from YT ?
Greetings
Max