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_rf.c
00001 /* 00002 * Copyright (c) 2014-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_rf.c 00019 * \copyright Copyright (c) ARM Ltd 2014 00020 * \author Donatien Garnier 00021 */ 00022 00023 #define __DEBUG__ 0 00024 #ifndef __MODULE__ 00025 #define __MODULE__ "pn512_rf.c" 00026 #endif 00027 00028 #include "stack/nfc_errors.h" 00029 00030 #include "pn512_callback.h" 00031 #include "pn512_rf.h" 00032 #include "pn512_registers.h" 00033 #include "pn512_timer.h" 00034 #include "pn512_irq.h" 00035 #include "pn512.h" 00036 #include "pn512_internal.h" 00037 00038 #include "stdlib.h" //For rand() func 00039 00040 #define PN512_FRAMING_REGS 6 00041 static const uint8_t framing_registers[] = { PN512_REG_MODE, PN512_REG_TXMODE, PN512_REG_RXMODE, PN512_REG_MODGSP, PN512_REG_RXTHRESHOLD, PN512_REG_MODWIDTH }; 00042 static const uint8_t framing_registers_mode_detector[] = { 0x3B, 0x80, 0x80, 0x3F, 0x55, 0x26 }; 00043 static const uint8_t framing_registers_initiator_iso14443a_106k[] = { 0x3D, 0x80, 0x80, 0x3F, 0x55, 0x26 }; 00044 static const uint8_t framing_registers_initiator_iso14443b_106k[] = { 0x3F, 0x83, 0x83, 0x04, 0x50, 0x26 }; 00045 static const uint8_t framing_registers_target_iso14443a_106k[] = { 0x3D, 0x80, 0x80, 0x3F, 0x55, 0x26 }; 00046 static const uint8_t framing_registers_felica_212k[] = { 0x3A, 0x92, 0x92, 0x12, 0x55, 0x15 }; 00047 static const uint8_t framing_registers_felica_414k[] = { 0x3A, 0xA2, 0xA2, 0x12, 0x55, 0x0A }; 00048 00049 nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing) 00050 { 00051 if (framing == pPN512->framing) { //No need to do anything 00052 return NFC_OK; 00053 } 00054 00055 NFC_DBG("Switching to %u", framing); 00056 00057 const uint8_t *framing_registers_values; 00058 switch (framing) { 00059 case nfc_framing_target_mode_detector: 00060 framing_registers_values = framing_registers_mode_detector; 00061 break; 00062 case nfc_framing_target_a_106: 00063 framing_registers_values = framing_registers_target_iso14443a_106k; 00064 break; 00065 case nfc_framing_initiator_a_106: 00066 framing_registers_values = framing_registers_initiator_iso14443a_106k; 00067 break; 00068 case nfc_framing_initiator_b_106: 00069 framing_registers_values = framing_registers_initiator_iso14443b_106k; 00070 break; 00071 case nfc_framing_target_f_212: 00072 case nfc_framing_initiator_f_212: 00073 framing_registers_values = framing_registers_felica_212k; 00074 break; 00075 case nfc_framing_target_f_424: 00076 case nfc_framing_initiator_f_424: 00077 framing_registers_values = framing_registers_felica_414k; 00078 break; 00079 default: 00080 return NFC_ERR_UNSUPPORTED; 00081 } 00082 00083 for (int i = 0; i < PN512_FRAMING_REGS; i++) { 00084 pn512_register_write(pPN512, framing_registers[i], framing_registers_values[i]); 00085 } 00086 00087 pPN512->framing = framing; 00088 pPN512->crc.out = true; 00089 pPN512->crc.in = true; 00090 00091 //TODO initiator: PN512_REG_MODGSP 00092 00093 switch (pPN512->framing) { 00094 case nfc_framing_initiator_a_106: 00095 case nfc_framing_initiator_b_106: 00096 case nfc_framing_initiator_f_212: 00097 case nfc_framing_initiator_f_424: 00098 pn512_register_write(pPN512, PN512_REG_CONTROL, 0x10); //Act as initiator 00099 break; 00100 case nfc_framing_target_mode_detector: 00101 case nfc_framing_target_a_106: 00102 case nfc_framing_target_f_212: 00103 case nfc_framing_target_f_424: 00104 pn512_register_write(pPN512, PN512_REG_CONTROL, 0x00); //Act as target 00105 break; 00106 default: 00107 return NFC_ERR_UNSUPPORTED; 00108 } 00109 #if 1 00110 if ((pPN512->framing == nfc_framing_initiator_a_106) /*|| (pPN512->framing == pn512_framing_target_iso14443a_106k)*/) { 00111 //Enable 100% ASK Modulation 00112 pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) | 0x40); 00113 } else { 00114 pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) & (~0x40)); 00115 } 00116 #endif 00117 return NFC_OK; 00118 } 00119 00120 nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in) 00121 { 00122 const uint8_t *framing_registers_values; 00123 switch (pPN512->framing) { 00124 case nfc_framing_target_mode_detector: 00125 framing_registers_values = framing_registers_mode_detector; 00126 break; 00127 case nfc_framing_target_a_106: 00128 framing_registers_values = framing_registers_target_iso14443a_106k; 00129 break; 00130 case nfc_framing_initiator_a_106: 00131 framing_registers_values = framing_registers_initiator_iso14443a_106k; 00132 break; 00133 case nfc_framing_initiator_b_106: 00134 framing_registers_values = framing_registers_initiator_iso14443b_106k; 00135 break; 00136 case nfc_framing_target_f_212: 00137 case nfc_framing_initiator_f_212: 00138 framing_registers_values = framing_registers_felica_212k; 00139 break; 00140 case nfc_framing_target_f_424: 00141 case nfc_framing_initiator_f_424: 00142 framing_registers_values = framing_registers_felica_414k; 00143 break; 00144 default: 00145 return NFC_ERR_UNSUPPORTED; 00146 } 00147 00148 if (pPN512->crc.out != out) { 00149 pn512_register_write(pPN512, framing_registers[1], (framing_registers_values[1] & 0x7F) | (out ? 0x80 : 0x00)); //TXMODE 00150 pPN512->crc.out = out; 00151 } 00152 if (pPN512->crc.in != in) { 00153 pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (in ? 0x80 : 0x00)); //RXMODE 00154 pPN512->crc.in = in; 00155 } 00156 00157 return NFC_OK; 00158 } 00159 00160 nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512) 00161 { 00162 const uint8_t *framing_registers_values; 00163 switch (pPN512->framing) { 00164 case nfc_framing_target_mode_detector: 00165 framing_registers_values = framing_registers_mode_detector; 00166 break; 00167 case nfc_framing_target_a_106: 00168 framing_registers_values = framing_registers_target_iso14443a_106k; 00169 break; 00170 case nfc_framing_initiator_a_106: 00171 framing_registers_values = framing_registers_initiator_iso14443a_106k; 00172 break; 00173 case nfc_framing_initiator_b_106: 00174 framing_registers_values = framing_registers_initiator_iso14443b_106k; 00175 break; 00176 case nfc_framing_target_f_212: 00177 case nfc_framing_initiator_f_212: 00178 framing_registers_values = framing_registers_felica_212k; 00179 break; 00180 case nfc_framing_target_f_424: 00181 case nfc_framing_initiator_f_424: 00182 framing_registers_values = framing_registers_felica_414k; 00183 break; 00184 default: 00185 return NFC_ERR_UNSUPPORTED; 00186 } 00187 00188 pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (pPN512->crc.in ? 0x80 : 0x00) | 0x04); //RXMODE 00189 00190 return NFC_OK; 00191 } 00192 00193 void pn512_rf_field_switch_off(pn512_t *pPN512) 00194 { 00195 pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); 00196 pn512_register_write(pPN512, PN512_REG_TXCONTROL, 0x80); 00197 pPN512->rf_on = false; 00198 } 00199 00200 void pn512_rf_field_nfcip1_rf_collision_avoidance_complete(uint32_t events, void *pUserData) 00201 { 00202 pn512_t *pPN512 = (pn512_t *) pUserData; 00203 00204 uint16_t irq_res = pn512_irq_get(pPN512); 00205 00206 (void) events; 00207 00208 pn512_timer_stop(pPN512); 00209 pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart 00210 pn512_irq_set(pPN512, PN512_IRQ_NONE); 00211 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); 00212 00213 if (irq_res & PN512_IRQ_RF_ON) { 00214 NFC_DBG("External field on"); 00215 00216 //Clear TXAUTO register 00217 pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); 00218 00219 pPN512->rf_on = false; //External field on 00220 pn512_rf_callback(pPN512, NFC_OK); 00221 return; 00222 } 00223 00224 //Has our RF field been switched on? 00225 if (pn512_register_read(pPN512, PN512_REG_TXAUTO) & 0x40) { //InitialRFOn bit is cleared automatically, if the RF field is switched on 00226 NFC_ERR("InitialRFOn bit still set"); 00227 pn512_rf_callback(pPN512, NFC_ERR_UNKNOWN); 00228 return; 00229 } 00230 00231 pPN512->rf_on = true; //Own field on and guard time ok 00232 00233 NFC_DBG("RF field enabled"); 00234 pn512_rf_callback(pPN512, NFC_OK); 00235 } 00236 00237 void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb) 00238 { 00239 pPN512->rf.cb = cb; 00240 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); 00241 00242 //If our field is switched on, Wait TIRFG according to NFC-IP1 = 5ms => 67800 clock edges = (3+1)*8475 00243 pn512_timer_config(pPN512, true, 3, 8475); 00244 00245 pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */ 00246 | PN512_IRQ_TIMER /* Timer reached 0 */); 00247 00248 //Try to enable RF field in compliance with NFC-IP1 00249 pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x0F); 00250 00251 //Is external RF Field already on? 00252 if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { 00253 NFC_DBG("External field already on"); 00254 pPN512->rf_on = false; //External field on 00255 00256 //Cancel 00257 pn512_timer_stop(pPN512); 00258 pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart 00259 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); 00260 pn512_rf_callback(pPN512, NFC_OK); 00261 return; 00262 } 00263 00264 //Queue task to process IRQ 00265 task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, -1, pn512_rf_field_nfcip1_rf_collision_avoidance_complete, pPN512); 00266 nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); 00267 } 00268 00269 void pn512_rf_field_wait_for_external_complete_task(uint32_t events, void *pUserData) 00270 { 00271 pn512_t *pPN512 = (pn512_t *) pUserData; 00272 00273 NFC_DBG("%lu events", events); 00274 00275 //Wake up PN512 00276 pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); 00277 while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10); 00278 00279 pn512_irq_set(pPN512, PN512_IRQ_NONE); 00280 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); 00281 00282 if (events & EVENT_ABORTED) { 00283 pn512_rf_callback(pPN512, NFC_ERR_ABORTED); 00284 return; 00285 } 00286 00287 if (events & EVENT_TIMEOUT) { 00288 NFC_DBG("Timeout"); 00289 pn512_rf_callback(pPN512, NFC_ERR_TIMEOUT); 00290 return; 00291 } 00292 00293 NFC_DBG("On"); 00294 pn512_rf_callback(pPN512, NFC_OK); 00295 } 00296 00297 void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb) 00298 { 00299 pPN512->rf.cb = cb; 00300 00301 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); 00302 00303 NFC_DBG("Wait for RF field to come up (timeout %d)", timeout); 00304 00305 //Is external RF Field already on? 00306 pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */); 00307 if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { 00308 NFC_DBG("RF field already on"); 00309 pn512_irq_set(pPN512, PN512_IRQ_NONE); 00310 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); 00311 00312 pn512_rf_callback(pPN512, NFC_OK); 00313 return; 00314 } 00315 00316 //Send PN512 to sleep mode 00317 pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down 00318 00319 //Queue task to process IRQ 00320 task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, timeout, pn512_rf_field_wait_for_external_complete_task, pPN512); 00321 nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); 00322 } 00323 00324 00325 00326
Generated on Tue Aug 9 2022 00:37:17 by
1.7.2