/* * jtag.cpp * * Created on: May 24, 2017 * Author: justin */ #include "jtag.h" #include #include #include #include #include #ifdef _WIN32 #include "mingw.thread.h" #else #include #endif #include using namespace std; Jtag::Jtag() { ftHandle = 0; active = false; } FT_STATUS Jtag::connect(unsigned int devNumber) { return FT_Open(devNumber, &ftHandle); } FT_STATUS Jtag::disconnect() { active = false; return FT_Close(ftHandle); } bool Jtag::initialize() { BYTE byInputBuffer[1024]; // Buffer to hold data read from the FT2232H DWORD dwNumBytesToRead = 0; // Number of bytes available to read in the driver's input buffer DWORD dwNumBytesRead = 0; // Count of actual bytes read - used with FT_Read FT_STATUS ftStatus; ftStatus = FT_ResetDevice(ftHandle); //Reset USB device //Purge USB receive buffer first by reading out all old data from FT2232H receive buffer ftStatus |= FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); // Get the number of bytes in the FT2232H receive buffer if ((ftStatus == FT_OK) && (dwNumBytesToRead > 0)) FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead);//Read out the data from FT2232H receive buffer ftStatus |= FT_SetUSBParameters(ftHandle, 65536, 65535);//Set USB request transfer sizes to 64K ftStatus |= FT_SetChars(ftHandle, false, 0, false, 0); //Disable event and error characters ftStatus |= FT_SetTimeouts(ftHandle, 0, 5000); //Sets the read and write timeouts in milliseconds ftStatus |= FT_SetLatencyTimer(ftHandle, 16); //Set the latency timer (default is 16mS) ftStatus |= FT_SetBitMode(ftHandle, 0x0, 0x00); //Reset controller ftStatus |= FT_SetBitMode(ftHandle, 0x0, 0x02); //Enable MPSSE mode if (ftStatus != FT_OK) { cerr << "Failed to set initial configuration!" << endl; return false; } std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait for all the USB stuff to complete and work if (!sync_mpsse()) { cerr << "Failed to sync with MPSSE!" << endl; return false; } if (!config_jtag()) { cerr << "Failed to set JTAG configuration!" << endl; return false; } active = true; return true; } bool Jtag::sync_mpsse() { BYTE byOutputBuffer[8]; // Buffer to hold MPSSE commands and data to be sent to the FT2232H BYTE byInputBuffer[8]; // Buffer to hold data read from the FT2232H DWORD dwCount = 0; // General loop index DWORD dwNumBytesToSend = 0; // Index to the output buffer DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write DWORD dwNumBytesToRead = 0; // Number of bytes available to read in the driver's input buffer DWORD dwNumBytesRead = 0; // Count of actual bytes read - used with FT_Read FT_STATUS ftStatus; byOutputBuffer[dwNumBytesToSend++] = 0xAA; //'\xAA'; //Add bogus command ‘xAA’ to the queue ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); if (ftStatus != FT_OK) cerr << "Failed to send bad command" << endl; // Send off the BAD commands dwNumBytesToSend = 0; // Reset output buffer pointer do { ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); if (ftStatus != FT_OK) cerr << "Failed to get queue status " << ftStatus << endl; // Get the number of bytes in the device input buffer } while ((dwNumBytesToRead == 0) && (ftStatus == FT_OK)); if (dwNumBytesRead > 8) { cerr << "Input buffer too small in sync_mpsse()!" << endl; return false; } //or Timeout bool bCommandEchod = false; ftStatus = FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) cerr << "Failed to read data" << endl; //Read out the data from input buffer for (dwCount = 0; dwCount < dwNumBytesRead - 1; dwCount++) //Check if Bad command and echo command received { if ((byInputBuffer[dwCount] == 0xFA) && (byInputBuffer[dwCount + 1] == 0xAA)) { bCommandEchod = true; break; } } return bCommandEchod; } bool Jtag::config_jtag() { FT_STATUS ftStatus; BYTE byOutputBuffer[64]; // Buffer to hold MPSSE commands and data to be sent to the FT2232H DWORD dwNumBytesToSend = 0; // Index to the output buffer DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write DWORD dwClockDivisor = 0x05DB; // Value of clock divisor, SCL Frequency = 60/((1+0x05DB)*2) (MHz) = 20khz // ----------------------------------------------------------- // Configure the MPSSE settings for JTAG // Multiple commands can be sent to the MPSSE with one FT_Write // ----------------------------------------------------------- dwNumBytesToSend = 0; // Start with a fresh index // Set up the Hi-Speed specific commands for the FTx232H byOutputBuffer[dwNumBytesToSend++] = 0x8A; // Use 60MHz master clock (disable divide by 5) byOutputBuffer[dwNumBytesToSend++] = 0x97; // Turn off adaptive clocking (may be needed for ARM) byOutputBuffer[dwNumBytesToSend++] = 0x8D; // Disable three-phase clocking ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the HS-specific commands if (ftStatus != FT_OK) return false; dwNumBytesToSend = 0; // Reset output buffer pointer // Set initial states of the MPSSE interface - low byte, both pin directions and output values // Pin name Signal Direction Config Initial State Config // ADBUS0 TCK output 1 low 0 // ADBUS1 TDI output 1 low 0 // ADBUS2 TDO input 0 0 // ADBUS3 TMS output 1 high 1 // ADBUS4 GPIOL0 input 0 0 // ADBUS5 GPIOL1 input 0 0 // ADBUS6 GPIOL2 input 0 0 // ADBUS7 GPIOL3 input 0 0 byOutputBuffer[dwNumBytesToSend++] = 0x80; // Set data bits low-byte of MPSSE port byOutputBuffer[dwNumBytesToSend++] = 0x08; // Initial state config above byOutputBuffer[dwNumBytesToSend++] = 0x0B; // Direction config above ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the low GPIO config commands if (ftStatus != FT_OK) return false; dwNumBytesToSend = 0; // Reset output buffer pointer // Set initial states of the MPSSE interface - high byte, both pin directions and output values // Pin name Signal Direction Config Initial State Config // ACBUS0 GPIOH0 input 0 0 // ACBUS1 GPIOH1 input 0 0 // ACBUS2 GPIOH2 input 0 0 // ACBUS3 GPIOH3 input 0 0 // ACBUS4 GPIOH4 input 0 0 // ACBUS5 GPIOH5 input 0 0 // ACBUS6 GPIOH6 input 0 0 // ACBUS7 GPIOH7 input 0 0 byOutputBuffer[dwNumBytesToSend++] = 0x82; // Set data bits low-byte of MPSSE port byOutputBuffer[dwNumBytesToSend++] = 0x00; // Initial state config above byOutputBuffer[dwNumBytesToSend++] = 0x00; // Direction config above ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the high GPIO config commands if (ftStatus != FT_OK) return false; dwNumBytesToSend = 0; // Reset output buffer pointer // Set TCK frequency // TCK = 60MHz /((1 + [(1 +0xValueH*256) OR 0xValueL])*2) byOutputBuffer[dwNumBytesToSend++] = 0x86; //Command to set clock divisor byOutputBuffer[dwNumBytesToSend++] = dwClockDivisor & 0xFF; //Set 0xValueL of clock divisor byOutputBuffer[dwNumBytesToSend++] = (dwClockDivisor >> 8) & 0xFF; //Set 0xValueH of clock divisor ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the clock divisor commands if (ftStatus != FT_OK) return false; dwNumBytesToSend = 0; // Reset output buffer pointer // Disable internal loop-back byOutputBuffer[dwNumBytesToSend++] = 0x85; // Disable loopback ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the loopback command if (ftStatus != FT_OK) return false; return true; } bool Jtag::setFreq(double freq) { if (!active) { cerr << "Jtag must be connected and initialized before calling setFreq()!" << endl; return false; } FT_STATUS ftStatus; BYTE byOutputBuffer[8]; // Buffer to hold MPSSE commands and data to be sent to the FT2232H DWORD dwNumBytesToSend = 0; // Index to the output buffer DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write DWORD dwClockDivisor; // Value of clock divisor, SCL Frequency = 60/((1+clkDiv)*2) (MHz) dwClockDivisor = 30.0 / (freq / 1000000.0) - 1.0; // Set TCK frequency // TCK = 60MHz /((1 + [(1 +0xValueH*256) OR 0xValueL])*2) byOutputBuffer[dwNumBytesToSend++] = 0x86; //Command to set clock divisor byOutputBuffer[dwNumBytesToSend++] = dwClockDivisor & 0xFF; //Set 0xValueL of clock divisor byOutputBuffer[dwNumBytesToSend++] = (dwClockDivisor >> 8) & 0xFF; //Set 0xValueH of clock divisor ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent); // Send off the clock divisor commands if (ftStatus != FT_OK) return false; return true; } bool Jtag::navigateToState(Jtag_fsm::State init, Jtag_fsm::State dest) { FT_STATUS ftStatus; BYTE byOutputBuffer[3]; // Buffer to hold MPSSE commands and data to be sent to the FT2232H DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write Jtag_fsm::Transistions transistions = Jtag_fsm::getTransitions(init, dest); if (transistions.moves > 0) { if (transistions.moves < 8) { byOutputBuffer[0] = 0x4B; byOutputBuffer[1] = transistions.moves - 1; byOutputBuffer[2] = 0x7f & transistions.tms; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) return false; } else { cout << "Transition of 8 moves!" << endl; byOutputBuffer[0] = 0x4B; byOutputBuffer[1] = 6; byOutputBuffer[2] = 0x7f & transistions.tms; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) return false; byOutputBuffer[0] = 0x4B; byOutputBuffer[1] = transistions.moves - 8; byOutputBuffer[2] = 0x7f & (transistions.tms >> 7); ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) return false; } } return true; } bool Jtag::shiftData(unsigned int bitCount, string tdi, string tdo, string mask) { FT_STATUS ftStatus; unsigned int reqBytes = bitCount / 8 + (bitCount % 8 > 0); BYTE *byOutputBuffer = new BYTE[reqBytes + 3]; BYTE *tdoBuffer = new BYTE[reqBytes + 3]; BYTE *byInputBuffer = new BYTE[reqBytes + 6]; DWORD dwNumBytesSent = 0; DWORD dwNumBytesToRead = 0; DWORD dwNumBytesRead = 0; DWORD tdoBytes = 0; unsigned int reqHex = bitCount / 4 + (bitCount % 4 > 0); if (tdi.length() < reqHex) return false; bool read = tdo != ""; if (read) { if (tdo.length() < reqHex) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return false; } if (mask != "" && mask.length() < reqHex) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return false; } } if (!flush()) return false; if (bitCount < 9) { int data = stoi(tdi, 0, 16); byOutputBuffer[0] = read ? 0x3B : 0x1B; byOutputBuffer[1] = bitCount - 2; byOutputBuffer[2] = data & 0xff; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return false; } BYTE lastBit = (data >> ((bitCount - 1) % 8)) & 0x01; byOutputBuffer[0] = read ? 0x6E : 0x4E; byOutputBuffer[1] = 0x00; byOutputBuffer[2] = 0x03 | (lastBit << 7); ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return false; } if (read) { do { ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); // Get the number of bytes in the device input buffer } while ((dwNumBytesToRead == 0) && (ftStatus == FT_OK)); //or Timeout ftStatus = FT_Read(ftHandle, byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return false; } tdoBuffer[0] = byInputBuffer[0] >> (8 - (bitCount - 1)); tdoBuffer[0] |= byInputBuffer[1] >> (7 - (bitCount - 1)); tdoBytes = 1; } } else { BYTE *tdiBytes = new BYTE[reqBytes + 1]; hexToByte(tdi, tdiBytes); unsigned int fullBytes = (bitCount - 1) / 8; unsigned int remBytes = fullBytes; unsigned int offset = 0; if (fullBytes > 65536 && read) { cout << "Large transfers with reads may not work!" << endl; } while (remBytes > 0) { unsigned int bct = remBytes > 65536 ? 65536 : remBytes; byOutputBuffer[0] = read ? 0x39 : 0x19; byOutputBuffer[1] = (bct - 1) & 0xff; byOutputBuffer[2] = ((bct - 1) >> 8) & 0xff; for (unsigned int i = 0; i < bct; i++) { byOutputBuffer[3 + i] = tdiBytes[i + offset]; } ftStatus = FT_Write(ftHandle, byOutputBuffer, 3 + bct, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return false; } remBytes -= bct; offset += bct; } unsigned int partialBits = bitCount - 1 - (fullBytes * 8); if (fullBytes * 8 + 1 != bitCount) { byOutputBuffer[0] = read ? 0x3B : 0x1B; byOutputBuffer[1] = partialBits - 1; byOutputBuffer[2] = tdiBytes[reqBytes - 1] & 0xff; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return false; } } BYTE lastBit = (tdiBytes[reqBytes - 1] >> ((bitCount - 1) % 8)) & 0x01; byOutputBuffer[0] = read ? 0x6E : 0x4E; byOutputBuffer[1] = 0x00; byOutputBuffer[2] = 0x03 | (lastBit << 7); ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return false; } if (read) { DWORD bytesToRead = fullBytes + ((fullBytes * 8 + 1 != bitCount) ? 2 : 1); do { ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); // Get the number of bytes in the device input buffer } while ((dwNumBytesToRead != bytesToRead) && (ftStatus == FT_OK)); //or Timeout ftStatus = FT_Read(ftHandle, byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return false; } for (unsigned int i = 0; i < fullBytes; i++) tdoBuffer[tdoBytes++] = byInputBuffer[i]; if (fullBytes * 8 + 1 != bitCount) { tdoBuffer[tdoBytes] = byInputBuffer[tdoBytes] >> (8 - partialBits); tdoBuffer[tdoBytes++] |= byInputBuffer[dwNumBytesRead - 1] >> (7 - partialBits); } else { tdoBuffer[tdoBytes++] = byInputBuffer[dwNumBytesRead - 1] >> 7; } } delete tdiBytes; } if (read) { //Read out the data from input buffer std::stringstream ss; for (int i = tdoBytes - 1; i >= 0; i--) ss << setfill('0') << setw(2) << hex << (int) tdoBuffer[i]; string hexTdo = ss.str(); if (hexTdo.length() - 1 == mask.length()) hexTdo = hexTdo.substr(1, hexTdo.length() - 1); if (!compareHexString(hexTdo, tdo, mask)) { cerr << "TDO didn't match expected string. Got " << hexTdo << " expected " << tdo << " with mask " << mask << endl; delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return false; } } delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return true; } string Jtag::shiftData(unsigned int bitCount, string tdi) { FT_STATUS ftStatus; unsigned int reqBytes = bitCount / 8 + (bitCount % 8 > 0); BYTE *byOutputBuffer = new BYTE[reqBytes + 3]; BYTE *tdoBuffer = new BYTE[reqBytes + 3]; BYTE *byInputBuffer = new BYTE[reqBytes + 6]; DWORD dwNumBytesSent = 0; DWORD dwNumBytesToRead = 0; DWORD dwNumBytesRead = 0; DWORD tdoBytes = 0; unsigned int reqHex = bitCount / 4 + (bitCount % 4 > 0); if (tdi.length() < reqHex) return ""; if (!flush()) return ""; if (bitCount < 9) { int data = stoi(tdi, 0, 16); byOutputBuffer[0] = 0x3B; byOutputBuffer[1] = bitCount - 2; byOutputBuffer[2] = data & 0xff; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return ""; } BYTE lastBit = (data >> ((bitCount - 1) % 8)) & 0x01; byOutputBuffer[0] = 0x6E; byOutputBuffer[1] = 0x00; byOutputBuffer[2] = 0x03 | (lastBit << 7); ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return ""; } do { ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); // Get the number of bytes in the device input buffer } while ((dwNumBytesToRead == 0) && (ftStatus == FT_OK)); //or Timeout ftStatus = FT_Read(ftHandle, byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return ""; } tdoBuffer[0] = byInputBuffer[0] >> (8 - (bitCount - 1)); tdoBuffer[0] |= byInputBuffer[1] >> (7 - (bitCount - 1)); tdoBytes = 1; } else { BYTE *tdiBytes = new BYTE[reqBytes + 1]; hexToByte(tdi, tdiBytes); unsigned int fullBytes = (bitCount - 1) / 8; unsigned int remBytes = fullBytes; unsigned int offset = 0; if (fullBytes > 65536) { cout << "Large transfers with reads may not work!" << endl; } while (remBytes > 0) { unsigned int bct = remBytes > 65536 ? 65536 : remBytes; byOutputBuffer[0] = 0x39; byOutputBuffer[1] = (bct - 1) & 0xff; byOutputBuffer[2] = ((bct - 1) >> 8) & 0xff; for (unsigned int i = 0; i < bct; i++) { byOutputBuffer[3 + i] = tdiBytes[i + offset]; } ftStatus = FT_Write(ftHandle, byOutputBuffer, 3 + bct, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return ""; } remBytes -= bct; offset += bct; } unsigned int partialBits = bitCount - 1 - (fullBytes * 8); if (fullBytes * 8 + 1 != bitCount) { byOutputBuffer[0] = 0x3B; byOutputBuffer[1] = partialBits - 1; byOutputBuffer[2] = tdiBytes[reqBytes - 1] & 0xff; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return ""; } } BYTE lastBit = (tdiBytes[reqBytes - 1] >> ((bitCount - 1) % 8)) & 0x01; byOutputBuffer[0] = 0x6E; byOutputBuffer[1] = 0x00; byOutputBuffer[2] = 0x03 | (lastBit << 7); ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return ""; } DWORD bytesToRead = fullBytes + ((fullBytes * 8 + 1 != bitCount) ? 2 : 1); do { ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); // Get the number of bytes in the device input buffer } while ((dwNumBytesToRead != bytesToRead) && (ftStatus == FT_OK)); //or Timeout ftStatus = FT_Read(ftHandle, byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) { delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; delete tdiBytes; return ""; } for (unsigned int i = 0; i < fullBytes; i++) tdoBuffer[tdoBytes++] = byInputBuffer[i]; if (fullBytes * 8 + 1 != bitCount) { tdoBuffer[tdoBytes] = byInputBuffer[tdoBytes] >> (8 - partialBits); tdoBuffer[tdoBytes++] |= byInputBuffer[dwNumBytesRead - 1] >> (7 - partialBits); } else { tdoBuffer[tdoBytes++] = byInputBuffer[dwNumBytesRead - 1] >> 7; } delete tdiBytes; } //Read out the data from input buffer std::stringstream ss; for (int i = tdoBytes - 1; i >= 0; i--) ss << setfill('0') << setw(2) << hex << (int) tdoBuffer[i]; string hexTdo = ss.str(); if (hexTdo.length() - 1 == tdi.length()) hexTdo = hexTdo.substr(1, hexTdo.length() - 1); delete byOutputBuffer; delete tdoBuffer; delete byInputBuffer; return hexTdo; } bool Jtag::sendClocks(unsigned long cycles) { BYTE byOutputBuffer[3]; DWORD dwNumBytesSent; FT_STATUS ftStatus; if (cycles / 8 > 65536) { if (!sendClocks(cycles - 65536 * 8)) return false; cycles = 65536 * 8; } cycles /= 8; byOutputBuffer[0] = 0x8F; byOutputBuffer[1] = (cycles - 1) & 0xff; byOutputBuffer[2] = ((cycles - 1) >> 8) & 0xff; ftStatus = FT_Write(ftHandle, byOutputBuffer, 3, &dwNumBytesSent); if (ftStatus != FT_OK) return false; return true; } bool Jtag::compareHexString(string a, string b, string mask) { unsigned int length = a.length(); if (length != b.length()) { cout << "length mismatch!" << endl; return false; } if (mask == "") return a == b; if (length != mask.length()) { cout << "length and mask mismatch! " << length << " and " << mask.length() << " of strings " << a << " and " << mask << endl; return false; } for (unsigned int i = 0; i < length / 2; i++) { BYTE m = stoi(mask.substr(length - 2 - i * 2, 2), 0, 16); BYTE pa = stoi(a.substr(length - 2 - i * 2, 2), 0, 16); BYTE pb = stoi(b.substr(length - 2 - i * 2, 2), 0, 16); if ((pa & m) != (pb & m)) { cout << "Mismatch at " << i << endl; return false; } } if ((length & 1) != 0) { BYTE m = stoi(mask.substr(0, 1), 0, 16); BYTE pa = stoi(a.substr(0, 1), 0, 16); BYTE pb = stoi(b.substr(0, 1), 0, 16); if ((pa & m) != (pb & m)) { cout << "Mismatch at last bit" << endl; return false; } } return true; } void Jtag::hexToByte(string hex, BYTE* out) { int length = hex.length(); for (int i = 0; i < length / 2; i++) { try { out[i] = stoi(hex.substr(length - 2 - i * 2, 2), 0, 16); } catch (exception& e) { cerr << "Failed at " << i << " with length " << length << endl; cerr.flush(); exit(2); } } if ((length & 1) != 0) try { out[length / 2] = stoi(hex.substr(0, 1), 0, 16); } catch (exception& e) { cerr << "Failed to convert string " << hex.substr(0, 1) << " to an int!" << endl; cerr.flush(); exit(2); } } bool Jtag::flush() { FT_STATUS ftStatus; BYTE byInputBuffer[1024]; DWORD dwNumBytesToRead = 0; DWORD dwNumBytesRead = 0; ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead); if (ftStatus != FT_OK) return false; if (dwNumBytesToRead == 0) return true; //or Timeout ftStatus = FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead); if (ftStatus != FT_OK) return false; return true; }