diff options
| author | 2026-05-29 21:59:53 -0400 | |
|---|---|---|
| committer | 2026-05-29 22:04:38 -0400 | |
| commit | fe456c2014c8d1d88b7fd5b24ebda7f7b4c53460 (patch) | |
| tree | a1ae3682aede1ea7550f4be76a79118bd6502902 /src/uart.zig | |
| download | quail-fe456c2014c8d1d88b7fd5b24ebda7f7b4c53460.tar.gz quail-fe456c2014c8d1d88b7fd5b24ebda7f7b4c53460.zip | |
basic physical memory page allocator
Signed-off-by: Matthew Wozniak <me@woz.blue>
Diffstat (limited to 'src/uart.zig')
| -rw-r--r-- | src/uart.zig | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/uart.zig b/src/uart.zig new file mode 100644 index 0000000..661084c --- /dev/null +++ b/src/uart.zig @@ -0,0 +1,80 @@ +const std = @import("std"); + +var uart_ptr: ?[*]u8 = null; + +pub fn init(base_addr: usize) void { + uart_ptr = @ptrFromInt(base_addr); + // Set the word length to 8 bits. Offset 3 is the LCR (line control + // register). + // + // The bottom 2 bits set the word length: + // 0 = 5 bits + // 1 = 6 bits + // 2 = 7 bits + // 3 = 8 bits + const lcr: u8 = 3 << 0; + uart_ptr.?[3] = lcr; + // Now enable the FIFO, which is the bottom bit of the FIFO control + // register (offset 2) + uart_ptr.?[2] = 1 << 0; + // Enable receiver buffer interrupts, which is the bottom bit of the IER + // (interrupt enable register) + uart_ptr.?[1] = 1 << 0; + // Per the datasheet, we are to set the clock divisor to: + // divisor = ceil(clock_hz/(baud_sps * 16)) + // divisor = ceil(22_729_000/(115200 * 16)) = 13 + const divisor: u16 = 13; + const divisor_least: u8 = divisor & 0xff; + const divisor_most: u8 = divisor >> 8; + // To write the divisor, we have to open the divisor latch on bit 7 of the + // line control register. + uart_ptr.?[3] = lcr | 1 << 7; + // Now we write the divisor + uart_ptr.?[0] = divisor_least; + uart_ptr.?[1] = divisor_most; + // Now we lock it again + uart_ptr.?[3] = lcr; +} + +pub fn get() ?u8 { + if (uart_ptr.?[5] & 1 != 0) { + return uart_ptr.?[0]; + } else { + return null; + } +} + +pub fn put(c: u8) void { + uart_ptr.?[0] = c; +} + +fn drain(_: *std.Io.Writer, data: []const []const u8, splat: usize) !usize { + if (uart_ptr == null) return std.Io.Writer.Error.WriteFailed; + var written: u32 = 0; + for (data, 0..) |item, i| { + if (i == data.len - 1) { + for (0..splat) |_| for (item) |c| { + put(c); + written += 1; + }; + } else { + for (item) |c| { + put(c); + written += 1; + } + } + } + return written; +} + +pub var writer: std.Io.Writer = .{ + .buffer = &.{}, + .vtable = &.{ + .drain = drain, + }, +}; + +pub var terminal: std.Io.Terminal = .{ + .writer = &writer, + .mode = .escape_codes, +}; |
