NAME

Protocol::IR::Format::Pronto - Raw Pronto Hex encoder and decoder

VERSION

version 1.2

SYNOPSIS

use Protocol::IR::Converter;

my $converter = Protocol::IR::Converter->new();
my $code = $converter->import_code('NEC', '0x10EF00FF');

# Encode an Protocol::IR::Code object as Pronto Hex
my $pronto = $converter->export_code($code, 'Pronto');

# Decode Pronto Hex back into an Protocol::IR::Code
my $decoded = $converter->import_format('Pronto', $pronto);

DESCRIPTION

Protocol::IR::Format::Pronto encodes Protocol::IR::Code objects into Pronto Hex strings and decodes Pronto Hex back into Protocol::IR::Code objects. Only the raw form (header 0000) is supported.

Example Pronto Hex (a 32-bit NEC transmission)
0000 006D 0022 0000 0157 00AC 0015 0015 0015 0015 0015 0015 0015 0015 \
0015 0040 0015 0015 0015 0015 0015 0015 0015 0040 0015 0040 0015 0040 \
0015 0040 0015 0015 0015 0040 0015 0040 0015 0040 0015 0015 0015 0015 \
0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0040 \
0015 0040 0015 0040 0015 0040 0015 0040 0015 0040 0015 0040 0015 0040 \
0015 0689

The fields are the raw-format marker (0000), the carrier frequency word (006D), the burst-pair counts for the one-time and repeat sequences (0022 0000), then that many mark/space pulse-count pairs, the final value being the trailing stop bit. See the IR Scrutinizer glossary for the full field layout (http://www.harctoolbox.org/Glossary.html).

The carrier frequency word is stored in the frequency field and converted to a period in microseconds: the pulse count stored for each mark/space is the duration in carrier cycles, so the actual duration depends on the transmitter's carrier frequency. Protocol encoders emit frequency words for their nominal carrier (typically 38 kHz) and pulse counts quantized to that carrier, so the decoded microsecond timings round-trip cleanly.

Because decoding works from the microsecond timing signature (see "DECODING VERSUS GENERATING TIMINGS" in Protocol::IR::Converter), a Pronto string is only recognized if it matches a registered protocol. Whether or not it does, the decoded Protocol::IR::Code keeps the exact capture -- the quantized timings and the hex stashed verbatim in pronto -- so export (and any Pronto-passthrough container such as wig or the JSON dump importer) round-trips the string byte-identically. A well-formed string with real timing data that no protocol recognizes is not an error: it decodes to an opaque UNKNOWN code (bypass_protocol set) so container conversions that move Pronto hex can still complete. Truncated or empty payloads are still rejected.

  • pronto is set on every Pronto decode, so export re-emits the original string rather than re-quantizing through the protocol encoder.

  • timings is set on every Pronto decode, so the same microsecond waveform feeds the other timing formats (Tasmota, mode2, LIRC) losslessly.

METHODS

export

my $pronto = $class->export($ir_code, $registry);

Converts a single Protocol::IR::Code object into a Pronto Hex string. When the code was itself decoded from Pronto Hex, its stashed pronto string is re-emitted verbatim. Otherwise the registered protocol handler for the code's protocol encodes it from its decoded fields (to_pronto).

decode

my $code = $class->decode($pronto_str, $registry);

Parses a Pronto Hex string into microsecond mark/space pairs and tries each registered protocol's decode_timing in registration order. Returns the first matching Protocol::IR::Code, or dies if the string cannot be decoded.

decode is named decode rather than import to avoid clashing with Perl's module import hook.

SUPPORT

Source code: https://github.com/bwarden/perl-protocol-ir

Bug reports and feature requests: https://github.com/bwarden/perl-protocol-ir/issues

AUTHOR

Brett T. Warden <bwarden@cpan.org>

COPYRIGHT AND LICENSE

Copyright (c) 2026 Brett T. Warden

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation.