NAME
Protocol::IR::Proto::NEC - NEC protocol handler (32-bit) and NEC-family base class
VERSION
version 0.08
SYNOPSIS
use Protocol::IR::Converter;
my $converter = Protocol::IR::Converter->new();
# From a raw 32-bit value or from parameters
my $code = $converter->import_code('NEC', '0x10EF00FF');
my $code = $converter->import_code('NEC',
{ address => 16, command => 0 });
DESCRIPTION
The NEC protocol family transmits 32-bit frames at 38 kHz. Each frame is four bytes -- address (device), subaddress, command, and the command's one's complement -- sent LSB-first, preceded by a header and followed by a stop mark. The data value matches Tasmota's Data field: address in bits 24-31, subaddress in bits 16-23, command in bits 8-15, and the inverted command in bits 0-7.
IRDB (via the MakeHex IRP files) distinguishes four single-frame formats:
NEC1(this class) -- full 9000/4500 us header, subaddress is the one's complement of the address (Default S=~D), short header+gap repeat.NEC2(Protocol::IR::Proto::NEC2) -- identical single-frame timing to NEC1; only the repeat differs (it re-transmits the whole frame).NECx1(Protocol::IR::Proto::NECX1) -- half 4500/4500 us header, subaddress is the low byte of a real 16-bit address (Default S=D), short repeat.NECx2(Protocol::IR::Proto::NECX2) -- identical single-frame timing to NECx1; whole-frame repeat.
Protocol::IR::Proto::NEC implements the shared machinery and doubles as the base class; the variants only override the header, the subaddress rule, and their protocol name. For a single frame NEC1 and NEC2 are timing-identical and so are NECx1 and NECx2, so a timing decode cannot tell the "1" and "2" forms apart -- the repeat structure is a property of the code's protocol name, not of any single frame.
When the subaddress equals the one's complement of the address (the normal case for standard NEC frames), subaddress is normalized to -1 on the resulting Protocol::IR::Code. NECx1/NECx2 never normalize: their subaddress byte is a real part of the 16-bit address.
Frame timing: header mark/space of 9024/4512 us (NEC1/NEC2, the IRP Prefix=16,-8 at a 564 us time base) or 4512/4512 us (NECx1/NECx2, Prefix=8,-8); each bit is a 562.5 us mark followed by a space of 562.5 us for 0 or 1687.5 us for 1. A 564 us stop mark and the inter-message space of ~44 ms (IRP Suffix=1,-78) end the frame, matching the MakeHex reference output for these IRPs.
The decode_timing decoder validates both the header and the stop bit, so a capture from an overlapping protocol (e.g. JVC, whose frame structure starts with a similar header) is rejected rather than misidentified.
METHODS
decode_raw
my $code = $class->decode_raw('0x10EF00FF');
Builds an Protocol::IR::Code from the raw 32-bit value.
decode_byte_order
my $code = $class->decode_byte_order($raw, $lsb);
Decodes from either byte order: $lsb true reads the accumulated (DataLSB) form directly; false reads the display (Data) form, the per-byte bit reversal of the accumulated word (the Tasmota Data field and the IRDB Code column). NEC sends each byte LSB-first, so the accumulated word is the one carried on the wire and by Tasmota's DataLSB.
lsb_is_accumulated
my $flag = $class->lsb_is_accumulated;
True (always, for NEC) when the accumulated byte order is what decode_raw reads, informing the Tasmota structured importer which of its Data/DataLSB fields to prefer.
decode_params
my $code = $class->decode_params(address => 16, command => 0);
Builds an Protocol::IR::Code from discrete parameters. Accepts address or device, subaddress or subdevice, and command or function.
decode_timing
my $code = $class->decode_timing(\@burst_pairs_us);
Decodes an arrayref of microsecond [mark_us, space_us] pairs. Returns an Protocol::IR::Code when the header, 32 data bits, and stop bit match the NEC timing signature, otherwise undef.
to_pronto
my $pronto = $class->to_pronto($ir_code);
Encodes an Protocol::IR::Code object as a Pronto Hex string at 38 kHz.
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.