Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pn512.c
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 * */
Generated on Tue Jul 12 2022 13:53:31 by
1.7.2