blob: 825c21b892378293512c5b8fbeb5eb352e15518a [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm
package internal
import (
"fmt"
"sync"
"time"
"github.com/davecheney/gpio"
"github.com/davecheney/gpio/rpi"
"v.io/x/lock"
)
const toggleWaitTime = 5 * time.Second
type hw struct {
relay gpio.Pin
monitor gpio.Pin
mu sync.Mutex // To allow for only one SetStatus invocation at a time.
}
func init() {
relay, err := gpio.OpenPin(rpi.GPIO17, gpio.ModeOutput)
if err != nil {
panic(err)
}
relay.Clear()
monitor, err := gpio.OpenPin(rpi.GPIO22, gpio.ModeInput)
if err != nil {
relay.Close()
panic(err)
}
hardware = &hw{relay: relay, monitor: monitor}
}
func (hw *hw) Status() lock.LockStatus {
if hw.monitor.Get() {
return lock.Unlocked
}
return lock.Locked
}
func (hw *hw) SetStatus(status lock.LockStatus) error {
hw.mu.Lock()
defer hw.mu.Unlock()
desired := (status == lock.Unlocked)
// TODO(ashankar): Change this to work with an actual relay. Currently
// simulating the "motor" with an active buzzer.
defer hw.relay.Clear()
hw.relay.Set()
start := time.Now()
for hw.monitor.Get() != desired {
if d := time.Since(start); d > toggleWaitTime {
return fmt.Errorf("lock state unchanged after %v: might be stuck. aborting.", d)
}
time.Sleep(200 * time.Millisecond)
}
return nil
}