STMicroelectronics' M24SR NFC Dynamic Tag Library.

Dependencies:   ST_INTERFACES

Dependents:   X_NUCLEO_NFC01A1

Fork of M24SR by ST Expansion SW Team

M24SR series Dynamic NFC Tags

The M24SR series provides an NFC forum tag type 4 RF interface and supports the NFC data exchange format (NDEF). This enables NFC use cases such as simple Bluetooth pairing and other connection handovers, automatic links to URLs, storage of Vcard and other types of information. It can be used in a wide variety of applications, including consumer electronics, computer peripherals, home appliances, industrial automation and healthcare products.

  • NFC forum tag type 4 based on ISO 14443 RF interface
  • 1 MHz I²C serial interface operating from 2.7 to 5.5 V
  • EEPROM memory density from 2 Kbits to 64 Kbits with built-in NDEF message support
  • RF disable pin allowing the application to control RF access from NFC phones
  • 128-bit password protection
  • General-purpose output pin allowing flexibility for the applications (wake up on several types of events)
  • Simple antenna design, backward compatible with M24LR series

For further information and ordering please refer to the ST Page.

HelloWorld application

Import programHelloWorld_Async_M24SR

M24SR NFC example. Simple application to asynchronously write and read an URL from a M24SR tag.

Committer:
nikapov
Date:
Mon Jul 31 12:26:02 2017 +0000
Revision:
0:11161008d77a
First revision.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nikapov 0:11161008d77a 1 /**
nikapov 0:11161008d77a 2 ******************************************************************************
nikapov 0:11161008d77a 3 * @file NdefNfcTagSTM24SR.cpp
nikapov 0:11161008d77a 4 * @author ST Central Labs
nikapov 0:11161008d77a 5 * @version V2.0.0
nikapov 0:11161008d77a 6 * @date 28 Apr 2017
nikapov 0:11161008d77a 7 * @brief Wrapper class of the NDefLib library to write/read NDEF messages
nikapov 0:11161008d77a 8 ******************************************************************************
nikapov 0:11161008d77a 9 * @attention
nikapov 0:11161008d77a 10 *
nikapov 0:11161008d77a 11 * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
nikapov 0:11161008d77a 12 *
nikapov 0:11161008d77a 13 * Redistribution and use in source and binary forms, with or without modification,
nikapov 0:11161008d77a 14 * are permitted provided that the following conditions are met:
nikapov 0:11161008d77a 15 * 1. Redistributions of source code must retain the above copyright notice,
nikapov 0:11161008d77a 16 * this list of conditions and the following disclaimer.
nikapov 0:11161008d77a 17 * 2. Redistributions in binary form must reproduce the above copyright notice,
nikapov 0:11161008d77a 18 * this list of conditions and the following disclaimer in the documentation
nikapov 0:11161008d77a 19 * and/or other materials provided with the distribution.
nikapov 0:11161008d77a 20 * 3. Neither the name of STMicroelectronics nor the names of its contributors
nikapov 0:11161008d77a 21 * may be used to endorse or promote products derived from this software
nikapov 0:11161008d77a 22 * without specific prior written permission.
nikapov 0:11161008d77a 23 *
nikapov 0:11161008d77a 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
nikapov 0:11161008d77a 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
nikapov 0:11161008d77a 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
nikapov 0:11161008d77a 27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
nikapov 0:11161008d77a 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
nikapov 0:11161008d77a 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
nikapov 0:11161008d77a 30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
nikapov 0:11161008d77a 31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
nikapov 0:11161008d77a 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nikapov 0:11161008d77a 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nikapov 0:11161008d77a 34 *
nikapov 0:11161008d77a 35 ******************************************************************************
nikapov 0:11161008d77a 36 */
nikapov 0:11161008d77a 37
nikapov 0:11161008d77a 38 #include <cmath>
nikapov 0:11161008d77a 39
nikapov 0:11161008d77a 40 #include "NDefNfcTagM24SR.h"
nikapov 0:11161008d77a 41
nikapov 0:11161008d77a 42
nikapov 0:11161008d77a 43 /* wait 1sec, driver is configured to let 200ms for command to complete */
nikapov 0:11161008d77a 44 /* which is enough for all commands except GetSession if RF session is already opened */
nikapov 0:11161008d77a 45 /* Smartphone generally releases the session within the second, anyway the user can modify this value */
nikapov 0:11161008d77a 46 #define OPENSESSION_NTRIALS 5
nikapov 0:11161008d77a 47
nikapov 0:11161008d77a 48 #define CC_FILE_LENGTH_BYTE 15
nikapov 0:11161008d77a 49 ////////////////////////////START OpenSessionCallBack/////////////////////////
nikapov 0:11161008d77a 50 NDefNfcTagM24SR::OpenSessionCallBack::
nikapov 0:11161008d77a 51 OpenSessionCallBack(NDefNfcTagM24SR& sender):
nikapov 0:11161008d77a 52 mSender(sender), mNTrials(OPENSESSION_NTRIALS){}
nikapov 0:11161008d77a 53
nikapov 0:11161008d77a 54 void NDefNfcTagM24SR::OpenSessionCallBack::on_session_open(M24SR *nfc, M24SR::StatusTypeDef status) {
nikapov 0:11161008d77a 55 if (status==M24SR::M24SR_SUCCESS) {
nikapov 0:11161008d77a 56 nfc->select_application();
nikapov 0:11161008d77a 57 } else {
nikapov 0:11161008d77a 58 mSender.mCallBack->on_session_open(&mSender,false);
nikapov 0:11161008d77a 59 }
nikapov 0:11161008d77a 60 }
nikapov 0:11161008d77a 61
nikapov 0:11161008d77a 62 void NDefNfcTagM24SR::OpenSessionCallBack::on_selected_application(M24SR *nfc, M24SR::StatusTypeDef status) {
nikapov 0:11161008d77a 63 if (status==M24SR::M24SR_SUCCESS) {
nikapov 0:11161008d77a 64 nfc->select_CC_file();
nikapov 0:11161008d77a 65 } else {
nikapov 0:11161008d77a 66 if (mNTrials==0) {
nikapov 0:11161008d77a 67 mSender.mCallBack->on_session_open(&mSender,false);
nikapov 0:11161008d77a 68 } else {
nikapov 0:11161008d77a 69 mNTrials--;
nikapov 0:11161008d77a 70 nfc->select_application();
nikapov 0:11161008d77a 71 }//if-else
nikapov 0:11161008d77a 72 }//if-else
nikapov 0:11161008d77a 73 }
nikapov 0:11161008d77a 74
nikapov 0:11161008d77a 75 void NDefNfcTagM24SR::OpenSessionCallBack::on_selected_CC_file(M24SR *nfc, M24SR::StatusTypeDef status) {
nikapov 0:11161008d77a 76 if (status==M24SR::M24SR_SUCCESS) {
nikapov 0:11161008d77a 77 nfc->read_binary(0x0000, CC_FILE_LENGTH_BYTE, CCFile);
nikapov 0:11161008d77a 78 } else {
nikapov 0:11161008d77a 79 mSender.mCallBack->on_session_open(&mSender,false);
nikapov 0:11161008d77a 80 }
nikapov 0:11161008d77a 81 }
nikapov 0:11161008d77a 82
nikapov 0:11161008d77a 83 void NDefNfcTagM24SR::OpenSessionCallBack::on_read_byte(M24SR *nfc, M24SR::StatusTypeDef status, uint16_t offset, uint8_t *readByte, uint16_t nReadByte) {
nikapov 0:11161008d77a 84 (void)offset;
nikapov 0:11161008d77a 85 if (status!=M24SR::M24SR_SUCCESS || nReadByte!=CC_FILE_LENGTH_BYTE) {
nikapov 0:11161008d77a 86 return mSender.mCallBack->on_session_open(&mSender,false);
nikapov 0:11161008d77a 87 }//else
nikapov 0:11161008d77a 88 uint16_t NDefFileId = (uint16_t) ((readByte[0x09] << 8) | readByte[0x0A]);
nikapov 0:11161008d77a 89 mSender.mMaxReadBytes = (uint16_t) ((readByte[0x03] << 8) | readByte[0x04]);
nikapov 0:11161008d77a 90 mSender.mMaxWriteBytes = (uint16_t) ((readByte[0x05] << 8) | readByte[0x06]);
nikapov 0:11161008d77a 91 nfc->select_NDEF_file(NDefFileId);
nikapov 0:11161008d77a 92 }
nikapov 0:11161008d77a 93
nikapov 0:11161008d77a 94 void NDefNfcTagM24SR::OpenSessionCallBack::on_selected_NDEF_file(M24SR *nfc, M24SR::StatusTypeDef status){
nikapov 0:11161008d77a 95 (void)nfc;
nikapov 0:11161008d77a 96
nikapov 0:11161008d77a 97 mSender.mIsSessionOpen = status==M24SR::M24SR_SUCCESS;
nikapov 0:11161008d77a 98 mSender.mCallBack->on_session_open(&mSender,mSender.mIsSessionOpen);
nikapov 0:11161008d77a 99 }
nikapov 0:11161008d77a 100 ////////////////////////////END OpenSessionCallBack/////////////////////////
nikapov 0:11161008d77a 101
nikapov 0:11161008d77a 102 bool NDefNfcTagM24SR::open_session(bool force) {
nikapov 0:11161008d77a 103
nikapov 0:11161008d77a 104 if (is_session_open()) {
nikapov 0:11161008d77a 105 mCallBack->on_session_open(this,true);
nikapov 0:11161008d77a 106 return true;
nikapov 0:11161008d77a 107 }
nikapov 0:11161008d77a 108
nikapov 0:11161008d77a 109 mDevice.set_callback(&mOpenSessionCallback);
nikapov 0:11161008d77a 110 if (force) {
nikapov 0:11161008d77a 111 return mDevice.force_get_session() == M24SR::M24SR_SUCCESS;
nikapov 0:11161008d77a 112 } else {
nikapov 0:11161008d77a 113 return mDevice.get_session() == M24SR::M24SR_SUCCESS;
nikapov 0:11161008d77a 114 }
nikapov 0:11161008d77a 115 }
nikapov 0:11161008d77a 116
nikapov 0:11161008d77a 117 bool NDefNfcTagM24SR::close_session() {
nikapov 0:11161008d77a 118 mDevice.set_callback(&mCloseSessionCallback);
nikapov 0:11161008d77a 119 return mDevice.deselect() == M24SR::M24SR_SUCCESS;
nikapov 0:11161008d77a 120 }
nikapov 0:11161008d77a 121
nikapov 0:11161008d77a 122 void NDefNfcTagM24SR::WriteByteCallback::on_updated_binary(M24SR *nfc,
nikapov 0:11161008d77a 123 M24SR::StatusTypeDef status,uint16_t startOffset, uint8_t *writeByte,uint16_t nWriteByte){
nikapov 0:11161008d77a 124
nikapov 0:11161008d77a 125 if (status!=M24SR::M24SR_SUCCESS){ // error -> finish to write
nikapov 0:11161008d77a 126 mCallback(mCallbackParam,false,mByteToWrite,mNByteToWrite);
nikapov 0:11161008d77a 127 return;
nikapov 0:11161008d77a 128 }//else
nikapov 0:11161008d77a 129
nikapov 0:11161008d77a 130 mByteWrote+=nWriteByte;
nikapov 0:11161008d77a 131 if (mByteWrote==mNByteToWrite) { //write all -> finish
nikapov 0:11161008d77a 132 mCallback(mCallbackParam,true,mByteToWrite,mNByteToWrite);
nikapov 0:11161008d77a 133 } else { //else write another slice
nikapov 0:11161008d77a 134 uint16_t tempLenght = std::min(mSender.mMaxWriteBytes, (uint16_t)(mNByteToWrite-mByteWrote));
nikapov 0:11161008d77a 135 nfc->update_binary(startOffset+nWriteByte,tempLenght,writeByte+nWriteByte);
nikapov 0:11161008d77a 136 }//if-else
nikapov 0:11161008d77a 137 }
nikapov 0:11161008d77a 138
nikapov 0:11161008d77a 139 bool NDefNfcTagM24SR::writeByte(const uint8_t *buffer, uint16_t length,uint16_t offset,
nikapov 0:11161008d77a 140 byteOperationCallback_t callback,CallbackStatus_t *callbackStatus){
nikapov 0:11161008d77a 141 if (!is_session_open())
nikapov 0:11161008d77a 142 callback(callbackStatus,false,buffer,length);
nikapov 0:11161008d77a 143 //else
nikapov 0:11161008d77a 144 mWriteByteCallback.set_task(buffer,length,callback,callbackStatus);
nikapov 0:11161008d77a 145 mDevice.set_callback(&mWriteByteCallback);
nikapov 0:11161008d77a 146
nikapov 0:11161008d77a 147 if (length > mMaxWriteBytes) {
nikapov 0:11161008d77a 148 return mDevice.update_binary(offset, mMaxWriteBytes,(uint8_t*) buffer) == M24SR::M24SR_SUCCESS;
nikapov 0:11161008d77a 149 } else {
nikapov 0:11161008d77a 150 return mDevice.update_binary(offset,length,(uint8_t*)buffer) == M24SR::M24SR_SUCCESS;
nikapov 0:11161008d77a 151 }//if-else
nikapov 0:11161008d77a 152 }
nikapov 0:11161008d77a 153
nikapov 0:11161008d77a 154 void NDefNfcTagM24SR::ReadByteCallback::on_read_byte(M24SR *nfc,
nikapov 0:11161008d77a 155 M24SR::StatusTypeDef status,uint16_t startOffset, uint8_t *readBffer,uint16_t nReadByte){
nikapov 0:11161008d77a 156
nikapov 0:11161008d77a 157 if (status!=M24SR::M24SR_SUCCESS) { // error -> finish to write
nikapov 0:11161008d77a 158 mCallback(mCallbackParam,false,mBuffer,mNByteToRead);
nikapov 0:11161008d77a 159 return;
nikapov 0:11161008d77a 160 }//else
nikapov 0:11161008d77a 161
nikapov 0:11161008d77a 162 mByteRead += nReadByte;
nikapov 0:11161008d77a 163 if (mByteRead==mNByteToRead) { //read all -> finish
nikapov 0:11161008d77a 164 mCallback(mCallbackParam,true,mBuffer,mNByteToRead);
nikapov 0:11161008d77a 165 } else { //else write another slice
nikapov 0:11161008d77a 166 uint16_t tempLenght = std::min(mSender.mMaxReadBytes, (uint16_t)(mNByteToRead-mByteRead));
nikapov 0:11161008d77a 167 nfc->read_binary(startOffset+nReadByte,tempLenght,readBffer+nReadByte);
nikapov 0:11161008d77a 168 }//if-else
nikapov 0:11161008d77a 169 }
nikapov 0:11161008d77a 170
nikapov 0:11161008d77a 171 bool NDefNfcTagM24SR::readByte(const uint16_t byteOffset, const uint16_t length,
nikapov 0:11161008d77a 172 uint8_t *buffer, byteOperationCallback_t callback,CallbackStatus_t *callbackStatus) {
nikapov 0:11161008d77a 173 if (!is_session_open()) {
nikapov 0:11161008d77a 174 return callback(callbackStatus,false,buffer,length);
nikapov 0:11161008d77a 175 }
nikapov 0:11161008d77a 176 //else
nikapov 0:11161008d77a 177 mReadByteCallback.set_task(buffer,length,callback,callbackStatus);
nikapov 0:11161008d77a 178 mDevice.set_callback(&mReadByteCallback);
nikapov 0:11161008d77a 179
nikapov 0:11161008d77a 180 if (length > mMaxReadBytes) {
nikapov 0:11161008d77a 181 return mDevice.read_binary(byteOffset, mMaxReadBytes,buffer)== M24SR::M24SR_SUCCESS;;
nikapov 0:11161008d77a 182 } else {
nikapov 0:11161008d77a 183 return mDevice.read_binary(byteOffset,length,buffer)== M24SR::M24SR_SUCCESS;;
nikapov 0:11161008d77a 184 }//if-else
nikapov 0:11161008d77a 185 }