+ return 0;
+}
+
+int EmSend4bitEx(uint8_t resp, bool correctionNeeded){
+ Code4bitAnswerAsTag(resp);
+ int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded);
+ // do the tracing for the previous reader request and this tag answer:
+ uint8_t par[1];
+ GetParity(&resp, 1, par);
+ EmLogTrace(Uart.output,
+ Uart.len,
+ Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG,
+ Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG,
+ Uart.parity,
+ &resp,
+ 1,
+ LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG,
+ (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG,
+ par);
+ return res;
+}
+
+int EmSend4bit(uint8_t resp){
+ return EmSend4bitEx(resp, false);
+}
+
+int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par){
+ CodeIso14443aAsTagPar(resp, respLen, par);
+ int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded);
+ // do the tracing for the previous reader request and this tag answer:
+ EmLogTrace(Uart.output,
+ Uart.len,
+ Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG,
+ Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG,
+ Uart.parity,
+ resp,
+ respLen,
+ LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG,
+ (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG,
+ par);
+ return res;
+}
+
+int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded){
+ uint8_t par[MAX_PARITY_SIZE];
+ GetParity(resp, respLen, par);
+ return EmSendCmdExPar(resp, respLen, correctionNeeded, par);
+}
+
+int EmSendCmd(uint8_t *resp, uint16_t respLen){
+ uint8_t par[MAX_PARITY_SIZE];
+ GetParity(resp, respLen, par);
+ return EmSendCmdExPar(resp, respLen, false, par);
+}
+
+int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){
+ return EmSendCmdExPar(resp, respLen, false, par);
+}
+
+bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
+ uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity)
+{
+ if (tracing) {
+ // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from
+ // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp.
+ // with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated:
+ uint16_t reader_modlen = reader_EndTime - reader_StartTime;
+ uint16_t approx_fdt = tag_StartTime - reader_EndTime;
+ uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20;
+ reader_EndTime = tag_StartTime - exact_fdt;
+ reader_StartTime = reader_EndTime - reader_modlen;
+ if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) {
+ return FALSE;
+ } else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, FALSE));
+ } else {
+ return TRUE;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Wait a certain time for tag response
+// If a response is captured return TRUE
+// If it takes too long return FALSE
+//-----------------------------------------------------------------------------
+static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset)
+{
+ uint32_t c = 0x00;
+
+ // Set FPGA mode to "reader listen mode", no modulation (listen
+ // only, since we are receiving, not transmitting).
+ // Signal field is on with the appropriate LED
+ LED_D_ON();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
+
+ // Now get the answer from the card
+ DemodInit(receivedResponse, receivedResponsePar);
+
+ // clear RXRDY:
+ uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+
+ for(;;) {
+ WDT_HIT();
+
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+ if(ManchesterDecoding(b, offset, 0)) {
+ NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD);
+ return TRUE;
+ } else if (c++ > iso14a_timeout && Demod.state == DEMOD_UNSYNCD) {
+ return FALSE;
+ }
+ }
+ }
+}
+
+
+void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
+{
+ CodeIso14443aBitsAsReaderPar(frame, bits, par);
+
+ // Send command to tag
+ TransmitFor14443a(ToSend, ToSendMax, timing);
+ if(trigger)
+ LED_A_ON();
+
+ // Log reader command in trace buffer
+ if (tracing) {
+ LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, TRUE);
+ }
+}
+
+
+void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
+{
+ ReaderTransmitBitsPar(frame, len*8, par, timing);
+}
+
+
+void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
+{
+ // Generate parity and redirect
+ uint8_t par[MAX_PARITY_SIZE];
+ GetParity(frame, len/8, par);
+ ReaderTransmitBitsPar(frame, len, par, timing);