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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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:54:41 by
