78 lines
2.2 KiB
Nim
78 lines
2.2 KiB
Nim
import std/[bitops, memfiles]
|
|
|
|
type
|
|
Pin* = range[0 .. 53]
|
|
|
|
const
|
|
gpioStart = 0x20200000
|
|
offsetGpfsel0 = 0x00000000
|
|
offsetGpfsel1 = 0x00000004
|
|
offsetGpfsel2 = 0x00000008
|
|
offsetGpfsel3 = 0x0000000C
|
|
offsetGpfsel4 = 0x00000010
|
|
offsetGpfsel5 = 0x00000014
|
|
offsetGpset0 = 0x0000001C
|
|
offsetGpset1 = 0x00000020
|
|
offsetGpclr0 = 0x00000028
|
|
offsetGpclr1 = 0x0000002C
|
|
offsetGplev0 = 0x00000034
|
|
offsetGplev1 = 0x00000038
|
|
offsetGpioEnd = 0x000000A0
|
|
|
|
func ptrFromOffset(p: pointer, offset: int): ptr[uint32] =
|
|
cast[ptr uint32](cast[ByteAddress](p) + offset)
|
|
|
|
let
|
|
mm*: MemFile = open("/dev/mem", mode = fmReadWrite,
|
|
offset = gpioStart, mappedSize = offsetGpioEnd)
|
|
gpfsel0* = ptrFromOffset(mm.mem, offsetGpfsel0)
|
|
gpfsel1* = ptrFromOffset(mm.mem, offsetGpfsel1)
|
|
gpfsel2* = ptrFromOffset(mm.mem, offsetGpfsel2)
|
|
gpfsel3* = ptrFromOffset(mm.mem, offsetGpfsel3)
|
|
gpfsel4* = ptrFromOffset(mm.mem, offsetGpfsel4)
|
|
gpfsel5* = ptrFromOffset(mm.mem, offsetGpfsel5)
|
|
gpset0* = ptrFromOffset(mm.mem, offsetGpset0)
|
|
gpset1* = ptrFromOffset(mm.mem, offsetGpset1)
|
|
gpclr0* = ptrFromOffset(mm.mem, offsetGpclr0)
|
|
gpclr1* = ptrFromOffset(mm.mem, offsetGpclr1)
|
|
gplev0* = ptrFromOffset(mm.mem, offsetGplev0)
|
|
gplev1* = ptrFromOffset(mm.mem, offsetGplev1)
|
|
|
|
proc gpset*(pin: Pin) =
|
|
let pinOffset = (1 shl (pin mod 32)).uint32
|
|
if pin < 32:
|
|
gpset0[] = pinOffset
|
|
else:
|
|
gpset1[] = pinOffset
|
|
|
|
proc gpclr*(pin: Pin) =
|
|
let pinOffset = (1 shl (pin mod 32)).uint32
|
|
if pin < 32:
|
|
gpclr0[] = pinOffset
|
|
else:
|
|
gpclr1[] = pinOffset
|
|
|
|
proc gpfsel(pin: Pin): ptr[uint32] =
|
|
case pin
|
|
of 0..9: gpfsel0
|
|
of 10..19: gpfsel1
|
|
of 20..29: gpfsel2
|
|
of 30..39: gpfsel3
|
|
of 40..49: gpfsel4
|
|
of 50..53: gpfsel5
|
|
|
|
proc setInputPin*(gpfsel: ptr[uint32], pin: Pin) =
|
|
let pinOffset = (0b111 shl ((pin mod 10) * 3)).uint32
|
|
gpfsel[].clearMask(pinOffset)
|
|
|
|
proc setOutputPin*(gpfsel: ptr[uint32], pin: Pin) =
|
|
let pinOffset = (0b001 shl ((pin mod 10) * 3)).uint32
|
|
gpfsel[].setMask(pinOffset)
|
|
|
|
proc setInputPins*(pins: varargs[Pin]) =
|
|
for pin in pins:
|
|
setInputPin(pin.gpfsel, pin)
|
|
|
|
proc setOutputPins*(pins: varargs[Pin]) =
|
|
for pin in pins:
|
|
setOutputPin(pin.gpfsel, pin)
|