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_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 ( 00111 pPN512->framing == nfc_framing_initiator_a_106 00112 //|| (pPN512->framing == pn512_framing_target_iso14443a_106k) 00113 ) { 00114 //Enable 100% ASK Modulation 00115 pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) | 0x40); 00116 } else { 00117 pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) & (~0x40)); 00118 } 00119 #endif 00120 return NFC_OK; 00121 } 00122 00123 nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in) 00124 { 00125 const uint8_t *framing_registers_values; 00126 switch (pPN512->framing) { 00127 case nfc_framing_target_mode_detector: 00128 framing_registers_values = framing_registers_mode_detector; 00129 break; 00130 case nfc_framing_target_a_106: 00131 framing_registers_values = framing_registers_target_iso14443a_106k; 00132 break; 00133 case nfc_framing_initiator_a_106: 00134 framing_registers_values = framing_registers_initiator_iso14443a_106k; 00135 break; 00136 case nfc_framing_initiator_b_106: 00137 framing_registers_values = framing_registers_initiator_iso14443b_106k; 00138 break; 00139 case nfc_framing_target_f_212: 00140 case nfc_framing_initiator_f_212: 00141 framing_registers_values = framing_registers_felica_212k; 00142 break; 00143 case nfc_framing_target_f_424: 00144 case nfc_framing_initiator_f_424: 00145 framing_registers_values = framing_registers_felica_414k; 00146 break; 00147 default: 00148 return NFC_ERR_UNSUPPORTED; 00149 } 00150 00151 if (pPN512->crc.out != out) { 00152 pn512_register_write(pPN512, framing_registers[1], (framing_registers_values[1] & 0x7F) | (out ? 0x80 : 0x00)); //TXMODE 00153 pPN512->crc.out = out; 00154 } 00155 if (pPN512->crc.in != in) { 00156 pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (in ? 0x80 : 0x00)); //RXMODE 00157 pPN512->crc.in = in; 00158 } 00159 00160 return NFC_OK; 00161 } 00162 00163 nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512) 00164 { 00165 const uint8_t *framing_registers_values; 00166 switch (pPN512->framing) { 00167 case nfc_framing_target_mode_detector: 00168 framing_registers_values = framing_registers_mode_detector; 00169 break; 00170 case nfc_framing_target_a_106: 00171 framing_registers_values = framing_registers_target_iso14443a_106k; 00172 break; 00173 case nfc_framing_initiator_a_106: 00174 framing_registers_values = framing_registers_initiator_iso14443a_106k; 00175 break; 00176 case nfc_framing_initiator_b_106: 00177 framing_registers_values = framing_registers_initiator_iso14443b_106k; 00178 break; 00179 case nfc_framing_target_f_212: 00180 case nfc_framing_initiator_f_212: 00181 framing_registers_values = framing_registers_felica_212k; 00182 break; 00183 case nfc_framing_target_f_424: 00184 case nfc_framing_initiator_f_424: 00185 framing_registers_values = framing_registers_felica_414k; 00186 break; 00187 default: 00188 return NFC_ERR_UNSUPPORTED; 00189 } 00190 00191 pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (pPN512->crc.in ? 0x80 : 0x00) | 0x04); //RXMODE 00192 00193 return NFC_OK; 00194 } 00195 00196 void pn512_rf_field_switch_off(pn512_t *pPN512) 00197 { 00198 pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); 00199 pn512_register_write(pPN512, PN512_REG_TXCONTROL, 0x80); 00200 pPN512->rf_on = false; 00201 } 00202 00203 void pn512_rf_field_nfcip1_rf_collision_avoidance_complete(uint32_t events, void *pUserData) 00204 { 00205 pn512_t *pPN512 = (pn512_t *) pUserData; 00206 00207 uint16_t irq_res = pn512_irq_get(pPN512); 00208 00209 (void) events; 00210 00211 pn512_timer_stop(pPN512); 00212 pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart 00213 pn512_irq_set(pPN512, PN512_IRQ_NONE); 00214 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); 00215 00216 if (irq_res & PN512_IRQ_RF_ON) { 00217 NFC_DBG("External field on"); 00218 00219 //Clear TXAUTO register 00220 pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); 00221 00222 pPN512->rf_on = false; //External field on 00223 pn512_rf_callback(pPN512, NFC_OK); 00224 return; 00225 } 00226 00227 //Has our RF field been switched on? 00228 if (pn512_register_read(pPN512, PN512_REG_TXAUTO) & 0x40) { //InitialRFOn bit is cleared automatically, if the RF field is switched on 00229 NFC_ERR("InitialRFOn bit still set"); 00230 pn512_rf_callback(pPN512, NFC_ERR_UNKNOWN); 00231 return; 00232 } 00233 00234 pPN512->rf_on = true; //Own field on and guard time ok 00235 00236 NFC_DBG("RF field enabled"); 00237 pn512_rf_callback(pPN512, NFC_OK); 00238 } 00239 00240 void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb) 00241 { 00242 pPN512->rf.cb = cb; 00243 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); 00244 00245 //If our field is switched on, Wait TIRFG according to NFC-IP1 = 5ms => 67800 clock edges = (3+1)*8475 00246 pn512_timer_config(pPN512, true, 3, 8475); 00247 00248 pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */ 00249 | PN512_IRQ_TIMER /* Timer reached 0 */); 00250 00251 //Try to enable RF field in compliance with NFC-IP1 00252 pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x0F); 00253 00254 //Is external RF Field already on? 00255 if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { 00256 NFC_DBG("External field already on"); 00257 pPN512->rf_on = false; //External field on 00258 00259 //Cancel 00260 pn512_timer_stop(pPN512); 00261 pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart 00262 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); 00263 pn512_rf_callback(pPN512, NFC_OK); 00264 return; 00265 } 00266 00267 //Queue task to process IRQ 00268 task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, -1, pn512_rf_field_nfcip1_rf_collision_avoidance_complete, pPN512); 00269 nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); 00270 } 00271 00272 void pn512_rf_field_wait_for_external_complete_task(uint32_t events, void *pUserData) 00273 { 00274 pn512_t *pPN512 = (pn512_t *) pUserData; 00275 00276 NFC_DBG("%lu events", events); 00277 00278 //Wake up PN512 00279 pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); 00280 while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10); 00281 00282 pn512_irq_set(pPN512, PN512_IRQ_NONE); 00283 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); 00284 00285 if (events & EVENT_ABORTED) { 00286 pn512_rf_callback(pPN512, NFC_ERR_ABORTED); 00287 return; 00288 } 00289 00290 if (events & EVENT_TIMEOUT) { 00291 NFC_DBG("Timeout"); 00292 pn512_rf_callback(pPN512, NFC_ERR_TIMEOUT); 00293 return; 00294 } 00295 00296 NFC_DBG("On"); 00297 pn512_rf_callback(pPN512, NFC_OK); 00298 } 00299 00300 void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb) 00301 { 00302 pPN512->rf.cb = cb; 00303 00304 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); 00305 00306 NFC_DBG("Wait for RF field to come up (timeout %d)", timeout); 00307 00308 //Is external RF Field already on? 00309 pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */); 00310 if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { 00311 NFC_DBG("RF field already on"); 00312 pn512_irq_set(pPN512, PN512_IRQ_NONE); 00313 pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); 00314 00315 pn512_rf_callback(pPN512, NFC_OK); 00316 return; 00317 } 00318 00319 //Send PN512 to sleep mode 00320 pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down 00321 00322 //Queue task to process IRQ 00323 task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, timeout, pn512_rf_field_wait_for_external_complete_task, pPN512); 00324 nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); 00325 } 00326 00327 00328 00329
Generated on Tue Jul 12 2022 13:54:41 by
1.7.2