diff --git a/src/modules/chips/atmega328p/atmega328p.zig b/src/modules/chips/atmega328p/atmega328p.zig index 3e6b978..7192049 100644 --- a/src/modules/chips/atmega328p/atmega328p.zig +++ b/src/modules/chips/atmega328p/atmega328p.zig @@ -8,8 +8,14 @@ pub const memory_regions = [_]micro_linker.MemoryRegion{ micro_linker.MemoryRegion{ .offset = 0x800100, .length = 2048, .kind = .ram }, }; +const Port = enum(u8) { + B = 1, + C = 2, + D = 3, +}; + pub fn parsePin(comptime spec: []const u8) type { - const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}.{Pin}\" scheme."; + const invalid_format_msg = "The given pin '" ++ spec ++ "' has an invalid format. Pins must follow the format \"P{Port}{Pin}\" scheme."; if (spec.len != 3) @compileError(invalid_format_msg); @@ -17,31 +23,41 @@ pub fn parsePin(comptime spec: []const u8) type { @compileError(invalid_format_msg); return struct { - pub const port: u8 = std.ascii.toUpper(spec[1]) - 'A'; - pub const pin: u3 = @intCast(u3, spec[2] - '0'); + pub const port: Port = std.meta.stringToEnum(Port, spec[1..2]) orelse @compileError(invalid_format_msg); + pub const pin: u3 = std.fmt.parseInt(u3, spec[2..3], 10) catch @compileError(invalid_format_msg); }; } pub const gpio = struct { - fn dirReg(comptime pin: type) *volatile u8 { - return @intToPtr(*volatile u8, 0x01); - } - fn portReg(comptime pin: type) *volatile u8 { - return @intToPtr(*volatile u8, 0x01); - } - fn pinReg(comptime pin: type) *volatile u8 { - return @intToPtr(*volatile u8, 0x01); + fn regs(comptime desc: type) type { + return struct { + const pin_addr = 3 * @enumToInt(desc.port) + 0x00; + const dir_addr = 3 * @enumToInt(desc.port) + 0x01; + const port_addr = 3 * @enumToInt(desc.port) + 0x02; + + const pin = @intToPtr(*volatile u8, pin_addr); + const dir = @intToPtr(*volatile u8, dir_addr); + const port = @intToPtr(*volatile u8, port_addr); + }; } pub fn setOutput(comptime pin: type) void { - dirReg(pin).* |= (1 << pin.pin); + asm volatile ("sbi %[port], %[pin]" + : + : [port] "I" (regs(pin).dir_addr), + [pin] "I" (pin.pin) + ); } pub fn setInput(comptime pin: type) void { - dirReg(pin).* &= ~(@as(u8, 1) << pin.pin); + asm volatile ("cbi %[port], %[pin]" + : + : [port] "I" (regs(pin).dir_addr), + [pin] "I" (pin.pin) + ); } pub fn read(comptime pin: type) u1 { - return if ((pinReg(pin).* & (1 << pin.pin)) != 0) + return if ((regs(pin).pin.* & (1 << pin.pin)) != 0) @as(u1, 1) else 0; @@ -49,13 +65,25 @@ pub const gpio = struct { pub fn write(comptime pin: type, state: u1) void { if (state == 1) { - portReg(pin).* |= (1 << pin.pin); + asm volatile ("sbi %[port], %[pin]" + : + : [port] "I" (regs(pin).port_addr), + [pin] "I" (pin.pin) + ); } else { - portReg(pin).* &= ~@as(u8, 1 << pin.pin); + asm volatile ("cbi %[port], %[pin]" + : + : [port] "I" (regs(pin).port_addr), + [pin] "I" (pin.pin) + ); } } pub fn toggle(comptime pin: type) void { - portReg(pin).* ^= (1 << pin.pin); + asm volatile ("sbi %[port], %[pin]" + : + : [port] "I" (regs(pin).pin_addr), + [pin] "I" (pin.pin) + ); } }; diff --git a/tests/blinky.zig b/tests/blinky.zig index 7b30cee..3dece30 100644 --- a/tests/blinky.zig +++ b/tests/blinky.zig @@ -30,8 +30,10 @@ pub fn main() void { } fn busyloop() void { + const limit = 100_000; + var i: u24 = 0; - while (i < 100_000) : (i += 1) { + while (i < limit) : (i += 1) { @import("std").mem.doNotOptimizeAway(i); } }