sw-uart.zig (1644B)
1 const std = @import("std"); 2 3 const interrupts = @import("../interrupts.zig"); 4 const mem = @import("../mem.zig"); 5 6 const clock = @import("./clock.zig"); 7 const gpio = @import("./gpio.zig"); 8 const pi = @import("../root.zig"); 9 10 pub const Error = error{ AlreadyInitialized, NotInitialized, InvalidBaud } || gpio.Error; 11 12 var initialized = false; 13 var interrupts_enabled = false; 14 15 pub var delay: u32 = undefined; 16 var tx: u8 = undefined; 17 var rx: u8 = undefined; 18 19 pub fn initialize(baud: u32, tx_pin: u8, rx_pin: u8) Error!void { 20 if (initialized) return Error.AlreadyInitialized; 21 22 try gpio.fn_sel(tx_pin, .output); 23 // try gpio.set_pull(tx_pin, .Up); 24 tx = tx_pin; 25 26 try gpio.fn_sel(rx_pin, .input); 27 // try gpio.set_pull(rx_pin, .Up); 28 rx = rx_pin; 29 30 try gpio.set_on(tx_pin); 31 32 mem.barrier(.Write); 33 34 // Cycles to delay 35 delay = (@divFloor(700_000_000, baud)); 36 if (delay == 0) return Error.InvalidBaud; 37 38 initialized = true; 39 } 40 41 pub fn write_byte(byte: u8) !void { 42 if (!initialized) return Error.NotInitialized; 43 44 gpio.set_off(tx) catch {}; 45 mem.barrier(.Write); 46 47 var deadline = pi.cycle_counter_read() + delay; 48 pi.cycle_wait_until(deadline); 49 50 for (0..8) |n| { 51 const state = (byte & (@as(u8, 1) << @truncate(n))) != 0; 52 gpio.write(tx, state) catch {}; 53 mem.barrier(.Write); 54 55 deadline += delay; 56 pi.cycle_wait_until(deadline); 57 } 58 59 gpio.set_on(tx) catch {}; 60 mem.barrier(.Write); 61 62 deadline += delay; 63 pi.cycle_wait_until(deadline); 64 } 65 66 pub fn write_slice(bytes: []const u8) !void { 67 for (bytes) |b| { 68 try write_byte(b); 69 } 70 }