mirror of https://github.com/ARMmbed/mbed-os.git
Implement PN512 SPI transport driver
parent
d4c29207cc
commit
5fa27744b0
|
@ -20,19 +20,23 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "nfc/NFCControllerDriver.h"
|
||||
#include "PN512TransportDriver.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace nfc {
|
||||
|
||||
struct PN512TransportDriver;
|
||||
class PN512Driver : NFCControllerDriver {
|
||||
class PN512Driver : public NFCControllerDriver, private PN512TransportDriver::Delegate {
|
||||
public:
|
||||
PN512Driver(PN512TransportDriver* transport_driver);
|
||||
|
||||
private:
|
||||
virtual void initialize(nfc_scheduler_timer_t* pTimer) = 0;
|
||||
virtual nfc_transceiver_t* get_transceiver() const;
|
||||
|
||||
private:
|
||||
// PN512TransportDriver::Delegate implementation
|
||||
void on_hw_interrupt();
|
||||
|
||||
pn512_t _pn512;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,21 +14,22 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_PN512_TRANSPORT_DRIVER_H
|
||||
#define MBED_PN512_TRANSPORT_DRIVER_H
|
||||
#ifndef MBED_PN512_SPI_TRANSPORT_DRIVER_H
|
||||
#define MBED_PN512_SPI_TRANSPORT_DRIVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/nfc_transport.h"
|
||||
#include "PN512TransportDriver.h"
|
||||
|
||||
|
||||
namespace mbed {
|
||||
namespace nfc {
|
||||
|
||||
class PN512SPITransportDriver {
|
||||
class PN512SPITransportDriver : public PN512TransportDriver {
|
||||
public:
|
||||
PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq);
|
||||
PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst);
|
||||
|
||||
private:
|
||||
virtual void initialize();
|
||||
|
@ -43,7 +44,9 @@ namespace nfc {
|
|||
|
||||
nfc_transport_t _nfc_transport;
|
||||
SPI _spi;
|
||||
DigitalOut _ssel;
|
||||
InterruptIn _irq;
|
||||
DigitalOut _rst;
|
||||
};
|
||||
|
||||
} // namespace nfc
|
||||
|
|
|
@ -23,10 +23,53 @@
|
|||
|
||||
namespace mbed {
|
||||
namespace nfc {
|
||||
|
||||
struct PN512TransportDriver {
|
||||
/**
|
||||
* The PN512 supports multiple transport mechanisms (SPI, I2C, UART): this class provides a unified API across these transports
|
||||
*/
|
||||
class PN512TransportDriver {
|
||||
public:
|
||||
/**
|
||||
* The PN512TransportDriver delegate
|
||||
*/
|
||||
struct Delegate {
|
||||
/**
|
||||
* Called when the PN512 asserts the interrupt line
|
||||
*/
|
||||
void on_hw_interrupt();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a PN512TransportDriver instance
|
||||
*/
|
||||
PN512TransportDriver();
|
||||
|
||||
/**
|
||||
* Initialize transport driver and perform a chip reset
|
||||
*/
|
||||
virtual void initialize() = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the nfc_transport_t struct for the stack to use
|
||||
*
|
||||
* @return a pointer to a nfc_transport_t struct
|
||||
*/
|
||||
virtual nfc_transport_t* get_transport() const = 0;
|
||||
|
||||
/**
|
||||
* Set this instance's delegate
|
||||
*
|
||||
* @param[in] delegate the delegate instance to use
|
||||
*/
|
||||
void set_delegate(Delegate* delegate);
|
||||
protected:
|
||||
|
||||
/**
|
||||
* An implementation must call this function (can be called from interrupt context)
|
||||
* when the PN512 asserts its interrupt line
|
||||
*/
|
||||
void hw_interrupt();
|
||||
private:
|
||||
Delegate* _delegate;
|
||||
};
|
||||
|
||||
} // namespace nfc
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "PN512Driver.h"
|
|
@ -0,0 +1,104 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "PN512SPITransportDriver.h"
|
||||
|
||||
#include "stack/transceiver/transceiver.h"
|
||||
#include "platform/mbed_wait_api.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace mbed::nfc;
|
||||
|
||||
PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst)) :
|
||||
_spi(mosi, miso, sclk),
|
||||
_ssel(ssel, 1),
|
||||
_irq(irq, PullNone),
|
||||
_rst(rst, 1) {
|
||||
|
||||
// Use SPI mode 0
|
||||
_spi.format(8, 0);
|
||||
|
||||
// The PN512 supports SPI clock frequencies up to 10MHz, so use this if we can
|
||||
_spi.frequency(10E6UL);
|
||||
|
||||
// Initialize NFC transport
|
||||
nfc_transport_init(&_nfc_transport, &PN512SPITransportDriver::s_transport_write, &PN512SPITransportDriver::s_transport_read, this);
|
||||
}
|
||||
|
||||
void PN512SPITransportDriver::initialize() {
|
||||
// Deactivate IRQ
|
||||
_irq.rise(callback(NULL));
|
||||
|
||||
// Assert reset pin
|
||||
// According to the datasheet, it needs to be asserted for at least 100ns
|
||||
// Wait for 1us as that's the shortest time we can wait for
|
||||
_rst = 0;
|
||||
wait_us(1);
|
||||
_rst = 1;
|
||||
|
||||
// Setup IRQ pin
|
||||
_irq.rise(callback(this, &PN512SPITransportDriver::hw_interrupt));
|
||||
}
|
||||
|
||||
nfc_transport_t* PN512SPITransportDriver::get_transport() const {
|
||||
return &_nfc_transport;
|
||||
}
|
||||
|
||||
void PN512SPITransportDriver::transport_write( uint8_t address, const uint8_t* outBuf, size_t outLen ) {
|
||||
if( outLen == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First byte is (address << 1) | 0x00 for a write
|
||||
address = (address << 1) | 0x00;
|
||||
_ssel = 0;
|
||||
_spi.write(address); // First write address byte
|
||||
_spi.write(outBuf, outLen, NULL, 0); // Ignore read bytes
|
||||
_ssel = 1;
|
||||
}
|
||||
|
||||
void PN512SPITransportDriver::transport_read( uint8_t address, uint8_t* inBuf, size_t inLen ) {
|
||||
if( inLen == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Address byte is (address << 1) | 0x80 for a read
|
||||
// This should be repeated accross the transfer, except for the last byte which should be 0
|
||||
address = (address << 1) | 0x80;
|
||||
|
||||
// Set this byte across inBuf so that it's repeated accross the transfer
|
||||
// Bit cheeky, but will work
|
||||
memset(inBuf, address, inLen - 1);
|
||||
|
||||
// Also terminate with 0 so that it's a no-op
|
||||
inBuf[inLen - 1] = 0;
|
||||
|
||||
_ssel = 0;
|
||||
_spi.write(address); // First write address byte
|
||||
_spi.write(inBuf, inLen, inBuf, inLen);
|
||||
_ssel = 1;
|
||||
}
|
||||
|
||||
// Callbacks from munfc
|
||||
static void PN512SPITransportDriver::s_transport_write( uint8_t address, const uint8_t* outBuf, size_t outLen, void* pUser ) {
|
||||
PN512SPITransportDriver* self = (PN512SPITransportDriver*)pUser;
|
||||
self->transport_write(address, outBuf, outLen);
|
||||
}
|
||||
|
||||
static void PN512SPITransportDriver::s_transport_read( uint8_t address, uint8_t* inBuf, size_t inLen, void* pUser ) {
|
||||
PN512SPITransportDriver* self = (PN512SPITransportDriver*)pUser;
|
||||
self->transport_read(address, inBuf, inLen);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "PN512TransportDriver.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace mbed::nfc;
|
||||
|
||||
PN512TransportDriver::PN512TransportDriver() : _delegate() {
|
||||
|
||||
}
|
||||
|
||||
void PN512TransportDriver::set_delegate(Delegate* delegate) {
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
void PN512TransportDriver::hw_interrupt() {
|
||||
if(_delegate != NULL) {
|
||||
_delegate->on_hw_interrupt();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue