IR is a library for parsing and generating NEC IR remote control signals.
Process the IR signal by calculating the time, in microseconds, between each rising/falling and falling/rising edge in the signal (pulses in the example below). If put() returns true, then a full packet has been received.
var nec = ir.NEC{};
for (pulses, 0..) |_, i| {
76A3
if (nec.put(pulses[i])) {
break;
}
}
const msg = try nec.value();
std.log.debug("address: 0x{x}, command: 0x{x}", .{msg.address, msg.command});Generate an IR packet:
var nec = ir.NEC{};
var packet: [66]u32 = undefined;
nec.generate(message{ .address = 0x16, .command = 0x04 }, &pulses);Example of sending the IR packet with pico and zig
const std = @import("std");
const microzig = @import("microzig");
const ir = @import("ir");
const rp2040 = microzig.hal;
const rptime = rp2040.time;
const gpio = rp2040.gpio;
const pwm = rp2040.pwm;
const pin_config = rp2040.pins.GlobalConfiguration{
.GPIO16 = .{ .name = "gpio16", .function = .PWM0_A },
.GPIO25 = .{ .name = "led", .direction = .out },
};
const pins = pin_config.pins();
pub fn main() !void {
pin_config.apply();
// For 38kHz:
// System clock is 125MHz
// PWM frequency = 125MHz / (DIV * (WRAP + 1))
// For 38kHz: 125000000 / 38000 ≈ 3289.47
// Using DIV=1.0, WRAP=3288 gives ~38.02kHz
const div_int: u8 = 1;
const div_frac: u8 = 0;
const top: u16 = 3288;
const slice = pins.gpio16.slice();
slice.set_clk_div(div_int, div_frac);
slice.set_wrap(top);
pins.gpio16.set_level(top / 2); // 50% duty cycle
var packet: [67]u32 = undefined;
var nec = ir.NEC{};
nec.generate(ir.message{ .address = 0x04, .command = 0x08 }, &packet);
var toggle: u16 = 0;
while (true) {
slice.enable();
pins.led.toggle();
for (packet) |duration| {
toggle = 1 - toggle;
pins.gpio16.set_level((top / 2) * toggle);
rptime.sleep_us(duration);
}
slice.disable();
rptime.sleep_ms(5000);
}
}