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.
Dependencies: nRF51_Vdd TextLCD BME280
TYBLE16_os5_BASE/features/nfc/stack/transceiver/pn512/pn512_transceive.c@6:6dd8c932bd56, 2019-12-19 (annotated)
- Committer:
- kenjiArai
- Date:
- Thu Dec 19 07:27:50 2019 +0000
- Revision:
- 6:6dd8c932bd56
- Parent:
- 4:e9dfb4ca4277
updated each main.cpp
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| kenjiArai | 4:e9dfb4ca4277 | 1 | /* |
| kenjiArai | 4:e9dfb4ca4277 | 2 | * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved |
| kenjiArai | 4:e9dfb4ca4277 | 3 | * SPDX-License-Identifier: Apache-2.0 |
| kenjiArai | 4:e9dfb4ca4277 | 4 | * |
| kenjiArai | 4:e9dfb4ca4277 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| kenjiArai | 4:e9dfb4ca4277 | 6 | * not use this file except in compliance with the License. |
| kenjiArai | 4:e9dfb4ca4277 | 7 | * You may obtain a copy of the License at |
| kenjiArai | 4:e9dfb4ca4277 | 8 | * |
| kenjiArai | 4:e9dfb4ca4277 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| kenjiArai | 4:e9dfb4ca4277 | 10 | * |
| kenjiArai | 4:e9dfb4ca4277 | 11 | * Unless required by applicable law or agreed to in writing, software |
| kenjiArai | 4:e9dfb4ca4277 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| kenjiArai | 4:e9dfb4ca4277 | 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| kenjiArai | 4:e9dfb4ca4277 | 14 | * See the License for the specific language governing permissions and |
| kenjiArai | 4:e9dfb4ca4277 | 15 | * limitations under the License. |
| kenjiArai | 4:e9dfb4ca4277 | 16 | */ |
| kenjiArai | 4:e9dfb4ca4277 | 17 | /** |
| kenjiArai | 4:e9dfb4ca4277 | 18 | * \file pn512_transceive.c |
| kenjiArai | 4:e9dfb4ca4277 | 19 | * \copyright Copyright (c) ARM Ltd 2014 |
| kenjiArai | 4:e9dfb4ca4277 | 20 | * \author Donatien Garnier |
| kenjiArai | 4:e9dfb4ca4277 | 21 | */ |
| kenjiArai | 4:e9dfb4ca4277 | 22 | |
| kenjiArai | 4:e9dfb4ca4277 | 23 | #define __DEBUG__ 0 |
| kenjiArai | 4:e9dfb4ca4277 | 24 | #ifndef __MODULE__ |
| kenjiArai | 4:e9dfb4ca4277 | 25 | #define __MODULE__ "pn512_transceive.c" |
| kenjiArai | 4:e9dfb4ca4277 | 26 | #endif |
| kenjiArai | 4:e9dfb4ca4277 | 27 | |
| kenjiArai | 4:e9dfb4ca4277 | 28 | #include "stack/nfc_errors.h" |
| kenjiArai | 4:e9dfb4ca4277 | 29 | |
| kenjiArai | 4:e9dfb4ca4277 | 30 | #include "pn512.h" |
| kenjiArai | 4:e9dfb4ca4277 | 31 | #include "pn512_transceive.h" |
| kenjiArai | 4:e9dfb4ca4277 | 32 | #include "pn512_rf.h" |
| kenjiArai | 4:e9dfb4ca4277 | 33 | #include "pn512_irq.h" |
| kenjiArai | 4:e9dfb4ca4277 | 34 | #include "pn512_cmd.h" |
| kenjiArai | 4:e9dfb4ca4277 | 35 | #include "pn512_registers.h" |
| kenjiArai | 4:e9dfb4ca4277 | 36 | #include "pn512_internal.h" |
| kenjiArai | 4:e9dfb4ca4277 | 37 | |
| kenjiArai | 4:e9dfb4ca4277 | 38 | |
| kenjiArai | 4:e9dfb4ca4277 | 39 | #define TIMEOUT 1000 |
| kenjiArai | 4:e9dfb4ca4277 | 40 | |
| kenjiArai | 4:e9dfb4ca4277 | 41 | void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start) |
| kenjiArai | 4:e9dfb4ca4277 | 42 | { |
| kenjiArai | 4:e9dfb4ca4277 | 43 | uint16_t irqs_en = pn512_irq_enabled(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 44 | |
| kenjiArai | 4:e9dfb4ca4277 | 45 | if (ac_buffer_reader_readable(&pPN512->writeBuf) > 0) { |
| kenjiArai | 4:e9dfb4ca4277 | 46 | //Fill FIFO |
| kenjiArai | 4:e9dfb4ca4277 | 47 | pn512_fifo_write(pPN512, &pPN512->writeBuf); |
| kenjiArai | 4:e9dfb4ca4277 | 48 | |
| kenjiArai | 4:e9dfb4ca4277 | 49 | if (ac_buffer_reader_readable(&pPN512->writeBuf) > 0) { //Did not fit in FIFO |
| kenjiArai | 4:e9dfb4ca4277 | 50 | pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); |
| kenjiArai | 4:e9dfb4ca4277 | 51 | //Has low FIFO alert IRQ already been enabled? |
| kenjiArai | 4:e9dfb4ca4277 | 52 | if (!(irqs_en & PN512_IRQ_LOW_ALERT)) { |
| kenjiArai | 4:e9dfb4ca4277 | 53 | irqs_en |= PN512_IRQ_LOW_ALERT; |
| kenjiArai | 4:e9dfb4ca4277 | 54 | pn512_irq_set(pPN512, irqs_en); |
| kenjiArai | 4:e9dfb4ca4277 | 55 | } |
| kenjiArai | 4:e9dfb4ca4277 | 56 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 57 | if (irqs_en & PN512_IRQ_LOW_ALERT) { |
| kenjiArai | 4:e9dfb4ca4277 | 58 | //Buffer has been fully sent |
| kenjiArai | 4:e9dfb4ca4277 | 59 | irqs_en &= ~PN512_IRQ_LOW_ALERT; |
| kenjiArai | 4:e9dfb4ca4277 | 60 | pn512_irq_set(pPN512, irqs_en); |
| kenjiArai | 4:e9dfb4ca4277 | 61 | } |
| kenjiArai | 4:e9dfb4ca4277 | 62 | } |
| kenjiArai | 4:e9dfb4ca4277 | 63 | } |
| kenjiArai | 4:e9dfb4ca4277 | 64 | |
| kenjiArai | 4:e9dfb4ca4277 | 65 | |
| kenjiArai | 4:e9dfb4ca4277 | 66 | if (start) { |
| kenjiArai | 4:e9dfb4ca4277 | 67 | if ((pPN512->transceive.mode == pn512_transceive_mode_transmit) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) { |
| kenjiArai | 4:e9dfb4ca4277 | 68 | //Update bitframing register |
| kenjiArai | 4:e9dfb4ca4277 | 69 | pn512_register_write(pPN512, PN512_REG_BITFRAMING, |
| kenjiArai | 4:e9dfb4ca4277 | 70 | 0x00 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); |
| kenjiArai | 4:e9dfb4ca4277 | 71 | |
| kenjiArai | 4:e9dfb4ca4277 | 72 | //Use transmit command |
| kenjiArai | 4:e9dfb4ca4277 | 73 | pn512_cmd_exec(pPN512, PN512_CMD_TRANSMIT); |
| kenjiArai | 4:e9dfb4ca4277 | 74 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 75 | NFC_DBG("Bitframing %02X", 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); |
| kenjiArai | 4:e9dfb4ca4277 | 76 | //Update bitframing register to start transmission |
| kenjiArai | 4:e9dfb4ca4277 | 77 | pn512_register_write(pPN512, PN512_REG_BITFRAMING, |
| kenjiArai | 4:e9dfb4ca4277 | 78 | 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); |
| kenjiArai | 4:e9dfb4ca4277 | 79 | } |
| kenjiArai | 4:e9dfb4ca4277 | 80 | |
| kenjiArai | 4:e9dfb4ca4277 | 81 | //Reset last byte length, first byte align |
| kenjiArai | 4:e9dfb4ca4277 | 82 | pPN512->writeLastByteLength = 8; |
| kenjiArai | 4:e9dfb4ca4277 | 83 | pPN512->readFirstByteAlign = 0; |
| kenjiArai | 4:e9dfb4ca4277 | 84 | } |
| kenjiArai | 4:e9dfb4ca4277 | 85 | |
| kenjiArai | 4:e9dfb4ca4277 | 86 | //Queue task to process IRQ |
| kenjiArai | 4:e9dfb4ca4277 | 87 | task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, TIMEOUT, pn512_transceive_hw_tx_task, pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 88 | nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); |
| kenjiArai | 4:e9dfb4ca4277 | 89 | } |
| kenjiArai | 4:e9dfb4ca4277 | 90 | |
| kenjiArai | 4:e9dfb4ca4277 | 91 | void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData) |
| kenjiArai | 4:e9dfb4ca4277 | 92 | { |
| kenjiArai | 4:e9dfb4ca4277 | 93 | pn512_t *pPN512 = (pn512_t *) pUserData; |
| kenjiArai | 4:e9dfb4ca4277 | 94 | |
| kenjiArai | 4:e9dfb4ca4277 | 95 | if (events & EVENT_ABORTED) { |
| kenjiArai | 4:e9dfb4ca4277 | 96 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 97 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 98 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 99 | |
| kenjiArai | 4:e9dfb4ca4277 | 100 | NFC_ERR("Aborted TX"); |
| kenjiArai | 4:e9dfb4ca4277 | 101 | |
| kenjiArai | 4:e9dfb4ca4277 | 102 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 103 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 104 | |
| kenjiArai | 4:e9dfb4ca4277 | 105 | pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); |
| kenjiArai | 4:e9dfb4ca4277 | 106 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 107 | } |
| kenjiArai | 4:e9dfb4ca4277 | 108 | |
| kenjiArai | 4:e9dfb4ca4277 | 109 | NFC_DBG("TX task"); |
| kenjiArai | 4:e9dfb4ca4277 | 110 | if (events & EVENT_TIMEOUT) { |
| kenjiArai | 4:e9dfb4ca4277 | 111 | // Check status |
| kenjiArai | 4:e9dfb4ca4277 | 112 | NFC_DBG("Status = %02X %02X", pn512_register_read(pPN512, PN512_REG_STATUS1), pn512_register_read(pPN512, PN512_REG_STATUS2)); |
| kenjiArai | 4:e9dfb4ca4277 | 113 | |
| kenjiArai | 4:e9dfb4ca4277 | 114 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 115 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 116 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 117 | |
| kenjiArai | 4:e9dfb4ca4277 | 118 | NFC_ERR("Timeout on TX"); |
| kenjiArai | 4:e9dfb4ca4277 | 119 | |
| kenjiArai | 4:e9dfb4ca4277 | 120 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 121 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 122 | |
| kenjiArai | 4:e9dfb4ca4277 | 123 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 124 | pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT); |
| kenjiArai | 4:e9dfb4ca4277 | 125 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 126 | } |
| kenjiArai | 4:e9dfb4ca4277 | 127 | |
| kenjiArai | 4:e9dfb4ca4277 | 128 | uint16_t irqs_en = pn512_irq_enabled(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 129 | uint16_t irqs = pn512_irq_get(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 130 | |
| kenjiArai | 4:e9dfb4ca4277 | 131 | if (irqs & PN512_IRQ_RF_OFF) { |
| kenjiArai | 4:e9dfb4ca4277 | 132 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 133 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 134 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 135 | |
| kenjiArai | 4:e9dfb4ca4277 | 136 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 137 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 138 | NFC_WARN("RF Off"); |
| kenjiArai | 4:e9dfb4ca4277 | 139 | pn512_transceive_callback(pPN512, NFC_ERR_FIELD); |
| kenjiArai | 4:e9dfb4ca4277 | 140 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 141 | } |
| kenjiArai | 4:e9dfb4ca4277 | 142 | if (irqs & PN512_IRQ_TX) { |
| kenjiArai | 4:e9dfb4ca4277 | 143 | if (irqs_en & PN512_IRQ_LOW_ALERT) { |
| kenjiArai | 4:e9dfb4ca4277 | 144 | //If the transmission has been completed without us getting a chance to fill the buffer up it means that we had a buffer underflow |
| kenjiArai | 4:e9dfb4ca4277 | 145 | NFC_ERR("Buffer underflow"); |
| kenjiArai | 4:e9dfb4ca4277 | 146 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 147 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 148 | |
| kenjiArai | 4:e9dfb4ca4277 | 149 | pn512_transceive_callback(pPN512, NFC_ERR_UNDERFLOW); |
| kenjiArai | 4:e9dfb4ca4277 | 150 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 151 | } |
| kenjiArai | 4:e9dfb4ca4277 | 152 | |
| kenjiArai | 4:e9dfb4ca4277 | 153 | //Transmission complete |
| kenjiArai | 4:e9dfb4ca4277 | 154 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 155 | pn512_irq_clear(pPN512, PN512_IRQ_TX | PN512_IRQ_LOW_ALERT); |
| kenjiArai | 4:e9dfb4ca4277 | 156 | |
| kenjiArai | 4:e9dfb4ca4277 | 157 | //Start receiving |
| kenjiArai | 4:e9dfb4ca4277 | 158 | NFC_DBG("Transmission complete"); |
| kenjiArai | 4:e9dfb4ca4277 | 159 | if (pPN512->transceive.mode != pn512_transceive_mode_transmit) { |
| kenjiArai | 4:e9dfb4ca4277 | 160 | if (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) { |
| kenjiArai | 4:e9dfb4ca4277 | 161 | //Make sure bitframing reg is clean |
| kenjiArai | 4:e9dfb4ca4277 | 162 | pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); |
| kenjiArai | 4:e9dfb4ca4277 | 163 | |
| kenjiArai | 4:e9dfb4ca4277 | 164 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 165 | pn512_transceive_hw_rx_start(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 166 | |
| kenjiArai | 4:e9dfb4ca4277 | 167 | //Start autocoll |
| kenjiArai | 4:e9dfb4ca4277 | 168 | pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); |
| kenjiArai | 4:e9dfb4ca4277 | 169 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 170 | pn512_transceive_hw_rx_start(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 171 | } |
| kenjiArai | 4:e9dfb4ca4277 | 172 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 173 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 174 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 175 | pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); |
| kenjiArai | 4:e9dfb4ca4277 | 176 | |
| kenjiArai | 4:e9dfb4ca4277 | 177 | pn512_transceive_callback(pPN512, NFC_OK); |
| kenjiArai | 4:e9dfb4ca4277 | 178 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 179 | } |
| kenjiArai | 4:e9dfb4ca4277 | 180 | } |
| kenjiArai | 4:e9dfb4ca4277 | 181 | if ((irqs & PN512_IRQ_LOW_ALERT) && (ac_buffer_reader_readable(&pPN512->writeBuf) > 0)) { |
| kenjiArai | 4:e9dfb4ca4277 | 182 | //Continue to fill FIFO |
| kenjiArai | 4:e9dfb4ca4277 | 183 | pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); |
| kenjiArai | 4:e9dfb4ca4277 | 184 | |
| kenjiArai | 4:e9dfb4ca4277 | 185 | pn512_transceive_hw_tx_iteration(pPN512, false); |
| kenjiArai | 4:e9dfb4ca4277 | 186 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 187 | } |
| kenjiArai | 4:e9dfb4ca4277 | 188 | |
| kenjiArai | 4:e9dfb4ca4277 | 189 | if (irqs & PN512_IRQ_IDLE) { |
| kenjiArai | 4:e9dfb4ca4277 | 190 | pn512_irq_clear(pPN512, PN512_IRQ_ERR); |
| kenjiArai | 4:e9dfb4ca4277 | 191 | |
| kenjiArai | 4:e9dfb4ca4277 | 192 | NFC_ERR("Modem went to idle"); |
| kenjiArai | 4:e9dfb4ca4277 | 193 | |
| kenjiArai | 4:e9dfb4ca4277 | 194 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 195 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 196 | |
| kenjiArai | 4:e9dfb4ca4277 | 197 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 198 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 199 | pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); |
| kenjiArai | 4:e9dfb4ca4277 | 200 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 201 | } |
| kenjiArai | 4:e9dfb4ca4277 | 202 | |
| kenjiArai | 4:e9dfb4ca4277 | 203 | //Call back function |
| kenjiArai | 4:e9dfb4ca4277 | 204 | pn512_transceive_hw_tx_iteration(pPN512, false); |
| kenjiArai | 4:e9dfb4ca4277 | 205 | } |
| kenjiArai | 4:e9dfb4ca4277 | 206 | |
| kenjiArai | 4:e9dfb4ca4277 | 207 | void pn512_transceive_hw_rx_start(pn512_t *pPN512) |
| kenjiArai | 4:e9dfb4ca4277 | 208 | { |
| kenjiArai | 4:e9dfb4ca4277 | 209 | uint16_t irqs_en = PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_ERR; |
| kenjiArai | 4:e9dfb4ca4277 | 210 | if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { |
| kenjiArai | 4:e9dfb4ca4277 | 211 | irqs_en |= PN512_IRQ_RF_OFF; |
| kenjiArai | 4:e9dfb4ca4277 | 212 | } |
| kenjiArai | 4:e9dfb4ca4277 | 213 | |
| kenjiArai | 4:e9dfb4ca4277 | 214 | pn512_irq_set(pPN512, irqs_en); |
| kenjiArai | 4:e9dfb4ca4277 | 215 | |
| kenjiArai | 4:e9dfb4ca4277 | 216 | //Reset buffer except if data should be appended to this -- TODO |
| kenjiArai | 4:e9dfb4ca4277 | 217 | ac_buffer_builder_reset(&pPN512->readBufBldr); |
| kenjiArai | 4:e9dfb4ca4277 | 218 | |
| kenjiArai | 4:e9dfb4ca4277 | 219 | //Queue task to process IRQ |
| kenjiArai | 4:e9dfb4ca4277 | 220 | task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, |
| kenjiArai | 4:e9dfb4ca4277 | 221 | pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 222 | nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, |
| kenjiArai | 4:e9dfb4ca4277 | 223 | &pPN512->transceiver.task); |
| kenjiArai | 4:e9dfb4ca4277 | 224 | } |
| kenjiArai | 4:e9dfb4ca4277 | 225 | |
| kenjiArai | 4:e9dfb4ca4277 | 226 | void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData) |
| kenjiArai | 4:e9dfb4ca4277 | 227 | { |
| kenjiArai | 4:e9dfb4ca4277 | 228 | pn512_t *pPN512 = (pn512_t *) pUserData; |
| kenjiArai | 4:e9dfb4ca4277 | 229 | |
| kenjiArai | 4:e9dfb4ca4277 | 230 | NFC_DBG("RX task"); |
| kenjiArai | 4:e9dfb4ca4277 | 231 | if (events & EVENT_ABORTED) { |
| kenjiArai | 4:e9dfb4ca4277 | 232 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 233 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 234 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 235 | |
| kenjiArai | 4:e9dfb4ca4277 | 236 | NFC_ERR("Aborted RX"); |
| kenjiArai | 4:e9dfb4ca4277 | 237 | |
| kenjiArai | 4:e9dfb4ca4277 | 238 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 239 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 240 | |
| kenjiArai | 4:e9dfb4ca4277 | 241 | pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); |
| kenjiArai | 4:e9dfb4ca4277 | 242 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 243 | } |
| kenjiArai | 4:e9dfb4ca4277 | 244 | |
| kenjiArai | 4:e9dfb4ca4277 | 245 | if (events & EVENT_TIMEOUT) { |
| kenjiArai | 4:e9dfb4ca4277 | 246 | NFC_WARN("Timeout"); |
| kenjiArai | 4:e9dfb4ca4277 | 247 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 248 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 249 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 250 | |
| kenjiArai | 4:e9dfb4ca4277 | 251 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 252 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 253 | |
| kenjiArai | 4:e9dfb4ca4277 | 254 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 255 | pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT); |
| kenjiArai | 4:e9dfb4ca4277 | 256 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 257 | } |
| kenjiArai | 4:e9dfb4ca4277 | 258 | |
| kenjiArai | 4:e9dfb4ca4277 | 259 | uint16_t irqs = pn512_irq_get(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 260 | NFC_DBG("irqs %04x", irqs); |
| kenjiArai | 4:e9dfb4ca4277 | 261 | bool collision_detected = false; |
| kenjiArai | 4:e9dfb4ca4277 | 262 | if (irqs & PN512_IRQ_ERR) { |
| kenjiArai | 4:e9dfb4ca4277 | 263 | pn512_irq_clear(pPN512, PN512_IRQ_ERR); |
| kenjiArai | 4:e9dfb4ca4277 | 264 | |
| kenjiArai | 4:e9dfb4ca4277 | 265 | uint8_t err_reg = pn512_register_read(pPN512, PN512_REG_ERROR); |
| kenjiArai | 4:e9dfb4ca4277 | 266 | NFC_ERR("Got error - error reg is %02X", err_reg); |
| kenjiArai | 4:e9dfb4ca4277 | 267 | // if err_reg == 0, sticky error that must have been cleared automatically, continue |
| kenjiArai | 4:e9dfb4ca4277 | 268 | if (err_reg != 0) { |
| kenjiArai | 4:e9dfb4ca4277 | 269 | //If it's a collsision, flag it but still carry on with RX procedure |
| kenjiArai | 4:e9dfb4ca4277 | 270 | collision_detected = true; |
| kenjiArai | 4:e9dfb4ca4277 | 271 | |
| kenjiArai | 4:e9dfb4ca4277 | 272 | if ((err_reg == 0x08) || (err_reg == 0x0A)) { // Collision (and maybe parity) (and no other error) |
| kenjiArai | 4:e9dfb4ca4277 | 273 | irqs &= ~PN512_IRQ_ERR; |
| kenjiArai | 4:e9dfb4ca4277 | 274 | irqs |= PN512_IRQ_RX; |
| kenjiArai | 4:e9dfb4ca4277 | 275 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 276 | NFC_DBG_BLOCK( |
| kenjiArai | 4:e9dfb4ca4277 | 277 | //Empty FIFO into buffer |
| kenjiArai | 4:e9dfb4ca4277 | 278 | pn512_fifo_read(pPN512, &pPN512->readBufBldr); |
| kenjiArai | 4:e9dfb4ca4277 | 279 | |
| kenjiArai | 4:e9dfb4ca4277 | 280 | NFC_DBG("Received"); |
| kenjiArai | 4:e9dfb4ca4277 | 281 | ac_buffer_dump(ac_buffer_builder_buffer(&pPN512->readBufBldr)); |
| kenjiArai | 4:e9dfb4ca4277 | 282 | |
| kenjiArai | 4:e9dfb4ca4277 | 283 | NFC_DBG("Computed CRC = %02X %02X", pn512_register_read(pPN512, PN512_REG_CRCRESULT_MSB), pn512_register_read(pPN512, PN512_REG_CRCRESULT_LSB)); |
| kenjiArai | 4:e9dfb4ca4277 | 284 | |
| kenjiArai | 4:e9dfb4ca4277 | 285 | ) |
| kenjiArai | 4:e9dfb4ca4277 | 286 | |
| kenjiArai | 4:e9dfb4ca4277 | 287 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 288 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 289 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 290 | |
| kenjiArai | 4:e9dfb4ca4277 | 291 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 292 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 293 | |
| kenjiArai | 4:e9dfb4ca4277 | 294 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 295 | pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); |
| kenjiArai | 4:e9dfb4ca4277 | 296 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 297 | } |
| kenjiArai | 4:e9dfb4ca4277 | 298 | } |
| kenjiArai | 4:e9dfb4ca4277 | 299 | } |
| kenjiArai | 4:e9dfb4ca4277 | 300 | if ((irqs & PN512_IRQ_RX) || (irqs & PN512_IRQ_HIGH_ALERT)) { |
| kenjiArai | 4:e9dfb4ca4277 | 301 | //Empty FIFO into buffer |
| kenjiArai | 4:e9dfb4ca4277 | 302 | pn512_fifo_read(pPN512, &pPN512->readBufBldr); |
| kenjiArai | 4:e9dfb4ca4277 | 303 | |
| kenjiArai | 4:e9dfb4ca4277 | 304 | if ((ac_buffer_builder_writable(&pPN512->readBufBldr) == 0) && (pn512_fifo_length(pPN512) > 0)) { |
| kenjiArai | 4:e9dfb4ca4277 | 305 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 306 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 307 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 308 | |
| kenjiArai | 4:e9dfb4ca4277 | 309 | NFC_WARN("RX buffer overflow"); |
| kenjiArai | 4:e9dfb4ca4277 | 310 | |
| kenjiArai | 4:e9dfb4ca4277 | 311 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 312 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 313 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 314 | pn512_transceive_callback(pPN512, NFC_ERR_BUFFER_TOO_SMALL); |
| kenjiArai | 4:e9dfb4ca4277 | 315 | return; //overflow |
| kenjiArai | 4:e9dfb4ca4277 | 316 | } |
| kenjiArai | 4:e9dfb4ca4277 | 317 | |
| kenjiArai | 4:e9dfb4ca4277 | 318 | if (irqs & PN512_IRQ_HIGH_ALERT) { |
| kenjiArai | 4:e9dfb4ca4277 | 319 | NFC_DBG("High alert"); |
| kenjiArai | 4:e9dfb4ca4277 | 320 | pn512_irq_clear(pPN512, PN512_IRQ_HIGH_ALERT); |
| kenjiArai | 4:e9dfb4ca4277 | 321 | } |
| kenjiArai | 4:e9dfb4ca4277 | 322 | |
| kenjiArai | 4:e9dfb4ca4277 | 323 | if (irqs & PN512_IRQ_RX) { |
| kenjiArai | 4:e9dfb4ca4277 | 324 | pn512_irq_clear(pPN512, PN512_IRQ_RX); |
| kenjiArai | 4:e9dfb4ca4277 | 325 | |
| kenjiArai | 4:e9dfb4ca4277 | 326 | size_t last_byte_length = pn512_register_read(pPN512, PN512_REG_CONTROL) & 0x7; |
| kenjiArai | 4:e9dfb4ca4277 | 327 | if (last_byte_length == 0) { |
| kenjiArai | 4:e9dfb4ca4277 | 328 | last_byte_length = 8; |
| kenjiArai | 4:e9dfb4ca4277 | 329 | } |
| kenjiArai | 4:e9dfb4ca4277 | 330 | pPN512->readLastByteLength = last_byte_length; |
| kenjiArai | 4:e9dfb4ca4277 | 331 | |
| kenjiArai | 4:e9dfb4ca4277 | 332 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 333 | pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); |
| kenjiArai | 4:e9dfb4ca4277 | 334 | |
| kenjiArai | 4:e9dfb4ca4277 | 335 | NFC_DBG("Received:"); |
| kenjiArai | 4:e9dfb4ca4277 | 336 | NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pPN512->readBufBldr));) |
| kenjiArai | 4:e9dfb4ca4277 | 337 | |
| kenjiArai | 4:e9dfb4ca4277 | 338 | if ((pPN512->transceive.mode == pn512_transceive_mode_target_autocoll) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) { |
| kenjiArai | 4:e9dfb4ca4277 | 339 | //Check if target was activated |
| kenjiArai | 4:e9dfb4ca4277 | 340 | if (!(pn512_register_read(pPN512, PN512_REG_STATUS2) & 0x10)) { |
| kenjiArai | 4:e9dfb4ca4277 | 341 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 342 | |
| kenjiArai | 4:e9dfb4ca4277 | 343 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 344 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 345 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 346 | pn512_transceive_callback(pPN512, NFC_ERR_PROTOCOL); |
| kenjiArai | 4:e9dfb4ca4277 | 347 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 348 | } |
| kenjiArai | 4:e9dfb4ca4277 | 349 | //PN512 switches to transceive automatically |
| kenjiArai | 4:e9dfb4ca4277 | 350 | pPN512->transceive.mode = pn512_transceive_mode_transceive; |
| kenjiArai | 4:e9dfb4ca4277 | 351 | } else if (pPN512->transceive.mode == pn512_transceive_mode_receive) { |
| kenjiArai | 4:e9dfb4ca4277 | 352 | pPN512->transceive.mode = pn512_transceive_mode_transceive; |
| kenjiArai | 4:e9dfb4ca4277 | 353 | //pn512_cmd_exec(pPN512, PN512_CMD_IDLE); //Useful? |
| kenjiArai | 4:e9dfb4ca4277 | 354 | } |
| kenjiArai | 4:e9dfb4ca4277 | 355 | |
| kenjiArai | 4:e9dfb4ca4277 | 356 | if (!collision_detected) { |
| kenjiArai | 4:e9dfb4ca4277 | 357 | pn512_transceive_callback(pPN512, NFC_OK); |
| kenjiArai | 4:e9dfb4ca4277 | 358 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 359 | pn512_transceive_callback(pPN512, NFC_ERR_COLLISION); |
| kenjiArai | 4:e9dfb4ca4277 | 360 | } |
| kenjiArai | 4:e9dfb4ca4277 | 361 | |
| kenjiArai | 4:e9dfb4ca4277 | 362 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 363 | } |
| kenjiArai | 4:e9dfb4ca4277 | 364 | } |
| kenjiArai | 4:e9dfb4ca4277 | 365 | if (irqs & PN512_IRQ_RF_OFF) { |
| kenjiArai | 4:e9dfb4ca4277 | 366 | //Stop command |
| kenjiArai | 4:e9dfb4ca4277 | 367 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 368 | pPN512->transceive.mode = pn512_transceive_mode_idle; |
| kenjiArai | 4:e9dfb4ca4277 | 369 | |
| kenjiArai | 4:e9dfb4ca4277 | 370 | pn512_irq_set(pPN512, PN512_IRQ_NONE); |
| kenjiArai | 4:e9dfb4ca4277 | 371 | pn512_irq_clear(pPN512, PN512_IRQ_ALL); |
| kenjiArai | 4:e9dfb4ca4277 | 372 | |
| kenjiArai | 4:e9dfb4ca4277 | 373 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 374 | pn512_transceive_callback(pPN512, NFC_ERR_FIELD); |
| kenjiArai | 4:e9dfb4ca4277 | 375 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 376 | } |
| kenjiArai | 4:e9dfb4ca4277 | 377 | |
| kenjiArai | 4:e9dfb4ca4277 | 378 | //Queue task to process IRQ |
| kenjiArai | 4:e9dfb4ca4277 | 379 | task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, |
| kenjiArai | 4:e9dfb4ca4277 | 380 | pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 381 | nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, |
| kenjiArai | 4:e9dfb4ca4277 | 382 | &pPN512->transceiver.task); |
| kenjiArai | 4:e9dfb4ca4277 | 383 | } |
| kenjiArai | 4:e9dfb4ca4277 | 384 | |
| kenjiArai | 4:e9dfb4ca4277 | 385 | void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb) |
| kenjiArai | 4:e9dfb4ca4277 | 386 | { |
| kenjiArai | 4:e9dfb4ca4277 | 387 | uint16_t irqs_en; |
| kenjiArai | 4:e9dfb4ca4277 | 388 | |
| kenjiArai | 4:e9dfb4ca4277 | 389 | //Store callback |
| kenjiArai | 4:e9dfb4ca4277 | 390 | pPN512->transceive.cb = cb; |
| kenjiArai | 4:e9dfb4ca4277 | 391 | |
| kenjiArai | 4:e9dfb4ca4277 | 392 | //Clear FIFO |
| kenjiArai | 4:e9dfb4ca4277 | 393 | pn512_fifo_clear(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 394 | |
| kenjiArai | 4:e9dfb4ca4277 | 395 | //Clear previous IRQs if present |
| kenjiArai | 4:e9dfb4ca4277 | 396 | pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_TX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_LOW_ALERT | PN512_IRQ_ERR | PN512_IRQ_IDLE | PN512_IRQ_RF_OFF); |
| kenjiArai | 4:e9dfb4ca4277 | 397 | |
| kenjiArai | 4:e9dfb4ca4277 | 398 | if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { |
| kenjiArai | 4:e9dfb4ca4277 | 399 | //RF off? |
| kenjiArai | 4:e9dfb4ca4277 | 400 | if (!(pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x04)) { |
| kenjiArai | 4:e9dfb4ca4277 | 401 | //Call callback |
| kenjiArai | 4:e9dfb4ca4277 | 402 | pn512_transceive_callback(pPN512, NFC_ERR_FIELD); |
| kenjiArai | 4:e9dfb4ca4277 | 403 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 404 | } |
| kenjiArai | 4:e9dfb4ca4277 | 405 | } else if ((pPN512->transceive.mode != mode) && (mode == pn512_transceive_mode_transceive)) { |
| kenjiArai | 4:e9dfb4ca4277 | 406 | pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE); |
| kenjiArai | 4:e9dfb4ca4277 | 407 | } |
| kenjiArai | 4:e9dfb4ca4277 | 408 | |
| kenjiArai | 4:e9dfb4ca4277 | 409 | pPN512->transceive.mode = mode; |
| kenjiArai | 4:e9dfb4ca4277 | 410 | |
| kenjiArai | 4:e9dfb4ca4277 | 411 | if (mode == pn512_transceive_mode_receive) { |
| kenjiArai | 4:e9dfb4ca4277 | 412 | pn512_cmd_exec(pPN512, PN512_CMD_IDLE); |
| kenjiArai | 4:e9dfb4ca4277 | 413 | pn512_transceive_hw_rx_start(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 414 | pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE); |
| kenjiArai | 4:e9dfb4ca4277 | 415 | } else if (mode == pn512_transceive_mode_target_autocoll) { |
| kenjiArai | 4:e9dfb4ca4277 | 416 | //Make sure bitframing reg is clean |
| kenjiArai | 4:e9dfb4ca4277 | 417 | pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); |
| kenjiArai | 4:e9dfb4ca4277 | 418 | |
| kenjiArai | 4:e9dfb4ca4277 | 419 | pn512_transceive_hw_rx_start(pPN512); |
| kenjiArai | 4:e9dfb4ca4277 | 420 | |
| kenjiArai | 4:e9dfb4ca4277 | 421 | //Start autocoll |
| kenjiArai | 4:e9dfb4ca4277 | 422 | pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); |
| kenjiArai | 4:e9dfb4ca4277 | 423 | return; |
| kenjiArai | 4:e9dfb4ca4277 | 424 | } else { |
| kenjiArai | 4:e9dfb4ca4277 | 425 | NFC_DBG("Sending:"); |
| kenjiArai | 4:e9dfb4ca4277 | 426 | NFC_DBG_BLOCK(ac_buffer_dump(&pPN512->writeBuf);) |
| kenjiArai | 4:e9dfb4ca4277 | 427 | |
| kenjiArai | 4:e9dfb4ca4277 | 428 | //Transmit a frame to remote target/initiator |
| kenjiArai | 4:e9dfb4ca4277 | 429 | irqs_en = PN512_IRQ_TX | PN512_IRQ_IDLE; |
| kenjiArai | 4:e9dfb4ca4277 | 430 | if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { |
| kenjiArai | 4:e9dfb4ca4277 | 431 | irqs_en |= PN512_IRQ_RF_OFF; |
| kenjiArai | 4:e9dfb4ca4277 | 432 | } |
| kenjiArai | 4:e9dfb4ca4277 | 433 | |
| kenjiArai | 4:e9dfb4ca4277 | 434 | pn512_irq_set(pPN512, irqs_en); |
| kenjiArai | 4:e9dfb4ca4277 | 435 | |
| kenjiArai | 4:e9dfb4ca4277 | 436 | pn512_transceive_hw_tx_iteration(pPN512, true); |
| kenjiArai | 4:e9dfb4ca4277 | 437 | } |
| kenjiArai | 4:e9dfb4ca4277 | 438 | } |
| kenjiArai | 4:e9dfb4ca4277 | 439 | |
| kenjiArai | 4:e9dfb4ca4277 | 440 | |
| kenjiArai | 4:e9dfb4ca4277 | 441 |