For the revision history of this document, see the original document on the web site.
Release notes for the current version
The "IRP notation" is a domain specific language for describing IR protocols, i.e. ways of mapping a number of parameters to infrared signals. It is a very powerful, slightly cryptic, way of describing IR protocols. In early 2010, Graham Dixon (mathdon in the JP1-Forum) wrote a specification. Up until this program was released, there has not been a usable implementation of the IRP-notation in the sense of a program that takes an IRP Protocol together with parameter values, and produces an IR signal. (The MakeHex program operates on a previous, more restricted version of the IRP notation. The MakeLearned program has severe restrictions, most importantly, its sources are not available.) The present work is a Java program/library that is hoped to fill that gap. It is written in Java 1.6, may or may not run with Java 1.5, but definitely not with earlier Java versions. It, optionally, calls the shared library DecodeIR on Windows, Linux, or Macintosh, but has no other "impurities" in the sense of Java. It can be used as a command line program, or it can be used through its API. For parsing the IRP-Notation, the tool ANTLR is used, generating the parser automatically from the grammar.
This project does not contain a graphical user interface (GUI). See Main principles for a background. Instead, the accompanying program IrMaster provides a GUi for the present program, among many other things.
For understanding this document, and the program, a basic understanding of IR protocol is assumed. However, the program can be successfully used just by understanding that an "IRP protocol" is a "program" in a particular "domain specific language" for turning a number of parameters into an IR signal, and the present program is a compiler/interpreter of that language. Some parts of this document requires more IRP knowledge, however.
The mandatory section... :-; Preferred spelling is "IrpMaster", with "I" and "M" capitalized (just as the Java class). Pronounce it any way you like.
I hope that this program/library should be useful to other projects involved in IR signals. It makes the vast knowledge of the JP1 project available to other programs. It can be used off-line, to manually or automatically produce e.g. configuration files containing rendered IR signal in some popular format, like the Pronto format. More exciting is to implement a real time "IR engine", that can generate and transmit IR signals in any of the known formats.
The program, as well as this document, is copyright by myself. Of course, it is based upon the IRP documentation, but is to be considered original work. The "database file" IrpProtocols.ini is derived from DecodeIR.html, thus I do not claim copyright.
The program uses, or interfaces with (the different is slightly blurred), other projects. ExchangeIR was written by Graham Dixon and published under GPL3 license. Its Analyze-function has been translated to Java by myself, and is used in by the present program. DecodeIR was originally written by John S. Fine, with later contributions from others. It is free software with undetermined license. IrpMaster depends on the runtime functions of ANTLR3, which is free software with BSD type license.
The program and its documentation are licensed under the GNU General Public License version 3, making everyone free to use, study, improve, etc., under certain conditions.
It is my opinion that it is better to get the functionality and the API right, before you do a graphical user interface (GUI). It is much easier and logical to put a GUI on top of a sane API, then to try to extract API functionality from a program that was never designed sanely but built around the GUI. (Look at WinZip for a good example of the latter. Or almost any Windows program, commercial or freeware...)
I have tried to follow the IRP document as closely as possible, in particular with respect to the grammar and the syntax. However, the Execution model of Chapter 14, turned out not to be usable.
Performance consideration were given minimal priorities. As it stands,
rendering a single IR signal typically takes less than 1 ms, so this
seems justified. Some debugging statements are covered
by functionally superfluous if-statements in order not to have to
evaluate arguments (to String()
etc) not needed anyhow.
Everything that is a "time" is internally represented as a double precision number. Most output formats however, are in some integer format. I here use the principle of sound numerics, do all computations with "high precision" (i.e. double precision) as long as ever possible, then transform to the lower precision form (i.e. integer formats) only in the final step.
All "integer quantities" like expressions, are done in Java long format, 64 bits long, amounting to 63 bits plus sign. Already the metanec-example would not work with Java int's. The performance penalty over using "int" (32 bits) is believed to be neglectable.
Differenty put, all parameters are limited to Java's long, and can thus be no larger than 2^63-1 = 9223372036854775807. A real-life protocol where this limit is exceeded is not known to me.
Versions prior to 0.2.1 also limited the length of bitfields, also the
concatenation of bitfields, to 64. In version 0.2.1 this restriction has been
removed, and arbitrary length (concatenation of) bitfields are allowed, as long
as the parameters are less
than 2^63-1. (Example: The concatenation of bitfields A:50,B:50
produces a concatenated bitfield of length 100, which is accepted by IrpMaster
0.2.1, but
rejected by prior versions.) (Thanx to 3FG for pointing this out to me.)
I do not have the slightest interest in internationalization of the project in its present form — it does not contain a user friendly interface anyhow.
Possibly the major difficulty in turning the IRP Specification into programming code was how to make sense of the repetition concept. Most treatises on IR signals (for example the Pronto format) considers an IR signal as an introduction sequence (corresponding to pressing a button on a remote control once), followed by a repeating signal, corresponding to holding down a repeating button. Any, but not both of these may be empty. In a few relatively rare cases, there is also an ending sequence, send after a repeating button has been released. Probably 99% of all IR signals fit into the intro/repetition scheme, allowing ending sequence in addition should leave very few practically used IR signals left. In "abstract" IRP notation, these are of the form A,(B)+,C with A, B, and C being "bare irstreams".
In contrast, the IRP notation in this concept reminds they syntax and semantics of regular expressions: There may be any numbers, and they can even be hierarchical. There certainly does not appear to be a consensus on how this very,... general ... notation should be practically thought of as a generator of IR signals. The following, "finite-automaton interpretation" may make sense: An IRP with several repetitions, say, A(B)+C(D)+E, can be thought of as a remote control reacting on single and double presses. Pressing the key and holding it down produces first A, then B's as long as the button is pressed. An action such as shortly releasing the key and immediately pressing it again then sends one C, and keeps sending D's as long as button is kept pressed. When released, E is sent. Similarly, hierarchical repetitions (repetitions containing other repetitions) may be interpreted with some secondary "key" being pressed and/or released while a "primary button" is being held down — possibly like a shift/meta/control modifier key on a keyboard or a sustain/wahwah-pedal on a musical instrument?
The present program does not implement hierarchical repetitions. However, an unlimited number of non-hierarchical repetitions are allowed, although not in the form if the class IrSignal — it is restricted to having three parts (intro, repeat, ending). Also, the repetition pattern (...)* is rejected, because it does not make sense as an IR signal.
The command line interpreter contains an "interactive mode", entered by
the argument --interactive
. This way the intrinsic finite
state machine (see above) inherent in an IRP with repetitions can be
interactively traversed, probably in the context of debugging.
There is presently no separate binary distributions of IrpMaster. The user
who do
not want to compile the sources should therefore install the binary
distribution of IrMaster, which contains everything needed to run IrpMaster
from the command line. Installing that package, either the Windows installer or
the ZIP
file, will install a wrapper, which is the preferred way to invoke IrpMaster
(technically: indirectly through IrMaster.main()
). See the IrMaster documentation.
I will next describe how to invoke the program from the command line. Elementary knowledge of command line usage is assumed.
There is a lot of functionality crammed in the command line interface. The usage message of the program gives an extremely brief summary:
Usage: one of IrpMaster --help IrpMaster [--decodeir] [--analyze] [-c|--config <configfilename>] --version IrpMaster [OPTIONS] -n|--name <protocolname> [?] IrpMaster [OPTIONS] --dump <dumpfilename> [-n|--name <protocolname>] IrpMaster [OPTIONS] [--ccf] <CCF-SIGNAL> IrpMaster [OPTIONS] [-n|--name] <protocolname> [PARAMETERASSIGNMENT] IrpMaster [OPTIONS] [-i|--irp] <IRP-Protocol> [PARAMETERASSIGNMENT] where OPTIONS=--stringtree <filename>,--dot <dotfilename>,--xmlprotocol <xmlprotocolfilename>, -c|--config <configfile>,-d|--debug <debugcode>|?,-s|--seed <seed>,-q|--quiet, -P|--pass <intro|repeat|ending|all>,--interactive,--decodeir,--analyze,--lirc <lircfilename>, -o|--outfile <outputfilename>, -x|--xml, -I|--ict, -r|--raw, -p|--pronto, -u|--uei, --disregard-repeat-mins, -#|--repetitions <number_repetitions>. Any filename can be given as `-', meaning stdin or stdout. PARAMETERASSIGNMENT is one or more expressions like `name=value' (without spaces!). One value without name defaults to `F`, two values defaults to `D` and `F`, three values defaults to `D`, `S`, and `F`, four values to `D`, `S`, `F', and `T`, in the order given. All integer values are nonnegative and can be given in base 10, 16 (prefix `0x'), 8 (leading 0), or 2 (prefix `0b' or `%'). They must be less or equal to 2^63-1 = 9223372036854775807. All parameter assignment, both with explicit name and without, can be given as intervals, like `0..255' or '0:255', causing the program to generate all signals within the interval. Also * can be used for parameter intervals, in which case min and max are taken from the parameterspecs in the (extended) IRP notation.
Note that if using the wrapper previously described, it has already added the
option --config
standard_confile
to the
commandline.
We will next explain this very brief description somewhat more verbosely:
--version
argument should normally be
given last, since it is executed immediately when
the command line is parsed.--dump
option (use -
for standard output).-n
or --name
option), to be found in the data base/configuration file
specified by the -c
or --config
option, that
protocol is used to render an IR signal or sequence using the supplied
parameters (more on that later).-i
or --irp
-option, to be used to render
the signal according to the parameters given.
In the simplest and most general form, parameter assignments are made
on the command line in one argument of the type name=value
. On both sides of the
"="-signs, there should not be any spaces. (More precisely, it is
required that all assignments are made within a single "argument" to
the program, which is determined by the command line interpreter. Thus
writing the arguments within single or double quotes, extra spaces can
be parsed.) After named parameters are given (possibly none), up to
four "standard" parameters can be given. These are, in order D, S, F,
and T (which per convention in the JP1 community stands for
"Device", "Subdevice", "Function" (also called OBC or command number),
and "Toggle"). If using -1 as the value, that parameter is considered
as not being assigned. One value without name defaults to `F',
two values defaults to `D' and `F', three values defaults to `D', `S',
and `F', and four to `D', `S', `F', and `T', in the order given.
For example,
E=12 34 -1 56 1
assigns the value 12 to E, the value 34 to D, the value of 56 to F, and 1 to T, while S is not assigned anything at all. Parameters can be given not only in decimal notation, but also as hexadecimal (using prefix 0x) binary (using prefix 0b or %), or octal (using prefix 0).
If the command line cannot be parsed the usage message will be printed.
If you are unsure of exactly what is wrong, consider issuing "-d
1
" (the debug option with argument 1) as the first argument on
the command line, which may produce more verbose error messages.
Using the -r
or --raw
option, the output is
given in "raw form" (in JP1-Forum jargon, this is a sequence of
positive numbers (indicating "flashes", or on-times in micro seconds)
and negative numbers (indicating "gaps" or off-times, where the
absolute value indicates the duration in micro seconds. Carrier
frequency is specified separately). Alternatively, or additionally,
using the -p
or --pronto
option, output is
produced in the so-called Pronto format, see e.g. this
document. This format is popular in several IR using internet
communities, like Promixis
(known for their (commercial) products Girder and NetRemote), as well
as EventGhost. Optionally,
these can be wrapped into an XML skeleton, offering an ideal platform
for translating to every other IR format this planet has encountered.
If desired, the output of the program is directed to a particular named
file using the -o
filename
or --output
filename
option. (There is also a possibility (using the --ict
or
-I
option) to generate output files in IRScope's
ict-format, but I am not sure this was as wise design decision: it
may be a better idea to generate additional formats by post-processing
the XML file.)
Motivated by this thread
in the JP1 forum, I have been thinking over the "correct" way to render signals
of this type ... (...)+
. This is a real issue,
to determine the correct behavior when e.g. a program is sent the instruction
"send the signal one time", and not an academic question like "keypress
shorter than 6ms" or debouncing circuitry.
The Pronto notation is normally described as "intro part exactly once,
repetition part if and as long as the button is held down". I.e., zero or more
times. Therfore, IMHO, the IRP I (R)+
should properly be rendered
as having intro sequence I R
, which is what IrpMaster normally
does. However, in a sense, this can be considered as ugly, awkward, and
redundant. If I
recall properly, there is a flag in the LIRC configuration called something like
"send_repeat_least_once", which should be exactly what we need.
The option called --disregard-repeat-mins
will make IrpMaster
render the intro sequence without repetition part, also in the
... (...)+
case.
Either for generating configuration files for other programs, or for testing, there is a very advanced feature for looping over input parameter sets. For all of the parameters to a protocol, instead of a single value, a set can be given. The program then computes all IR signals/sequences belonging to the Cartesian product of the input parameter sets. There are five types of parameter sets:
min..max++increment
or
min:max++increment
, or alternatively, simply as *, which will get
the min and max values from the parameter's parameter specs. a:b<<c
,
which has the following semantics: starting with a
, this
is shifted to the left by c
bits, until b
has been exceeded (reminding of the left-shift operator <<
found in languages such as C).a:b#c
generates c pseudo random numbers between a and b
(inclusive). The "pseudo random" numbers are completely
deterministically determined from the seed, optionally given with the
--seed
option. As of version 0.2.2 a
and
b>
are optional. If left out, the values are taken as from the protocol parameters min
and max respectivelly, just as with the *
form.
See the test file test.sh
(include in the distributions) for some examples.
Of course, using the command line, some of the involved characters,
most notably the *, has a meaning to the command line interpreter and
may need "escaping" by a backslash character, or double or single
quotes.
There is also an option, denoted -#
or --repetitions
taking an integer argument, that will compute that many "copies"
of the IR signal or sequence. This may be of interest for signals that
are non-constant (toggles being the simplest example) or for profiling
the program.
There are a number of different debug parameters available. Use -d
or --debug
with "?" as argument for a listing:
$ java -jar IrpMaster.jar --debug ? Debug options: Main=1, Configfile=2, IrpParser=4, ASTParser=8, NameEngine=16, BitFields=32, Parameters=64, Expressions=128, IrSignals=256, IrStreamItems=512, BitSpec=1024, DecodeIR=2048, IrStreams=4096, BitStream=8192, Evaluate=16384
For every debug option, there is an integer of the form 2^n associated
with it. Just add the desired numbers together and use as argument for
the -d
or --debug
command. There are also
commands for debugging the parsed version of the IRP: Notably the
--stringtree
filename
option (produces a LISP-like parsed
representation of the so-called AST (abstract syntax tree)).
--dot
filename
produces a dot-file, that can be translated by the open-source program dot
contained in the Graphviz project, producing a nice picture (e.g. in
any common bitmap format) of the current IRP protocol, and
--xmlprotocol
filename
producing an XML representation. It may be possible in the future to
use any of these representations to e.g., write a C code generator for
a particular protocol.
Some of the classes contain their own main methods (for those not familiar with the Java jargon: these can be called as programs on their own) allowing for both debugging and pedagogical exploration, together possibly with other possibilities. In particular, this goes for the Expression class, One day I am going to document this...
java -classpath IrpMaster.jar org.harctoolbox.IrpMaster.Expression -d 'a + b *c**#d' {a=12,b=34,c=56,d=4} (+ a (* b (** c (BITCOUNT d)))) 1916
For the DecodeIR-integration, IrpMaster requires a small support
package, DecodeIR.jar, which is distributed together with IrpMaster. It
consists of the compiled DecodeIRCaller.java
from DecodeIR (full
name
com.hifiremote.decodeir.DecodeIRCaller.class
), and
com.hifiremote.LibraryLoader.class
from RemoteMaster, which is
also free software. To get rid of some (in this context)
annoying messages, it was necessary to create a (very) lightly modified
version, which can be found on the download page. IrpMaster also requires the runtime libraries of the
parser generator ANTLR, which
is also free software but licensed under a BSD-License. I
distribute the whole (binary) package antlr-3.4-complete.jar
. (No
usable "runtime version" is known to me.)
In the first, now obsolete, version of the IRP notation the parameters
of a protocol had to be declared with the allowed max- and min-value. I
have reinvented this, using the name parameter_spec. For example, the
well known NEC1 protocol, the Parameter Spec reads:
[D:0..255,S:0..255=255-D,F:0..255]
. (D, S, and F have the
semantics of device, sub-device, and function or
command number.) This defines the three variables D, S, and F, having
the allowed domain the integers between 0 and 255. D and F must be
given, however, S has a default value that is used if the user does not
supply a value. The software requires that the values without default
values are actually given, and within the stated limits. If, and only
if, the parameter specs is incomplete, there may occur run-time errors
concerning not assigned values. It is the duty of the IRP author to
ensure that all variables that are referenced within the main
body of the IRP are defined either within the parameter specs, defined
with "definitions" (Chapter 10 of the specification), or assigned in
assignments before usage, otherwise a run-time error will occur
(technically an UnassignedException
will be thrown).
The preferred ordering of the parameters is: D, S (if present), F, T (if present), then the rest in alphabetical order,
The formal syntax is as follows, where the meaning of the '@' will be explained in the following section:
parameter_specs: '[' parameter_spec (',' parameter_spec )* ']' | '[' ']' parameter_spec: name ':' number '.' '.' h=number ('=' i=bare_expression)? | name '@' ':' number '.' '.' number '=' bare_expression
For the implementation, I allow the four parts (three in the original specification) to be given in any order, if at all, but I do not disallow multiple occurrences — it is quite hard to implement cleanly and simply not worth it. (For example, ANTLR does not implement exclusions. The only language/grammar I know with that property is SGML, which is probably one of the reasons why it was considered so difficult (in comparison to XML) to write a complete parser.)
Graham, in the specification and in following forum contributions,
appears to consider all variables in a IRP description as intrinsically
persistent: They do not need explicit initialization, if they are not,
they are initialized to an undefined, random value. This may be a
reasonable model for a particular physical remote control, however,
from a scientific standpoint it is less attractive. I have a way of
denoting a variable, typically a toggle of some sort, as persistent by
appending an "@" to its name in the parameter specs. An initial value
(with syntax as default value) is here mandatory. It is set to its
initial value by the constructor of the Protocol class. Calling the
renderIrSignal(...) function or such of the Protocol instance typically
updates the value (as given in an assignment, a 0-1 toggle goes like
T=1-T). As opposed to variables that has not been declared as
persistent, it (normally) retains its value between the invocations of
renderIrSignal(...). A toggle is typically declared as [T@:0..1=0]
in the parameter specs.
Comments in the C syntax (starting with /*
and ended by
*/
) are allowed and ignored. Line breaks can be embedded within an
IRP string by "escaping" the line break by a backslash
The IRP documentation clearly states that the carrier frequency is a real number, while everything else is integers. Unfortunately, users of the IRP notation, for example in the DecodeIR.html document, has freely used decimal, non-integer numbers. I have implemented the following convention: Everything that has a unit (second or Hz), durations and frequency, are real numbers (in the code double precision numbers).
The specification writes ``An extent has a scope which consists of a consecutive range of items that immediately precede the extent in the order of transmission in the signal. ... The precise scope of an extent has to be defined in the context in which it is used.'', and, to my best knowledge, nothing more. I consider it as specification hole. I have, starting with IrpMaster 0.2.2, implemented the following: Every extend encountered resets the duration count.
It turned out that the preprocessing/inheritance concept necessitated allowing several definition objects. These are simply evaluated in the order they are encountered, possibly overwriting previous content.
Previous programs (makehex, makelearned) have only allowed one-letter names. However, in DecodeIR.html there are some multi-letter names. The IRP documentation allows multi-letter names, using only capital letters. I have, admittedly somewhat arbitrarily, extended it to the C-name syntax: Letters (both upper and lower cases) and digits allowed, starting with letter. Underscore "_" counts as letter. Case is significant.
Also there are a few predefined, read-only variables, mainly for
debugging, although a practical use is not excluded. To distinguish
from the normal, and not to cause name collision, they start by a dollar
sign. Presently, these are: $count
(numbers the
call to a render*-()
-function, after the constructor has
been called), $pass
(Requested pass in a
--pass
-argument, (or from API call), not to be confused with the
following), $state
(current state (intro=0, repeat=1, ending=2,...) of parsing of an IRP),
$final_state
(undefined until the final state has been
reached, then the number of the final state). For example, the OrtekMCE
example
{...}<...>([P=0][P=1][P=2],4,-1,D:5,P:2,F:6,C:4,-48m)+[...]
could be written with $state
as
(4,-1,D:5,$state:2,F:6,C:4,-48m)+
(disregarding last frame).
Without any very good reason, I allow a duty cycle in percent to be
given within the GeneralSpec, for example as {37k,123,msb,33%}
.
It is currently not used for anything, but preserved through the processing and
can be retrieved using API-functions. If some, possibly future, hardware needs
it, it is there.
There is a difference in between the IRP documentation and the
implementation of the Makehex program, in that the former has one name
space for both assignments and definitions, while the
latter has two different name spaces. IrpMaster has one name space, as
in the documentation. (This is implemented with the NameEngine
class.)
It has sometimes been suggested (see this thread) to introduce the shift operators "<<" and ">>" with syntax and semantics as in C. This far, I have not done so, but I estimate that it would be a very simple addition. (The reader might like to have a look at my example, which possibly would have been more naturally expressed with left shifts than with multiplication with powers of two.)
In particular in the light of current
discussion on the F12 protocol, in my opinion more useful would be
the logical operators &&, ||
, and ?:
, having
their short circuiting semantics, like in languages such as C, Perl,..., but
unless, e.g. Pascal. Recall, the expression A && B
is evaluated as follows: First A
is checked for being 0 or
not. If 0, then 0 is returned, without even evaluating B
. If
however, A
is nonzero, B
is evaluated, possibly to a
"funny" type and is returned. The F12 protocol (cf. the latest version 2.43 of
DecodeIR.html) could then probably be
written like <...>(introsequence, (H &&
repetitionsequence*))
or <...>(H ? longsequence+ :
shortsequence)
.
Generally, I think you should be very reluctant to add "nice features"
to something like IRP. However, in the applications in DecodeIR.html,
the phrase "number of ones", often modulo 2 ("parity"), occurs
frequently in the more complicated protocols. This is awkward and
error prone to implement using expressions, for example: F:1 + F:1:1 +
F:1:2 + F:1:3 + F:1:4 + F:1:5 + F:1:6 + F:1:7
. Instead, I have introduced the BitCount function, denoted by "#". Thus, odd parity of F
will be #F%1
, even parity 1-#F%2
. It is
implemented by translating to the Java Long.bitCount-function.
Reading through the protocols in DecodeIR.html, the reader is struck by the observation that there are a few general abstract "families", and many concrete protocol are "special cases". For example all the variants of the NEC* protocols, the Kaseikyo-protocols, or the rc6-families. Would it not be elegant, theoretically as well as practically, to be able to express this, for example as a kind of inheritance, or sub-classing?
For a problem like this, it is easily suggested to invoke a general purpose macro preprocessor, like the C preprocessor or m4. I have successfully resisted that temptation, and am instead offering the following solution: If the IRP notation does not start with "{" (as they all have to do to confirm with the specification), the string up until the first "{" is taken as an "ancestor protocol", that has hopefully been defined at some other place in the configuration file. Its name is replaced by its IRP string, with a possible parameter spec removed — parameter specs are not sensible to inherit. The process is then repeated up until, currently, 5 times.
The preprocessing takes place in the class IrpMaster, in its role as data base manager for IRP protocols.
This shows excepts from a virtual configuration file. Let
us define the "abstract" protocol metanec
by
[protocol] name=metanec irp={38.4k,564}<1,-1|1,-3>(16,-8,A:32,1,-78,(16,-4,1,-173)*)[A:0..4294967295]
having an unspecified 32 bit payload, to be subdivided by its "inherited protocols". Now we can define, for example, the NEC1 protocol as
[protocol] name=NEC1 irp=metanec{A = D | 2**8*S | 2**16*F | 2**24*(~F:8)}[D:0..255,S:0..255=255-D,F:0..255]
As can be seen, this definition does nothing else than to stuff the
unstructured payload with D, S, and F, and to supply a corresponding
parameter spec. The IrpMaster class replaces "metanec
"
by {38.4k,564}<1,-1|1,-3>(16,-8,A:32,1,-78,(16,-4,1,-173)*)
"
(note that the parameter spec was stripped), resulting in an IRP string
corresponding to the familiar NEC1 protocol. Also, the "Apple protocol"
can now be formulated as
[protocol] name=Apple irp=metanec{A=D | 2**8*S | 2**16*C:1 | 2**17*F | 2**24*PairID} \ {C=1-(#F+#PairID)%2,S=135} \ [D:0..255=238,F:0..127,PairID:0..255]
The design is not cast in iron, and I am open to suggestions for improvements. For example, it seems reasonable that protocols that only differ in carrier frequency should be possible to express in a concise manner.
There is presently not a "official" IRP database. MakeHex
comes with a number of protocol files with the .irp
-extension,
but that is another, obsolete and much less powerful format. MakeLeaned also comes with a number of
"irp-files", in the new format, but incomplete. The DecodeIR.html-file presently comes closest:
it has a number (upper two-digit) of IRPs, however, often not even
syntactically confirming to the specification, and often
with the description of the protocol at least partially in prose ("C
is the number of ..."), parseable only by humans, not by programs.
Possibly as an intermediate solution, I invented the
IrpProtocols.ini
file. This file
has a format similar to ini-files under Windows. For every protocol, it
contains name and an IRP-string, possibly also a documentation string.
The latter can, in principle, contain HTML elements, i.e. it can be an
HTML fragment.
Every protocol is described in a section starting with the key
[protocol]
. Then there are a few keywords describing different
properties:
name
The name of the protocol. This is folded to lowercase
for searches and comparisons. irp
The IRP string representation. This may continue over
several lines if the line feeds are escaped by a backslash ("\"), i.e. having
the backspace as last character on the line.
Other keywords are allowed, but ignored. Then, optionally, there may be
a section [documentation]
, that, in principle, could contain
e.g. an HTML-fragment. The documentation section continues until the next
[protocol]
is encountered.
I have created the present IrpProtocols.ini
by hand editing the
DecodeIR.html-file.
I would welcome if the community can settle for one endorsed format for
such a data base. It can be one file, or many files: One file per
protocol is easier for the developer, in particular if several
developers are using a version management system (with or without file
locking), but less convenient for the user.
It would be highly desirable in the future to be able just to maintain one file (or set of files). Some possibilities for this are:
protocol.ini
("belonging to RemoteMaster")
with the IRP information. Leaves the problem of duplicated
"documentation" between DecodeIR.html and protocols.ini.
Optionally (when installed and selected with the --decodeir
option) the computed IR signal is sent to DecodeIR, to check DecodeIR's
opinion on the nature of the signal. This gives a magnificent
possibility for automated tests, not only of the present program, but also of
DecodeIR. Note in particular that there are very advance possibilities
for testing not only a single signal, but for testing whole ranges of
signals, a list of signals, "random" inputs, equidistant inputs, or
inputs achieved by shifting, see the section on parameter iterating.
The shared library is sought first in architecture dependent
sub-directories, like in RemoteMaster, .\windows
on
Windows, ./Linux-amd64
and ./Linux-i386
on 64- and 32-bit Linux respectively, etc, then in system
libraries, for example given on the command line to the Java VM,
using the -Djava.library.path=
option.
There is some fairly hairy programming in DecodeIR.java
for identifying some different cases.
The enclosed script test.sh
runs under a Unix/Linux shell such as bash
or sh. It should also run within Cygwin
on Windows. It does not run with the standard Windows command line
interpreter. Note that it might need some adjustment of file paths etc.
Possibly because I did not find any more logical way to dispose it, the current distribution contains a class (with main()-method) named EvaluateLog that can be used to evaluate the output of the above script. Use like
java -classpath IrpMaster.jar IrpMaster/EvaluateLog protocols.log
The Java programmer can access the functionality through a number of API functions.
The class IrpMaster
is the data base manager. The class
is immutable, constructed from a file name (or an InputStream), and can
deliver assorted pieces of information from the data base. Most
interesting is the newProtocol()
-function that generates
a Protocol-object from parsing the IRP-string associated with the
requested protocol name. It contains a very elaborate
main()
-function for command line use -- strictly speaking
this is "the program" that is described herein. Actually, that
main()
-function does not necessarily belong to the IrpMaster
class, but could be located
somewhere else.
Instances of the Protocol class are constructed (essentially) from a
String, containing the IRP representation to be parsed. Once
constructed (and IRP-String parsed), the Protocol instances can render
IrSignals and IrSequences for many different parameter values. This is
done with the render(...)
and renderIrSignal(...)
functions, producing IrSequences
and IrSignals
respectively:
An IrSequence
is a sequence of pulse pairs. It does not know
weather it is supposed to repeat or not. In contrast, an IrSignal
has one introductory IrSequence
, one repetition
IrSequence
(either, but not both, of these can be empty), and an
(in most cases empty) ending IrSequence
.
The API is documented in standard Javadoc style, which can be installed from the source package, just like any other Java package. For the convenience of the reader, the javadoc API documentation is also available here.
A final note, this program is in its first stage, thus I may no promise not to change the API in the future, or even to maintain backwards compatibility.
The task is to write a command line program, taking, in order, the configuration file name, a protocol name, a device number and a function/command/obc number, and send the corresponding IR signal to a GlobalCaché GC-100-06 networked IR-transmitter, having IP address 192.168.1.70, using its IR Port 1. For this, we use the GlobalCaché functionality of the Harctoolbox, which is also GPL-software written by myself. This task is solved with essentially just a few lines of code.