Created
March 13, 2025 12:05
-
-
Save patryk4815/fd30d518aa8f79c11d07bc4381823250 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const microzig = @import("microzig"); | |
const rp2xxx = microzig.hal; | |
const gpio = rp2xxx.gpio; | |
const time = rp2xxx.time; | |
const Pio = rp2xxx.pio.Pio; | |
const StateMachine = rp2xxx.pio.StateMachine; | |
const manchester_tx = blk: { | |
@setEvalBranchQuota(8000); | |
break :blk rp2xxx.pio.assemble( | |
\\.program manchester_tx | |
\\.side_set 1 opt | |
\\ | |
\\; Transmit one bit every 12 cycles. a '0' is encoded as a high-low sequence | |
\\; (each part lasting half a bit period, or 6 cycles) and a '1' is encoded as a | |
\\; low-high sequence. | |
\\; | |
\\; Side-set bit 0 must be mapped to the GPIO used for TX. | |
\\; Autopull must be enabled -- this program does not care about the threshold. | |
\\; The program starts at the public label 'start'. | |
\\ | |
\\.wrap_target | |
\\do_1: | |
\\ nop side 1 [5] ; Low for 6 cycles (5 delay, +1 for nop) | |
\\ jmp get_bit side 0 [3] ; High for 4 cycles. 'get_bit' takes another 2 cycles | |
\\do_0: | |
\\ nop side 0 [5] ; Output high for 6 cycles | |
\\ nop side 1 [3] ; Output low for 4 cycles | |
\\public start: | |
\\get_bit: | |
\\ out x, 1 ; Always shift out one bit from OSR to X, so we can | |
\\ jmp !x do_0 ; branch on it. Autopull refills the OSR when empty. | |
\\.wrap | |
, .{}).get_program_by_name("manchester_tx"); | |
}; | |
// Pick one PIO instance arbitrarily. We're also arbitrarily picking state | |
// machine 0 on this PIO instance (the state machines are numbered 0 to 3 | |
// inclusive). | |
const pio: Pio = rp2xxx.pio.num(0); | |
const sm: StateMachine = .sm0; | |
const DOUT_NEW = gpio.num(5); | |
pub fn manchester_tx_program_init() void { | |
pio.gpio_init(DOUT_NEW); | |
// This method is provided as a convenience to set initial pin states, and should not be used against a state machine that is enabled. | |
// * Note: This method only works for pins < 32. To use with pins >= 32 call pio_sm_set_pins_with_mask64 | |
// uint32_t pin_values, uint32_t pin_mask | |
// pio_sm_set_pins_with_mask(pio, sm, 0, 1u << pin); | |
pio.sm_set_pin(sm, 5, 1, 1); | |
// uint pins_base, uint pin_count, bool is_out | |
// pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); | |
pio.sm_set_pindir(sm, 5, 1, .out); | |
// T0...Carrier period time (1/125 kHz = 8 µs nominal). | |
// calc from_float: (150_000_000 / 125_000) * (32 / 12) | |
// rfid_bit_length = 32; // 256us = 1bit | |
// program_tx = 12 cycles = 1bit | |
pio.sm_load_and_start_program(sm, manchester_tx, .{ | |
.clkdiv = rp2xxx.pio.ClkDivOptions.from_float(3200), | |
// sm_config_set_out_shift(&c, (shift_right)true, (autopull)true, (pull_threshold)32); | |
// sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); | |
.shift = .{ | |
.out_shiftdir = .right, | |
.autopull = true, | |
.pull_threshold = 0, // 0 means full 32-bits | |
.join_tx = true, | |
}, | |
// sm_config_set_sideset_pins(&c, pin); | |
.pin_mappings = .{ | |
.side_set = .{ | |
.base = 5, | |
.count = 2, | |
} | |
}, | |
}) catch unreachable; | |
pio.sm_set_enabled(sm, true); | |
const em4100_part1: u32 = 0b111111111_1110_1_0100_0_0000_0_0001_1_110; | |
const em4100_part2: u32 = 0b1_0_1010_1_1000_1_0100_1_1101_0_1101_1_0000_0; | |
while (true) { | |
pio.sm_blocking_write(sm, @bitReverse(em4100_part1)); | |
pio.sm_blocking_write(sm, @bitReverse(em4100_part2)); | |
time.sleep_ms(50); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment