1// Copyright © 2021 Sören Tempel2//3// This program is free software: you can redistribute it and/or modify4// it under the terms of the GNU Affero General Public License as5// published by the Free Software Foundation, either version 3 of the6// License, or (at your option) any later version.7//8// This program is distributed in the hope that it will be useful, but9// WITHOUT ANY WARRANTY; without even the implied warranty of10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU11// Affero General Public License for more details.12//13// You should have received a copy of the GNU Affero General Public License14// along with this program. If not, see <https://www.gnu.org/licenses/>.1516// Maximum of 32 pins -> 2**5 = 32.17pub const Pin = u5;1819pub const Mode = enum {20 IN,21 OUT,22};2324pub fn pin(x: Pin, y: Pin) Pin {25 return x | y;26}2728pub const Gpio = struct {29 base_addr: usize,3031 const Reg = enum(usize) {32 input = 0x04,33 output_en = 0x08,34 output_val = 0x0c,35 pue = 0x10,36 iof_en = 0x38,37 iof_sel = 0x3c,38 };3940 fn readWord(self: Gpio, reg: Reg) u32 {41 const ptr = @intToPtr(*volatile u32, self.base_addr + @enumToInt(reg));42 return ptr.*;43 }4445 fn writeWord(self: Gpio, reg: Reg, value: u32) void {46 const ptr = @intToPtr(*volatile u32, self.base_addr + @enumToInt(reg));47 ptr.* = value;48 }4950 pub fn setRegister(self: Gpio, reg: Reg, x: Pin, val: u1) void {51 const regVal = self.readWord(reg);5253 const mask = @as(u32, 1) << x;54 if (val == 0) {55 self.writeWord(reg, regVal & ~mask);56 } else {57 self.writeWord(reg, regVal | mask);58 }59 }6061 // Configure a GPIO pin as IOF controlled (instead of software controlled).62 pub fn setIOFCtrl(self: Gpio, x: Pin, select: u1) void {63 // Select one of the two HW-Driven functions.64 self.setRegister(Reg.iof_sel, x, select);6566 // Enable selected HW-Driven function.67 self.setRegister(Reg.iof_en, x, 1);68 }6970 pub fn set(self: Gpio, x: Pin, v: u1) void {71 self.setRegister(Reg.output_val, x, v);72 }7374 pub fn init(self: Gpio, x: Pin, mode: Mode) void {75 switch (mode) {76 Mode.IN => {77 self.setRegister(Reg.input, x, 1);78 self.setRegister(Reg.output_en, x, 0);79 self.setRegister(Reg.pue, x, 0);80 },81 Mode.OUT => {82 self.setRegister(Reg.input, x, 0);83 self.setRegister(Reg.output_en, x, 1);84 self.setRegister(Reg.pue, x, 0);85 },86 }8788 // Disable HW-driven functions for Pin89 self.setRegister(Reg.iof_en, x, 0);90 self.setRegister(Reg.iof_sel, x, 0);91 }92};