+// Send one downlink command to the card
+void T55xx_SendCMD (uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg) { //, bool read_cmd) {//, struct T55xx_Timing *Timing) {
+
+ /*
+ arg bits
+ xxxxxxx1 0x01 PwdMode
+ xxxxxx1x 0x02 Page
+ xxxxx1xx 0x04 testMode
+ xxx11xxx 0x18 downlink mode
+ xx1xxxxx 0x20 reg_readmode
+ x1xxxxxx 0x40 called for a read, so no data packet
+
+ */
+ bool PwdMode = ((arg & 0x01) == 0x01);
+ uint8_t Page = (arg & 0x02) >> 1;
+ bool testMode = ((arg & 0x04) == 0x04);
+ uint8_t downlink_mode = (arg >> 3) & 0x03;
+ bool reg_readmode = ((arg & 0x20) == 0x20);
+ bool read_cmd = ((arg & 0x40) == 0x40);
+ uint8_t i = 0;
+ uint8_t BitStream[10]; // Max Downlink Command size ~74 bits, so 10 bytes (80 bits)
+ uint8_t BitStreamLen;
+ T55xx_Timing *Timing;
+ uint8_t SendBits;
+
+ // Assigning Downlink Timeing for write
+ switch (downlink_mode)
+ {
+ case T55xx_DLMode_Fixed : Timing = &T55xx_Timing_FixedBit; break;
+ case T55xx_DLMode_LLR : Timing = &T55xx_Timing_LLR; break;
+ case T55xx_DLMode_Leading0 : Timing = &T55xx_Timing_Leading0; break;
+ case T55xx_DLMode_1of4 : Timing = &T55xx_Timing_1of4; break;
+ default:
+ Timing = &T55xx_Timing_FixedBit;
+ }
+
+ // Build Bit Stream to send.
+ memset (BitStream,0x00,sizeof(BitStream));
+
+ BitStreamLen = 0;
+
+ // Add Leading 0 and 1 of 4 reference bit
+ if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4))
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
+
+ // Add extra reference 0 for 1 of 4
+ if (downlink_mode == T55xx_DLMode_1of4)
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
+
+ // Add Opcode
+ if (testMode) Dbprintf("TestMODE");
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 0 : 1 , 1,sizeof(BitStream));
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen,testMode ? 1 : Page , 1,sizeof(BitStream));
+
+ if (PwdMode) {
+ // Leading 0 and 1 of 4 00 fixed bits if passsword used
+ if ((downlink_mode == T55xx_DLMode_Leading0) || (downlink_mode == T55xx_DLMode_1of4)) {
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
+ }
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Pwd, 32,sizeof(BitStream));
+ }
+
+ // Add Lock bit 0
+ BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, 0, 1,sizeof(BitStream));
+
+ // Add Data if a write command
+ if (!read_cmd) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Data, 32,sizeof(BitStream));
+
+ // Add Address
+ if (!reg_readmode) BitStreamLen = T55xx_SetBits (BitStream, BitStreamLen, Block, 3,sizeof(BitStream));
+
+ // Send Bits to T55xx
+ // Set up FPGA, 125kHz
+ LFSetupFPGAForADC(95, true);
+ StartTicks();
+ // make sure tag is fully powered up...
+ WaitMS(5);
+ // Trigger T55x7 in mode.
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(Timing->START_GAP);
+
+ // If long leading 0 send long reference pulse
+ if (downlink_mode == T55xx_DLMode_LLR)
+ T55xxWriteBit (T55xx_LongLeadingReference,Timing); // Send Long Leading Start Reference
+
+ if (downlink_mode == T55xx_DLMode_1of4) { // 1 of 4 need to send 2 bits at a time
+ for ( i = 0; i < BitStreamLen; i+=2 ) {
+ SendBits = (BitStream[BitStream_Byte(i )] >> (BitStream_Bit(i )) & 1) << 1; // Bit i
+ SendBits += (BitStream[BitStream_Byte(i+1)] >> (BitStream_Bit(i+1)) & 1); // Bit i+1;
+ T55xxWriteBit (SendBits & 3,Timing);
+ }
+ }
+ else {
+ for (i = 0; i < BitStreamLen; i++) {
+ SendBits = (BitStream[BitStream_Byte(i)] >> BitStream_Bit(i));
+ T55xxWriteBit (SendBits & 1,Timing);
+ }
+ }
+}