|
|
|
@ -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)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|