From 93d2236e2175151372b7035480b86248fb937d62 Mon Sep 17 00:00:00 2001 From: Vlad Korniev Date: Mon, 29 Oct 2018 12:24:07 -0700 Subject: [PATCH] mfrc522: improvements to gain and wait (#297) - Antenna Gain - Terminating Wait if Halt received - Renamed SetOperationtimeout to SetOperationTimeout --- experimental/devices/mfrc522/mfrc522.go | 74 ++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/experimental/devices/mfrc522/mfrc522.go b/experimental/devices/mfrc522/mfrc522.go index 92796e1..8b2db57 100644 --- a/experimental/devices/mfrc522/mfrc522.go +++ b/experimental/devices/mfrc522/mfrc522.go @@ -11,6 +11,7 @@ package mfrc522 import ( "fmt" + "sync" "time" "periph.io/x/periph/conn" @@ -119,6 +120,8 @@ func NewSPI(spiPort spi.Port, resetPin gpio.PinOut, irqPin gpio.PinIn) (*Dev, er operationTimeout: 30 * time.Second, irqPin: irqPin, resetPin: resetPin, + antennaGain: 4, + stop: make(chan struct{}, 1), } if err := dev.Init(); err != nil { return nil, err @@ -132,6 +135,13 @@ type Dev struct { irqPin gpio.PinIn operationTimeout time.Duration spiDev spi.Conn + stop chan struct{} + + aMu sync.Mutex + antennaGain int + + mu sync.Mutex + isWaiting bool } // String implements conn.Resource. @@ -144,16 +154,28 @@ func (r *Dev) String() string { // // It soft-stops the chip - PowerDown bit set, command IDLE func (r *Dev) Halt() error { + r.mu.Lock() + defer r.mu.Unlock() + + if r.isWaiting { + select { + case <-r.stop: + default: + } + + r.stop <- struct{}{} + } + return r.devWrite(commands.CommandReg, 16) } -// SetOperationtimeout updates the device timeout for card operations. +// SetOperationTimeout updates the device timeout for card operations. // // Effectively that sets the maximum time the RFID device will wait for IRQ // from the proximity card detection. // // timeout the duration to wait for IRQ strobe. -func (r *Dev) SetOperationtimeout(timeout time.Duration) { +func (r *Dev) SetOperationTimeout(timeout time.Duration) { r.operationTimeout = timeout } @@ -165,6 +187,15 @@ func (r *Dev) Init() error { if err := r.writeCommandSequence(sequenceCommands.init); err != nil { return err } + + r.aMu.Lock() + gain := byte(r.antennaGain)<<4 + r.aMu.Unlock() + + if err := r.devWrite(int(commands.RFCfgReg), gain); err != nil { + return err + } + return r.SetAntenna(true) } @@ -188,6 +219,18 @@ func (r *Dev) SetAntenna(state bool) error { return r.clearBitmask(commands.TxControlReg, 0x03) } +// SetAntennaGain configures antenna signal strength. +// +// gain - signal strength from 0 to 7. +func (r *Dev) SetAntennaGain(gain int) { + r.aMu.Lock() + defer r.aMu.Unlock() + + if 0 <= gain && gain <= 7 { + r.antennaGain = gain + } +} + // CardWrite the low-level interface to write some raw commands to the card. // // command - the command register @@ -321,12 +364,35 @@ func (r *Dev) Request() (int, error) { // Wait wait for IRQ to strobe on the IRQ pin when the card is detected. func (r *Dev) Wait() error { + r.mu.Lock() + waitCancelled := false + if r.isWaiting { + r.mu.Unlock() + return wrapf("concurrent access is forbidden") + } + + r.isWaiting = true + r.mu.Unlock() + irqChannel := make(chan bool) + go func() { - irqChannel <- r.irqPin.WaitForEdge(r.operationTimeout) + result := r.irqPin.WaitForEdge(r.operationTimeout) + r.mu.Lock() + defer r.mu.Unlock() + if waitCancelled { + return + } + + irqChannel <- result }() defer func() { + r.mu.Lock() + r.isWaiting = false + waitCancelled = true + r.mu.Unlock() + close(irqChannel) }() @@ -342,6 +408,8 @@ func (r *Dev) Wait() error { return err } select { + case <-r.stop: + return wrapf("halt") case irqResult := <-irqChannel: if !irqResult { return wrapf("timeout waitinf for IRQ edge: %v", r.operationTimeout)