Skip to content

Commit

Permalink
Merge pull request #29 from Drahoslav7/perf/gpio-write
Browse files Browse the repository at this point in the history
Perf/gpio - faster write and toggle
  • Loading branch information
stianeikeland committed Oct 9, 2018
2 parents 3abdd22 + 6c29b50 commit 2c2ef09
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 9 deletions.
27 changes: 18 additions & 9 deletions rpio.go
Expand Up @@ -284,19 +284,19 @@ func PinMode(pin Pin, mode Mode) {
func WritePin(pin Pin, state State) {
p := uint8(pin)

// Clear register, 10 / 11 depending on bank
// Set register, 7 / 8 depending on bank
clearReg := p/32 + 10
// Clear register, 10 / 11 depending on bank
setReg := p/32 + 7
clearReg := p/32 + 10

memlock.Lock()
defer memlock.Unlock()

if state == Low {
gpioMem[clearReg] = 1 << (p & 31)
} else {
gpioMem[setReg] = 1 << (p & 31)
}
memlock.Unlock() // not deferring saves ~600ns
}

// Read the state of a pin
Expand All @@ -312,14 +312,23 @@ func ReadPin(pin Pin) State {
}

// Toggle a pin state (high -> low -> high)
// TODO: probably possible to do this much faster without read
func TogglePin(pin Pin) {
switch ReadPin(pin) {
case Low:
pin.High()
case High:
pin.Low()
p := uint8(pin)

setReg := p/32 + 7
clearReg := p/32 + 10
levelReg := p/32 + 13

bit := uint32(1 << (p & 31))

memlock.Lock()

if (gpioMem[levelReg] & bit) != 0 {
gpioMem[clearReg] = bit
} else {
gpioMem[setReg] = bit
}
memlock.Unlock()
}

// Enable edge event detection on pin.
Expand Down
73 changes: 73 additions & 0 deletions rpio_test.go
Expand Up @@ -117,4 +117,77 @@ func TestEvent(t *testing.T) {
}

})

}

func BenchmarkGpio(b *testing.B) {
src := Pin(3)
src.Mode(Output)
src.Low()

pin := Pin(2)
pin.Mode(Input)
pin.PullDown()

oldWrite := func(pin Pin, state State) {
p := uint8(pin)

setReg := p/32 + 7
clearReg := p/32 + 10

memlock.Lock()
defer memlock.Unlock()

if state == Low {
gpioMem[clearReg] = 1 << (p & 31)
} else {
gpioMem[setReg] = 1 << (p & 31)
}
}

oldToggle := func(pin Pin) {
switch ReadPin(pin) {
case Low:
oldWrite(pin, High)
case High:
oldWrite(pin, Low)
}
}

b.Run("write", func(b *testing.B) {
b.Run("old", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if i%2 == 0 {
oldWrite(src, High)
} else {
oldWrite(src, Low)
}
}
})

b.Run("new", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if i%2 == 0 {
WritePin(src, High)
} else {
WritePin(src, Low)
}
}
})
})

b.Run("toggle", func(b *testing.B) {
b.Run("old", func(b *testing.B) {
for i := 0; i < b.N; i++ {
oldToggle(src)
}
})

b.Run("new", func(b *testing.B) {
for i := 0; i < b.N; i++ {
TogglePin(src)
}
})
})

}

0 comments on commit 2c2ef09

Please sign in to comment.