cyborg5 / IRLib

An Arduino library for encoding and decoding infrared remote signals
Other
213 stars 76 forks source link

Feature request: Implement IRP notation #1

Closed probonopd closed 6 years ago

probonopd commented 11 years ago

Wouldn't it be cool if we could send the Arduino a command like:

SEND NEC1 0 191 1

and it would correctly send the code (but not just for a handful but for ALL protocols)?

John S. Fine, who is the original IRP inventor, writes on http://www.remotecentral.com/cgi-bin/forums/viewpost.cgi?811010

"The easiest way to make a generator for many different protocols (such as a universal remote) would be to make a program that understands IRP notation and uses it as the guide to generating the signals. My MakeHex program (source code available at [Link: john.fine.home.comcast.net] ) generates Pronto Hex from an older form of IRP notation. It is a good C++ example of how to translate from an IRP notation to the actual signal."

cyborg5 commented 11 years ago

The IRP notation that Mr. Fine speaks of is a rather complicated syntax that defines a protocol but it doesn't really help you what data to send for a particular function. Your example of "SEND NEC… Some string of numbers…" Isn't what IRP does. The IRP notation for NEC1 is IRP notation: {38.4k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,-78,(16,-4,1,-173)_) The amount of code necessary to parse and interpret that string of text would be major. However if you understand IRP notation it was pretty easy to write the following line of code sendGeneric(data,32, 564_16, 564_8, 564, 564, 564_3, 564, 38, true); which sends data to an NEC protocol device. In an upcoming tutorial I hope to talk more about IRP notation so that people can implement other protocols by studying the notation and writing the necessary code. I use the following reference for IRP notation. http://www.hifi-remote.com/johnsfine/DecodeIR.html and it lists about 40 different protocols. I could implement them all but unless I have actual devices that use those protocols I have no way of testing. I don't like putting out untested code.

The kind of command that you are talking about sending to the Arduino is something that I have partially implemented in part 3 of my IRLib tutorial which you can read here. http://tech.cyborg5.com/irlib/ By the way the link that you sent and quoted has a number of outdated links in it that are no longer valid so I can't see the pages that he's talking about.

probonopd commented 11 years ago

Thanks for the quick response and sorry if I was unclear. What I am looking for is a way to send arbitrary commands via the Arduino, without having to modify the sketch or the library whenever I need a new/other protocol. (Background: I am working on compiling a crowdsourced database of IR commands, and would want to send these IR commands to devices in order to test them. This can be done using specialized equipment, but an Arduino would be better suited because it is cheap and widely available to users.)

Your work with IRP and Arduino made me think of the following scheme: Say tomorrow comes a protocol "newproto" with IRP notation "{foo}(bar,(baz))". Then it would be nice if we could send to the arduino: SET newproto = "{foo}(bar,(baz))" SEND newproto 0 191 1 Would that exceed the hardware power of what the Arduino can do?

Another idea to achieve something similar would be to send the Arduino raw signals, and create these raw signals on the host computer using an IRP interpreter such as MakeHex, like so: SEND +9024 -4512 +564 -564 +564 ...

Another idea would be to send the Arduino Pronto Hex, and have the Arduino interpret that, like so: SEND 0000 006C 0022 0002 015B ...

Or just hex: SEND 00 00 27 00 D3 04 10 68 ...

Which route seems most feasible to you?

cyborg5 commented 11 years ago

The idea of sending it the IRP of the protocol that it would then remember is pretty much beyond the limited capability. Most of them only have 2K RAM for data even if they do have 16 or 30 2K for program memory. I'm not familiar with some of these hex notations that you're talking about such as Pronto Hex. Can you point me to a reference. We do have a raw format implemented that assumes 38 kHz and then it's just the length of each single as marks and spaces. With the limited power of an Arduino however the simpler the command is the better. Most people use Arduino for small standalone devices and they know or can pretty easily determine the protocol. If I had a bunch of users who had access to all of the protocols in some reference when contest them out I would not mind writing up the code and putting it in the library but I just don't want to arbitrarily implement something and hope it works. Feel free to contact me directly at cy_borg5@cyborg5.com rather than through github.

arturmaj commented 10 years ago

I am trying to send IR commands to X10 IR543. IRP notation for X10: {40.8k,565}<2,-12|7,-7>(7,-7,F:5,~F:5,21,-7)+ . EFC translation: LSB of 2*OBC+1. How do I convert IRP to: sendGeneric(unsigned long data, unsigned char Num_Bits, unsigned int Head_Mark, unsigned int Head_Space, unsigned int Mark_One, unsigned int Mark_Zero, unsigned int Space_One, unsigned int Space_Zero, unsigned char kHz, bool Use_Stop, unsigned long Max_Extent).

arturmaj commented 10 years ago

Detail description of the IR543 codes can be found here: http://davehouston.org/ir.htm . And also : Protocol=X10AH-Housecode Frequency=40000 Time Base=650 One=7,-7 Zero=2,-13 Form=;*,F:4,~F:4,_ Prefix=8,-8 suffix=23,-8

cyborg5 commented 10 years ago

In the IRP notation the 40.8 is the kilohertz but it only uses integer numbers so I would just rounded down to 40. That would be close enough. 565 is the base time interval. Everything else is expressed in multiples of that interval. The 7, -7 is the length of the header mark and space so 565_7= 3955 however the other document that you linked to me says that the header should be 4000 so I would use 4000 for both. The part of the IRP which says "F:5,~F:5" means that the function code is five bits long followed by the bitwise complement of the five bits function code. However typically I don't care what the data is. For our purposes it just tells us that there are 10 bits of data. The following 21, -7 is some sort of a trailer. I'm really surprised that the 21 is there because that means 21_565=11865 µs followed by 4000 µs of space. That's really unusual to have a trailer link that. Your other reference however does say that there is 12 ms or about 12,000 µs of trailer. That may mean that the sendGeneric would not work. You could try using sendGeneric without a stop bit and then afterwards use a mark (12000); space(4000);

Your IRP notation is missing the information on what constitutes a "1" and a "0" but the other reference that you sent me says that a "1" 4000, 4000 and that a "0" is 1200, 6800.

That would give us something like this…

void X10IR543:: send(unsigned long data) {

sendGeneric(data, 10, 4000, 4000, 4000, 4000, 1200, 6800, 40,0,0);

mark(12000); space(4000);

};

My concern is that the exit from sendGeneric might not be quick enough to get that final mark and space. If that doesn't work you have to write a custom send routine.

So try playing around with that and see what kind of results you get. If it doesn't work and I get some free time I would write you up something more specific that is if I get time.

Let me know how it goes.

From: Artur Maj [mailto:notifications@github.com] Sent: Friday, January 31, 2014 6:45 PM To: cyborg5/IRLib Cc: Chris Young Subject: Re: [IRLib] Feature request: Implement IRP notation (#1)

I am trying to send IR commands to X10 IR543. IRP notation for X10: {40.8k,565}(7,-7,F:5,~F:5,21,-7)+ . EFC translation: LSB of 2*OBC+1. How do I convert IRP to: sendGeneric(unsigned long data, unsigned char Num_Bits, unsigned int Head_Mark, unsigned int Head_Space, unsigned int Mark_One, unsigned int Mark_Zero, unsigned int Space_One, unsigned int Space_Zero, unsigned char kHz, bool Use_Stop, unsigned long Max_Extent).

— Reply to this email directly or view it on GitHub https://github.com/cyborg5/IRLib/issues/1#issuecomment-33854337 . https://github.com/notifications/beacon/3612858__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcwNjc0NDcxMCwiZGF0YSI6eyJpZCI6MTIzNzI5NTN9fQ==--b6fcd4fc41f1c429e7754830d0f0959a7a3be27f.gif

arturmaj commented 10 years ago

Thank you Chris for the analysis. It did not work. I found another project on GitHub https://github.com/probonopd/arduino-infrared-pronto . The app converts pronto codes to IR and this is what works for me. Thanks again.

On Sat, Feb 1, 2014 at 10:03 AM, Chris Young notifications@github.comwrote:

In the IRP notation the 40.8 is the kilohertz but it only uses integer numbers so I would just rounded down to 40. That would be close enough. 565 is the base time interval. Everything else is expressed in multiples of that interval. The 7, -7 is the length of the header mark and space so 565_7= 3955 however the other document that you linked to me says that the header should be 4000 so I would use 4000 for both. The part of the IRP which says "F:5,~F:5" means that the function code is five bits long followed by the bitwise complement of the five bits function code. However typically I don't care what the data is. For our purposes it just tells us that there are 10 bits of data. The following 21, -7 is some sort of a trailer. I'm really surprised that the 21 is there because that means 21_565=11865 µs followed by 4000 µs of space. That's really unusual to have a trailer link that. Your other reference however does say that there is 12 ms or about 12,000 µs of trailer. That may mean that the sendGeneric would not work. You could try using sendGeneric without a stop bit and then afterwards use a mark (12000); space(4000);

Your IRP notation is missing the information on what constitutes a "1" and a "0" but the other reference that you sent me says that a "1" 4000, 4000 and that a "0" is 1200, 6800.

That would give us something like this...

void X10IR543:: send(unsigned long data) {

sendGeneric(data, 10, 4000, 4000, 4000, 4000, 1200, 6800, 40,0,0);

mark(12000); space(4000);

};

My concern is that the exit from sendGeneric might not be quick enough to get that final mark and space. If that doesn't work you have to write a custom send routine.

So try playing around with that and see what kind of results you get. If it doesn't work and I get some free time I would write you up something more specific that is if I get time.

Let me know how it goes.

From: Artur Maj [mailto:notifications@github.com] Sent: Friday, January 31, 2014 6:45 PM To: cyborg5/IRLib Cc: Chris Young Subject: Re: [IRLib] Feature request: Implement IRP notation (#1)

I am trying to send IR commands to X10 IR543. IRP notation for X10: {40.8k,565}(7,-7,F:5,~F:5,21,-7)+ . EFC translation: LSB of 2*OBC+1. How do I convert IRP to: sendGeneric(unsigned long data, unsigned char Num_Bits, unsigned int Head_Mark, unsigned int Head_Space, unsigned int Mark_One, unsigned int Mark_Zero, unsigned int Space_One, unsigned int Space_Zero, unsigned char kHz, bool Use_Stop, unsigned long Max_Extent).

Reply to this email directly or view it on GitHub < https://github.com/cyborg5/IRLib/issues/1#issuecomment-33854337> . < https://github.com/notifications/beacon/3612858__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcwNjc0NDcxMCwiZGF0YSI6eyJpZCI6MTIzNzI5NTN9fQ==--b6fcd4fc41f1c429e7754830d0f0959a7a3be27f.gif>

Reply to this email directly or view it on GitHubhttps://github.com/cyborg5/IRLib/issues/1#issuecomment-33878700 .

probonopd commented 9 years ago

I tried to convert MakeHex to Arduino and it appears to start working, but it still has some issues (among which a memory leak) that I was not able to fix so far. Maybe you'd like to have a look at it. https://github.com/probonopd/MakeHex/tree/arduino/encodeir

bengtmartensson commented 9 years ago

I hate to stop enthusiasts, but I doubt this is a good idea. The IRP version implemented in Makehex is obsolete, current is the version 2, which is implemented in https://github.com/bengtmartensson/harctoolboxbundle/tree/master/IrpMaster. (took a few months and several thousands of lines in Java, still not implementing the (practically completely useless) hierarchical repetitions.) There is a vast difference between version 1 and 2. And John Fine's code is of quite low quality, writing outside of array limits, incorrectly rounding, etc (note that Makehex NEC1 signal contains both 0015 and 0016 :-))

Instead, I suggest having a program like IrpMaster generate Arduino C++-code (or a complete sketch) that can be incorporated in a sender that is capable of rendering and sending these signals?

cyborg5 commented 9 years ago

I tend to agree that converting IRP into something that Arduino could use would best be left to a standalone program that would extract timing values that could then be implemented in C++ code.

From: Bengt Martensson [mailto:notifications@github.com] Sent: Sunday, July 19, 2015 1:45 PM To: cyborg5/IRLib Cc: Chris Young Subject: Re: [IRLib] Feature request: Implement IRP notation (#1)

I hate to stop enthusiasts, but I doubt this is a good idea. The IRP version implemented in Makehex is obsolete, current is the version 2, which is implemented in https://github.com/bengtmartensson/harctoolboxbundle/tree/master/IrpMaster. (took a few months and several thousands of lines in Java, still not implementing the (practically completely useless) hierarchical repetitions.) There is a vast difference between version 1 and 2. And John Fine's code is of quite low quality, writing outside of array limits, incorrectly rounding, etc (note that Makehex NEC1 signal contains both 0015 and 0016 :-))

Instead, I suggest having a program like IrpMaster generate Arduino C++-code (or a complete sketch) that can be incorporated in a sender that is capable of rendering and sending these signals?

— Reply to this email directly or view it on GitHub https://github.com/cyborg5/IRLib/issues/1#issuecomment-122688366 . https://github.com/notifications/beacon/ADcgurubCCkYEagwadEuU10uIcD2de-8ks5oe9megaJpZM4AvMvZ.gif