3pi IR remote control

As I was not sure if I can port existing IR control libs to 3pi I try my own.
I use as receiver tsop4138 …works well with my sony IR remote control.

I did the first tests with the pololu programmer oszi and ended up in this

The decoding of the sony protocol is not that difficult. I found a good explanation here:

To make it easy … the information is finaly in the low pulse length.
if it is short it is a 0;
if it is longer it is 1;
if it is extra long it is the start token.
if you have 12 bits (and use a 12 bit IR control) you have the IRcode which is devided in addr and cmd.

I used the inpulse lib which makes it quiet easy to react on the falling edge of the IR sensor.

The example decoder looks like this one

while (1) {
	get_pulse_info(0, &pulse_info);  // get pulse info  0=1st channel of the pulseInPins[]
	// we wait for the first falling edge ..could not get triggered that by the function?
	if (pulse_info.newPulse == LOW_PULSE) {
		// we only care for the low pulse as here is the info
		//we are high and can check the last low pulse length 
		//ToDo ..make it portable to different CPU clocks
		if ((pulse_info.lastLowPulse > 1000) && (pulse_info.lastLowPulse < 2000)) {
            bits++;	//we have a zero bit ..nothing to do with IRcode as 0 is default set
			else if (pulse_info.lastLowPulse < 3500) {
				// we have a 1 and need to set the bit in IRcode
				IRcode|= (uint16_t)(1<< bits); bits++; 
				else if (pulse_info.lastLowPulse < 7000) {
				IRtoken++; // we have a start token
		//everything else is a problem we might add error counter and handling
		if ((IRtoken > 1) ||  //we should not see more than 1 token
		    ((bits > 0) && (IRtoken != 1)) ||  // we have bits before token
		    (bits > 12)  // we have too many bits
			) // we should also care for the high pulse errors ..but works 
			{ // reset everything; some debug output would be nice
				IRtoken = 0; bits=0; IRcode=0;			 
		    else if (bits == 12) { // we have the code
				IRcmd = IRcode & (int) 0b1111111; // lowest 7 bit are the cmd
				IRaddr = IRcode >> 7; //upper 5 (of 12) bits are the address
				//ToDo ..what we are doing with the IRcmd
				//we might have a nice callback function
				//should we care about the 3x replications typical for sony?
				// we could determine the distance between the IRtokens ..
				// now we can reset everything
				IRtoken = 0; bits=0; IRcode=0;

Where is room for improvement …handling the error noise … high pulse length are simply ignored.
But so far it works fine …its more the button of the 15 years old IR control which make some problems.

So far not bad …but now comes the problem with the 3pi. The shortest low pulse wide is about 500us.
As the inpulse lib makes you polling and the IRsensor for the line follower is blocking upto 2 ms …
you could not use both.
Current approach to get around it: shift the bit decoding into the ISR of the Pin Change Interrupt and provide
the decoded cmd. That should not happen faster than every 45 ms.
(which makes also clear …why IR controls are not the best way for movement control of a robot, delay and
number of cmd per second is not good)

The downside of the own ISR …first it takes longer …second it will mostlikely conflict with the inpulse lib.
May be I find a way to extend the InPulse lib in a compatible way …
Or I focus on that IRSensor lib …

Here my proposal for a inPulse extension:

add a callback funktion which allows to add additional functionality to the ISR.
could be part of the PulseInputStruct …
and set via an extra method per pin

as an example, the QTRSensors could use this lib to load the capacitor after every falling edge.

callback funktion should have access to its pulsinfo to get further infos
clear risk is the extended processing time of the ISR
serval open questions:
do we need to disable / enable the interrupt?
could it make sense to group pins to 1 callback function (reduces number of calls if you have serval pins with
the same callback function)?
for that …might be a better approach to have multiple instances of PulseIn object and having only 1 callback per
instance …but getting conflict with haveing only 1 ISR per InputPort???

other feature needed for QTRSensor would be a timeout …