summaryrefslogtreecommitdiff
path: root/src/uart.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/uart.zig')
-rw-r--r--src/uart.zig80
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,
+};