takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PN512SPITransportDriver.cpp Source File

PN512SPITransportDriver.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "platform/platform.h"
00018 
00019 #if (defined (DEVICE_SPI) && defined (DEVICE_INTERRUPTIN)) || defined(DOXYGEN_ONLY)
00020 
00021 #include "PN512SPITransportDriver.h"
00022 
00023 #include "stack/transceiver/transceiver.h"
00024 #include "platform/mbed_wait_api.h"
00025 
00026 using namespace mbed;
00027 using namespace mbed::nfc;
00028 
00029 PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst) :
00030     _spi(mosi, miso, sclk),
00031     _ssel(ssel, 1),
00032     _irq(irq, PullNone),
00033     _rst(rst, 1)
00034 {
00035 
00036     // Use SPI mode 0
00037     _spi.format(8, 0);
00038 
00039     // The PN512 supports SPI clock frequencies up to 10MHz, so use this if we can
00040     _spi.frequency(10000000UL);
00041 
00042     // Initialize NFC transport
00043     nfc_transport_init(&_nfc_transport, &PN512SPITransportDriver::s_transport_write, &PN512SPITransportDriver::s_transport_read, this);
00044 }
00045 
00046 void PN512SPITransportDriver::initialize()
00047 {
00048     // Deactivate IRQ
00049     _irq.rise(callback<void>());
00050 
00051     // Assert reset pin
00052     // According to the datasheet, it needs to be asserted for at least 100ns
00053     // Wait for 1us as that's the shortest time we can wait for
00054     _rst = 0;
00055     wait_us(1);
00056     _rst = 1;
00057 
00058     // Setup IRQ pin
00059     _irq.rise(callback(this, &PN512SPITransportDriver::hw_interrupt));
00060 }
00061 
00062 nfc_transport_t *PN512SPITransportDriver::get_transport()
00063 {
00064     return &_nfc_transport;
00065 }
00066 
00067 void PN512SPITransportDriver::transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen)
00068 {
00069     if (outLen == 0) {
00070         return;
00071     }
00072 
00073     // First byte is (address << 1) | 0x00 for a write
00074     address = (address << 1) | 0x00;
00075     _ssel = 0;
00076     _spi.write(address); // First write address byte
00077     _spi.write((const char *) outBuf, outLen, (char *) NULL, 0); // Ignore read bytes
00078     _ssel = 1;
00079 }
00080 
00081 void PN512SPITransportDriver::transport_read(uint8_t address, uint8_t *inBuf, size_t inLen)
00082 {
00083     if (inLen == 0) {
00084         return;
00085     }
00086 
00087     // Address byte is (address << 1) | 0x80 for a read
00088     // This should be repeated accross the transfer, except for the last byte which should be 0
00089     address = (address << 1) | 0x80;
00090 
00091     // Set this byte across inBuf so that it's repeated accross the transfer
00092     // Bit cheeky, but will work
00093     memset(inBuf, address, inLen - 1);
00094 
00095     // Also terminate with 0 so that it's a no-op
00096     inBuf[inLen - 1] = 0;
00097 
00098     _ssel = 0;
00099     _spi.write(address); // First write address byte
00100     _spi.write((const char *) inBuf, inLen, (char *) inBuf, inLen);
00101     _ssel = 1;
00102 }
00103 
00104 // Callbacks from munfc
00105 void PN512SPITransportDriver::s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser)
00106 {
00107     PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser;
00108     self->transport_write(address, outBuf, outLen);
00109 }
00110 
00111 void PN512SPITransportDriver::s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser)
00112 {
00113     PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser;
00114     self->transport_read(address, inBuf, inLen);
00115 }
00116 
00117 #endif