Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pn512.c Source File

pn512.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 /**
00018  * \file pn512.c
00019  * \copyright Copyright (c) ARM Ltd 2013
00020  * \author Donatien Garnier
00021  * \details PN512 implementation of the transceiver interface
00022  */
00023 
00024 #define __DEBUG__ 4
00025 #ifndef __MODULE__
00026 #define __MODULE__ "pn512.c"
00027 #endif
00028 #include "stack/nfc_errors.h"
00029 
00030 #include "stdlib.h"
00031 
00032 #include "acore/ac_buffer.h"
00033 
00034 #include "transceiver/transceiver.h"
00035 #include "transceiver/protocols.h"
00036 #include "pn512_rf.h"
00037 #include "pn512_registers.h"
00038 #include "pn512_cmd.h"
00039 #include "pn512_hw.h"
00040 #include "pn512_irq.h"
00041 #include "pn512_poll.h"
00042 #include "pn512_transceive.h"
00043 #include "pn512_internal.h"
00044 
00045 #include "pn512.h"
00046 
00047 #define DEFAULT_READER_TRANSCEIVE_TIMEOUT 100
00048 #define DEFAULT_TARGET_TRANSCEIVE_TIMEOUT -1
00049 
00050 
00051 //Prototypes
00052 #include "pn512_internal.h"
00053 
00054 /** \addtogroup PN512
00055  *  @{
00056  *  \name Transceiver
00057  *  \details Implementation of the transceiver interface
00058  *  @{
00059  */
00060 
00061 //PN 512 VTABLE
00062 
00063 static const transceiver_impl_t pn512_impl = {
00064     .set_protocols = pn512_set_protocols,
00065     .poll = pn512_poll,
00066     .transceive = pn512_transceive,
00067     .abort = pn512_abort,
00068     .set_crc = pn512_set_crc,
00069     .set_timeout = pn512_set_timeout,
00070     .set_transceive_options = pn512_set_transceive_options,
00071     .set_transceive_framing = pn512_set_transceive_framing,
00072     .set_write = pn512_set_write,
00073     .get_read = pn512_get_read,
00074     .set_last_byte_length = pn512_set_last_byte_length,
00075     .get_last_byte_length = pn512_get_last_byte_length,
00076     .set_first_byte_align = pn512_set_first_byte_align,
00077     .close = pn512_close,
00078     .sleep = pn512_sleep
00079 };
00080 
00081 /** Initialize PN512 transceiver
00082  * \param pPN512 pointer to pn512_t structure to initialize
00083  * \param pTransport pointer to already initialized nfc_transport_t structure
00084  * \return NFC_OK (0) on success or NFC_ERR_* error on failure
00085  */
00086 nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer)
00087 {
00088     ////
00089     //For Self-test
00090     ////
00091 #if NFC_PN512_SELFTEST
00092     const uint8_t null_array[25] = {0};
00093 #endif
00094     ////
00095     uint8_t r;
00096 
00097     //Init transceiver
00098     transceiver_init((nfc_transceiver_t *)pPN512, pTransport, pTimer);
00099 
00100     //Init buffer
00101     ac_buffer_builder_init(&pPN512->readBufBldr, pPN512->payload, 256);
00102 
00103     pPN512->readFirstByteAlign = 0;
00104     pPN512->readLastByteLength = 8;
00105     pPN512->writeLastByteLength = 8;
00106 
00107     //Populate functions
00108     pPN512->transceiver.fn = &pn512_impl;
00109 
00110     //Init variables
00111     memset(&pPN512->config.initiators, 0, sizeof(nfc_tech_t));
00112     memset(&pPN512->config.targets, 0, sizeof(nfc_tech_t));
00113     pPN512->timeout = -1;
00114     pPN512->nextFrameMode = pn512_transceive_mode_transceive;
00115 
00116     pn512_hw_init(pPN512);
00117     pn512_registers_init(pPN512); //Cannot switch page now
00118     pn512_cmd_init(pPN512);
00119 
00120     pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST);
00121     pn512_cmd_wait_idle(pPN512, -1);
00122 
00123     //pn512_registers_init(pPN512);
00124     //Put into known state
00125     pn512_registers_reset(pPN512);
00126 
00127     pPN512->transceive.mode = pn512_transceive_mode_idle;
00128 
00129     pn512_irq_clear(pPN512, PN512_IRQ_ALL);
00130     pn512_fifo_clear(pPN512);
00131     pn512_cmd_exec(pPN512, PN512_CMD_IDLE);
00132     pn512_cmd_wait_idle(pPN512, -1);
00133 
00134     pn512_rf_field_switch_off(pPN512);
00135 
00136     //Required for polling loop
00137     srand(4242);
00138 
00139 #if NFC_PN512_SELFTEST // Self test
00140     pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST);
00141     pn512_cmd_wait_idle(pPN512, -1);
00142 
00143     const uint8_t null_array_buf[25] = {0}; //FIXME
00144     ac_buffer_t null_array;
00145     ac_buffer_init(&null_array, null_array_buf, 25);
00146 
00147     //Perform self test
00148     pn512_fifo_write(pPN512, &null_array);
00149     pn512_cmd_exec(pPN512, PN512_CMD_CONFIG);
00150     while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE);
00151     pn512_register_write(pPN512, PN512_REG_AUTOTEST, 0x09);
00152 
00153     ac_buffer_init(&null_array, null_array_buf, 1);
00154 
00155     pn512_fifo_write(pPN512, &null_array);
00156     pn512_cmd_exec(pPN512, PN512_CMD_CRC);
00157     while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE);
00158 
00159     DBGX_ENTER();
00160     NFC_DBG("Test result:");
00161     while (pn512_fifo_length(pPN512)) {
00162         ac_buffer_builder_t read_byte;
00163         ac_buffer_builder_init(&read_byte, null_array_buf, 1);
00164 
00165         pn512_fifo_read(pPN512, &read_byte);
00166         DBGX("%02x ", null_array_buf[0]);
00167     }
00168     DBGX("\n");
00169     DBGX_LEAVE();
00170 #endif
00171 
00172     r = pn512_register_read(pPN512, PN512_REG_VERSION);
00173 
00174     NFC_DBG_BLOCK(
00175         NFC_DBG("PN512 version %02x", r);
00176     )
00177 
00178     if ((r != 0x82) && (r != 0xB1) && (r != 0xB2)) {
00179         return NFC_ERR_UNSUPPORTED; //PN512 not found
00180     }
00181 
00182     return NFC_OK;
00183 }
00184 
00185 /** Get pointer to nfc_transceiver_t structure
00186  * \param pPN512 pointer to pn512_t instance
00187  * \return pointer to initialized nfc_transceiver_t instance
00188  */
00189 nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512)
00190 {
00191     return &pPN512->transceiver;
00192 }
00193 
00194 void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options)
00195 {
00196     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00197     //If different, reconfigure
00198     if (memcmp(&initiators, &pPN512->config.initiators, sizeof(nfc_tech_t)) || memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) {
00199         pPN512->config.initiators = initiators;
00200         if (memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) {
00201             pPN512->config.targets = targets;
00202             pn512_poll_setup(pPN512);
00203         }
00204         pTransceiver->initiator_ntarget = false;
00205         memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t));
00206     }
00207     pPN512->config.options = options;
00208 }
00209 
00210 void pn512_poll(nfc_transceiver_t *pTransceiver)
00211 {
00212     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00213     pPN512->nextFrameMode = pn512_transceive_mode_transceive;
00214     pn512_poll_hw(pPN512, pn512_transceiver_callback);
00215 }
00216 
00217 void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in)
00218 {
00219     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00220     pn512_framing_crc_set(pPN512, crc_out, crc_in);
00221 }
00222 
00223 void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout)
00224 {
00225     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00226     pPN512->timeout = timeout;
00227 }
00228 
00229 void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll)
00230 {
00231     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00232     if (transmit && receive) {
00233         pPN512->nextFrameMode = pn512_transceive_mode_transceive;
00234     } else if (transmit && repoll) {
00235         pPN512->nextFrameMode = pn512_transceive_mode_transmit_and_target_autocoll;
00236     } else if (transmit) {
00237         pPN512->nextFrameMode = pn512_transceive_mode_transmit;
00238     } else if (receive) {
00239         pPN512->nextFrameMode = pn512_transceive_mode_receive;
00240     } else {
00241         pPN512->nextFrameMode = pn512_transceive_mode_target_autocoll;
00242     }
00243 }
00244 
00245 void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing)
00246 {
00247     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00248     pn512_framing_set(pPN512, framing);
00249 
00250     //Switch NFC tech if NFC DEP
00251     if (pTransceiver->active_tech.nfc_nfc_dep_a
00252             || pTransceiver->active_tech.nfc_nfc_dep_f_212
00253             || pTransceiver->active_tech.nfc_nfc_dep_f_424) {
00254         //FIXME
00255         pTransceiver->active_tech.nfc_nfc_dep_a = 0;
00256         pTransceiver->active_tech.nfc_nfc_dep_f_212 = 0;
00257         pTransceiver->active_tech.nfc_nfc_dep_f_424 = 0;
00258         switch (framing) {
00259             case nfc_framing_target_a_106:
00260             case nfc_framing_initiator_a_106:
00261                 pTransceiver->active_tech.nfc_nfc_dep_a = 1;
00262                 break;
00263             case nfc_framing_target_f_212:
00264             case nfc_framing_initiator_f_212:
00265                 pTransceiver->active_tech.nfc_nfc_dep_f_212 = 1;
00266                 break;
00267             case nfc_framing_target_f_424:
00268             case nfc_framing_initiator_f_424:
00269                 pTransceiver->active_tech.nfc_nfc_dep_f_424 = 1;
00270                 break;
00271             default:
00272                 break;
00273         }
00274     }
00275 }
00276 
00277 void pn512_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf)
00278 {
00279     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00280     if (pWriteBuf == NULL) {
00281         ac_buffer_init(&pPN512->writeBuf, NULL, 0);
00282         return;
00283     }
00284     ac_buffer_dup(&pPN512->writeBuf, pWriteBuf);
00285 }
00286 
00287 ac_buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver)
00288 {
00289     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00290     return ac_buffer_builder_buffer(&pPN512->readBufBldr);
00291 }
00292 
00293 void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength)
00294 {
00295     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00296     if ((lastByteLength > 8) || (lastByteLength == 0)) {
00297         lastByteLength = 8;
00298     }
00299     pPN512->writeLastByteLength = lastByteLength;
00300 }
00301 
00302 void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign)
00303 {
00304     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00305     firstByteAlign &= 0x7;
00306     pPN512->readFirstByteAlign = firstByteAlign;
00307 }
00308 
00309 size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver)
00310 {
00311     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00312     return pPN512->readLastByteLength;
00313 }
00314 
00315 void pn512_transceive(nfc_transceiver_t *pTransceiver)
00316 {
00317     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00318     pn512_transceive_hw(pPN512, pPN512->nextFrameMode, pn512_transceiver_callback);
00319     pPN512->nextFrameMode = pn512_transceive_mode_transceive;
00320 }
00321 
00322 void pn512_abort(nfc_transceiver_t *pTransceiver)
00323 {
00324     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00325     nfc_scheduler_dequeue_task(&pTransceiver->scheduler, true, &pPN512->transceiver.task);
00326 }
00327 
00328 void pn512_close(nfc_transceiver_t *pTransceiver)
00329 {
00330     //pn512_t* pPN512 = (pn512_t*) pTransceiver;
00331     (void) pTransceiver;
00332     //TODO
00333     return;
00334 }
00335 
00336 void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep)
00337 {
00338     pn512_t *pPN512 = (pn512_t *) pTransceiver;
00339 
00340     if (sleep) {
00341         pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down
00342     } else {
00343         pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00);
00344         while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10);
00345     }
00346 }
00347 
00348 void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret)
00349 {
00350     transceiver_callback(&pPN512->transceiver, ret);
00351 }
00352 
00353 /**
00354  * @}
00355  * @}
00356  * */