|
|
|
|
@ -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)
|
|
|
|
|
|