/
gpio.zig
83 lines (70 loc) · 2.41 KB
/
gpio.zig
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
pub fn setAlt5(pin_number: u32) void {
setPinPull(pin_number, Pull.None);
setPinFunction(pin_number, GPIO_FUNCTION_ALT5);
}
pub fn initOutputPinWithPullNone(pin_number: u32) void {
setPinPull(pin_number, Pull.None);
setPinFunction(pin_number, GPIO_FUNCTION_OUT);
}
pub fn setPinOutputBool(pin_number: u32, onOrOff: bool) void {
if (onOrOff) {
pins_set.write(pin_number, 1);
} else {
pins_clear.write(pin_number, 1);
}
}
fn setPinPull(pin_number: u32, pull: Pull) void {
GPPUD.* = @enumToInt(pull);
arm.delay(150);
pins_pull.write(pin_number, 1);
arm.delay(150);
GPPUD.* = @enumToInt(Pull.None);
pins_pull.write(pin_number, 0);
}
fn setPinFunction(pin_number: u32, function: u32) void {
pins_function.write(pin_number, function);
}
pub fn ioArrayOf(base: u32, field_size: u32, length: u32) type {
var IoArray = struct {
const Self = @This();
fn write(self: Self, index: u32, value: u32) void {
const field_mask = u32(1) << @intCast(u5, field_size - 1);
rangeCheck(index, length - 1);
rangeCheck(value, field_mask);
const fields_per_word = 32 / field_size;
const register = @intToPtr(*volatile u32, base + (index / fields_per_word) * 4);
const shift = @intCast(u5, (index % fields_per_word) * field_size);
var word = register.*;
word &= ~(field_mask << shift);
word |= value << shift;
register.* = word;
}
};
return IoArray;
}
fn rangeCheck(x: u32, max: u32) void {
if (x > max) {
panicf("{} exceeds max {}", x, max);
}
}
const pins_set: ioArrayOf(GPSET0, 1, GPIO_MAX_PIN) = undefined;
const pins_clear: ioArrayOf(GPCLR0, 1, GPIO_MAX_PIN) = undefined;
const pins_pull: ioArrayOf(GPPUDCLK0, 1, GPIO_MAX_PIN) = undefined;
const pins_function: ioArrayOf(GPFSEL0, 3, GPIO_MAX_PIN) = undefined;
const GPIO_MAX_PIN = 53;
const GPFSEL0 = PERIPHERAL_BASE + 0x200000;
const GPSET0 = PERIPHERAL_BASE + 0x20001C;
const GPCLR0 = PERIPHERAL_BASE + 0x200028;
const GPPUD = arm.io(0x200094);
const GPPUDCLK0 = PERIPHERAL_BASE + 0x200098;
const Pull = enum {
None,
Down,
Up,
};
const GPIO_FUNCTION_FIELD_SIZE: u32 = 3;
const GPIO_FUNCTION_OUT: u32 = 1;
const GPIO_FUNCTION_ALT5: u32 = 2;
const arm = @import("arm_assembly_code.zig");
const panicf = arm.panicf;
const PERIPHERAL_BASE = arm.PERIPHERAL_BASE;