+/* Perform the ISO 14443 B Card Selection procedure
+ * Currently does NOT do any collision handling.
+ * It expects 0-1 cards in the device's range.
+ * TODO: Support multiple cards (perform anticollision)
+ * TODO: Verify CRC checksums
+ */
+uint8_t iso14443b_select_card(iso14b_card_select_t *card )
+{
+ // WUPB command (including CRC)
+ // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
+ static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
+ // ATTRIB command (with space for CRC)
+ uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
+
+ // temp to calc crc.
+ uint8_t crc[2] = {0x00, 0x00};
+
+ // first, wake up the tag
+ CodeAndTransmit14443bAsReader(wupb, sizeof(wupb));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+
+ // ATQB too short?
+ if (Demod.len < 14) return 2;
+
+ // VALIDATE CRC
+ ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
+ if ( crc[0] != Demod.output[12] || crc[1] != Demod.output[13] )
+ return 3;
+
+ if (card) {
+ card->uidlen = 4;
+ memcpy(card->uid, Demod.output+1, 4);
+ memcpy(card->atqb, Demod.output+5, 7);
+ }
+
+ // copy the PUPI to ATTRIB
+ memcpy(attrib + 1, Demod.output + 1, 4);
+
+ // copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into ATTRIB (Param 3)
+ attrib[7] = Demod.output[10] & 0x0F;
+ ComputeCrc14443(CRC_14443_B, attrib, 9, attrib + 9, attrib + 10);
+
+ CodeAndTransmit14443bAsReader(attrib, sizeof(attrib));
+ GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE);
+
+ // Answer to ATTRIB too short?
+ if(Demod.len < 3) return 2;
+
+ // VALIDATE CRC
+ ComputeCrc14443(CRC_14443_B, Demod.output, Demod.len-2, &crc[0], &crc[1]);
+ if ( crc[0] != Demod.output[1] || crc[1] != Demod.output[2] )
+ return 3;
+
+ // CID
+ if (card) card->cid = Demod.output[0];
+
+ // reset PCB block number
+ pcb_blocknum = 0;
+ return 0;
+}
+
+// Set up ISO 14443 Type B communication (similar to iso14443a_setup)
+void iso14443b_setup() {
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+
+ BigBuf_free(); BigBuf_Clear_ext(false);
+ DemodReset();
+ UartReset();
+
+ // Set up the synchronous serial port
+ FpgaSetupSsc();
+
+ // connect Demodulated Signal to ADC:
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+ // Signal field is on with the appropriate LED
+ LED_D_ON();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
+ SpinDelay(400);