wires

summary refs log tree commit diff
path: root/src/gpio.zig
blob: ba54394f7d13cfb56660f5ea46f9d6c3807621ae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const PERIPHERAL_BASE = @import("board.zig").PERIPHERAL_BASE;

const FSEL = PERIPHERAL_BASE + 0x200000;
const SET = PERIPHERAL_BASE + 0x20001c;
const CLR = PERIPHERAL_BASE + 0x200028;
const PULL = PERIPHERAL_BASE + 0x2000e4;

const MAX_PIN = 53;

fn call(
    pin: comptime_int,
    value: u32,
    base: comptime_int,
    field_size: comptime_int,
) void {
    const field_mask: u32 = (1 << field_size) - 1;

    if (pin > MAX_PIN) @compileError("invalid pin number");

    const n_fields = 32 / field_size;
    const reg = base + (pin / n_fields) * 4;
    const shift = (pin % n_fields) * field_size;

    const mmio_ptr: *volatile u32 = @ptrFromInt(reg);
    var reg_val = mmio_ptr.*;
    reg_val &= ~(field_mask << shift);
    reg_val |= value << shift;
    mmio_ptr.* = reg_val;
}

pub fn write(pin: comptime_int, value: bool) void {
    if (value) {
        call(pin, 1, SET, 1);
    } else {
        call(pin, 1, CLR, 1);
    }
}

pub const Pull = enum {
    none,
    up,
    down,
};

pub fn setPull(pin: comptime_int, pull: Pull) void {
    call(pin, @intFromEnum(pull), PULL, 2);
}

pub const Function = enum {
    input,
    output,
    alt5,
    alt4,
    alt0,
    alt1,
    alt2,
    alt3,
};

pub fn setFunction(pin: comptime_int, function: Function) void {
    call(pin, @intFromEnum(function), FSEL, 3);
}