Rev Author Line No. Line
2697 miho 1 // Include FTDI library
2 #include "mlab_xvcd_port_FTDI.h"
3  
4  
5 // JTAG Output Pin Mask
6 #define IO_OUTPUT_MASK (PORT_TCK|PORT_TDI|PORT_TMS|PORT_LED) // Mask for all Output Pins
7  
8  
9 // Global Variables
10 FT_HANDLE ftHandle; // Handle for FTDI device
11 bool ftHandleValid = false; // Valid Handle
12 unsigned char PinStatus = 0; // Status of DBUS pins
13 unsigned char LedMask = 0; // LED Mask for DBUS data transfer
14  
15  
16 // Convert string to int (both decimal and hex string)
17 int atoiEx(char *s)
18 {
19 if (s[0]=='0' && (s[1]=='x' || s[1]=='X'))
20 {
21 // Hex Value
22 int i;
23 #pragma warning(disable: 4996) // Disable MS warning about scanf
24 sscanf(s, "%x", &i);
25 return i;
26 }
27 else
28 {
29 // Decimal Value
30 return atoi(s);
31 }
32 }
33  
34  
35 // Print FTDI Pin Names (from mask value)
36 void jtagPrintPinNames(int pinMask)
37 {
38 // 16bit (MSB is CBUS, LSB is DBUS)
39 int bit=15;
40 bool useDelimiter=false;
41  
42 do
43 {
44 int mask = 1 << bit;
45 if (pinMask & mask)
46 {
47 if (useDelimiter)
48 {
49 printf("+");
50 }
51 if (bit > 7)
52 {
53 printf("CBUS%c", '0' + bit - 8);
54 }
55 else
56 {
57 printf("DBUS%c", '0' + bit);
58 switch (mask)
59 {
60 case FTDI_TXD: printf("(TXD)"); break;
61 case FTDI_RXD: printf("(RXD)"); break;
62 case FTDI_RTS: printf("(RTS)"); break;
63 case FTDI_CTS: printf("(CTS)"); break;
64 case FTDI_DTR: printf("(DTR)"); break;
65 case FTDI_DSR: printf("(DSR)"); break;
66 case FTDI_DCD: printf("(DCD)"); break;
67 case FTDI_RI: printf("(RI) "); break;
68 }
69 }
70 useDelimiter = true;
71 }
72 }
73 while (bit-- > 0);
74 }
75  
76  
77 // Verify pin usage
78 void jtagCheckPinConfig()
79 {
80 // Check CBUS usage
2940 miho 81 if ( PORT_TCK > 0x00FF )
2697 miho 82 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TCK can't use CBUS signal"), exit(2);
2940 miho 83 if ( PORT_TCK == 0 )
2697 miho 84 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TCK not defined"), exit(2);
85  
2940 miho 86 if ( PORT_TDI > 0x00FF )
2697 miho 87 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TDI can't use CBUS signal"), exit(2);
2940 miho 88 if ( PORT_TDI == 0 )
2697 miho 89 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TDI not defined"), exit(2);
90  
2940 miho 91 if ( PORT_TDO > 0x00FF )
2697 miho 92 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TDO can't use CBUS signal"), exit(2);
2940 miho 93 if ( PORT_TDO == 0 )
2697 miho 94 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TDO not defined"), exit(2);
95  
2940 miho 96 if ( PORT_TMS > 0x00FF)
2697 miho 97 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TMS can't use CBUS signal"), exit(2);
2940 miho 98 if ( PORT_TMS == 0 )
2697 miho 99 fprintf(stderr, "\nFTDI: INTERNAL ERROR: TMS not defined"), exit(2);
100  
2940 miho 101 if ( PORT_LED > 0x0FFF)
2697 miho 102 fprintf(stderr, "\nFTDI: INTERNAL ERROR: LED can't use CBUS signal > 3"), exit(2);
103 }
104  
105  
106 // Print JTAG Pin Assignment
107 void jtagPrintPinConfig()
108 {
109 // Print pin masks human readable
110 printf(" JTAG Port Pins "); printf("TCK->"); jtagPrintPinNames(PORT_TCK); printf("\n");
111 printf(" "); printf("TDI->"); jtagPrintPinNames(PORT_TDI); printf("\n");
112 printf(" "); printf("TDO->"); jtagPrintPinNames(PORT_TDO); printf("\n");
113 printf(" "); printf("TMS->"); jtagPrintPinNames(PORT_TMS); printf("\n");
114 printf(" "); printf("LED->"); jtagPrintPinNames(PORT_LED); printf("\n");
115 }
116  
117  
118 // Connect to FTDI driver
119 int jtagOpenPort(int findDeviceBy, char *findDeviceByStr)
120 {
121 // Enumerate FTDI Devices
122 // ----------------------
123  
124 FT_STATUS ftStatus;
125  
126 // Print Library Version
127 printf("FTDI Connect\n");
128 DWORD dwLibraryVer;
129 ftStatus = FT_GetLibraryVersion(&dwLibraryVer);
130 if (ftStatus == FT_OK)
131 printf(" Library Version 0x%x\n", dwLibraryVer);
132 else
133 fprintf(stderr, "\nFTDI: Error Reading Library Version\n");
134  
135 // Create Device Information List
136 DWORD numDevs = 0;
137 ftStatus = FT_CreateDeviceInfoList(&numDevs);
138 if (ftStatus == FT_OK)
139 printf(" Devices Found %d\n", numDevs);
140 else
141 printf(" No FTDI Device Found\n");
142  
143 if (numDevs==0)
144 return -1;
145  
146 // Print Config Info
147 jtagPrintPinConfig();
148 jtagCheckPinConfig();
149 printf("\n");
150  
151 // List All FTDI Devices
152 FT_HANDLE ftHandleTemp;
153 DWORD Flags;
154 DWORD ID;
155 DWORD Type;
156 DWORD LocId;
157 char SerialNumber[16];
158 char Description[64];
159 for (DWORD i=0; i<numDevs; i++)
160 {
161 ftStatus = FT_GetDeviceInfoDetail(i, &Flags, &Type, &ID, &LocId, SerialNumber, Description, &ftHandleTemp);
162 if (ftStatus == FT_OK)
163 {
164 printf("Device %d\n", i);
2940 miho 165 if (Flags & FT_FLAGS_OPENED)
2933 miho 166 {
167 printf(" Description Device is used by another process\n");
168 }
169 else
170 {
171 printf(" Description \"%s\"\n", Description);
172 printf(" SerialNumber \"%s\"\n", SerialNumber);
173 //printf(" Flags 0x%x\n", Flags);
174 //printf(" Type 0x%x\n", Type);
175 //printf(" ID 0x%x\n", ID);
176 printf(" Location 0x%x\n", LocId);
177 }
178 printf("\n");
2697 miho 179 }
180 }
181  
182 // Select one Device and Open It
183 unsigned int selectedDeviceIndex = 0;
184 if (findDeviceBy==0)
185 {
186 // Select by Device Number
187 selectedDeviceIndex = atoiEx(findDeviceByStr);
188 if (numDevs<=selectedDeviceIndex)
189 {
190 fprintf(stderr, " There is no Device Number %d\n\n", selectedDeviceIndex);
191 return -1;
192 }
193 // Open device
194 ftStatus = FT_Open(selectedDeviceIndex, &ftHandle);
195 }
196 else
197 {
198 // Select by Description / Serial Number / Location
199 if (findDeviceBy==FT_OPEN_BY_LOCATION)
200 {
201 // Open device (location is number, not string)
202 int findDeviceByInt = atoiEx(findDeviceByStr);
203 ftStatus = FT_OpenEx((void*)findDeviceByInt, findDeviceBy, &ftHandle);
204 }
205 else
206 {
207 ftStatus = FT_OpenEx(findDeviceByStr, findDeviceBy, &ftHandle);
208 }
209 }
210  
211 // Check Status
212 if (ftStatus == FT_OK)
213 {
214 ftHandleValid = true;
215 //printf(" FTDI Device Opened\n");
216 }
217 else
218 {
219 fprintf(stderr, " Can't Open FTDI Device (error code %d)\n\n", ftStatus);
220 return -1;
221 }
222  
223 // Selected Device
224 ftStatus = FT_GetDeviceInfo(ftHandle, &Type, &ID, SerialNumber, Description, 0);
225 if (ftStatus == FT_OK)
226 {
227 printf("Selected Device\n");
228 printf(" Description \"%s\"\n", Description);
229 printf(" SerialNumber \"%s\"\n", SerialNumber);
230 //printf(" Type 0x%x\n", Type);
231 //printf(" ID 0x%x\n", ID);
232 }
233  
234 // Get Driver Version
235 DWORD dwDriverVer;
236 ftStatus = FT_GetDriverVersion(ftHandle, &dwDriverVer);
237 if (ftStatus == FT_OK)
238 {
239 printf(" Device Driver Ver 0x%x\n", dwDriverVer);
240 }
241 else
242 {
243 fprintf(stderr, "FTDI: Error Reading Driver Version\n");
244 }
245  
246 // Set BitBang Mode
2940 miho 247 ftStatus = FT_SetBitMode(ftHandle, (UCHAR)(0xFF & IO_OUTPUT_MASK), FT_BITMODE_SYNC_BITBANG); //FT_BITMODE_SYNC_BITBANG / FT_BITMODE_ASYNC_BITBANG
2697 miho 248 if (ftStatus == FT_OK)
249 {
250 // printf("Set BitBang Mode\n");
251 }
252 else
253 {
254 fprintf(stderr, "FTDI: Set BitBang Mode Failed %d\n", ftStatus);
255 }
256  
257 // Set Baud Rate
258 ftStatus = FT_SetBaudRate(ftHandle, BAUD_RATE);
259 if (ftStatus == FT_OK)
260 {
261 printf(" Baud Rate %d\n", BAUD_RATE);
262 }
263 else
264 {
265 fprintf(stderr, "FTDI: Set Baud Rate Failed %d\n", ftStatus);
266 }
267  
268 ftStatus = FT_Purge(ftHandle, FT_PURGE_RX | FT_PURGE_TX); // Purge both Rx and Tx buffers
269 if (ftStatus == FT_OK)
270 {
271 // printf("Purge \n");
272 }
273 else
274 {
275 fprintf(stderr, "FTDI: FT_Purge failed %d\n", ftStatus);
276 }
277  
278 ftStatus = FT_SetLatencyTimer(ftHandle, USB_LATENCY); // Latency in ms
279 if (ftStatus == FT_OK)
280 {
281 printf(" USB Latency %d\n", USB_LATENCY);
282 }
283 else
284 {
285 fprintf(stderr, "FTDI: Set USB Latency Timer Failed %d\n", ftStatus);
286 }
287  
288 printf("\n");
289 return 0;
290 }
291  
292  
293 // Enable or Disable Activity LED
294 void jtagSetLED(bool LedEnable)
295 {
296  
297 // DBUS Connected LED (BitBang Mode)
2940 miho 298 LedMask = LedEnable ? (PORT_LED & 0xFF) : 0; // Set mask for jtagScan function
2697 miho 299 if (PORT_LED & 0xFF)
300 {
301 // Set / Reset LED Pin
302 DWORD BytesWritten;
303 DWORD BytesReceived;
304 unsigned char DataOut = LedMask | (PinStatus & ~PORT_LED); // Preserve PinStatus
305 unsigned char Dummy;
306 FT_Write(ftHandle, &DataOut, 1, &BytesWritten ); // Send 1 byte
307 FT_Read (ftHandle, &Dummy, 1, &BytesReceived); // Read 1 byte
308 //printf("[PinStatus %x DataOut %x]", PinStatus, DataOut);
309 }
310  
311 // CBUS Connected LED (BitBang Mode) 1 and 0 state of the port
2940 miho 312 const unsigned char On = ( ((PORT_LED & 0x0F00) >> 4) | ((PORT_LED & 0x0F00) >> 8) );
313 const unsigned char Off = ( ((PORT_LED & 0x0F00) >> 4) );
2697 miho 314  
315 if (On)
316 {
317 // Set / Reset LED Pin
2940 miho 318 FT_SetBitMode(ftHandle, LedEnable ? On : Off, FT_BITMODE_CBUS_BITBANG);
2697 miho 319  
320 // Return to used Mode
2940 miho 321 FT_SetBitMode(ftHandle, (UCHAR)(0xFF & IO_OUTPUT_MASK), FT_BITMODE_SYNC_BITBANG); //FT_BITMODE_SYNC_BITBANG / FT_BITMODE_ASYNC_BITBANG
2697 miho 322 }
323 }
324  
325  
326 // Set port to Idle state
327 void jtagSetIdle()
328 {
329 char b = 0; // Idle State for JTAG pins
330 DWORD BytesWritten;
331 DWORD BytesReceived;
332  
333 // Write (idle state of pins)
334 FT_Write(ftHandle, &b, 1, &BytesWritten);
335 // Read (not to left data in input fifo)
336 FT_Read(ftHandle, &b, 1, &BytesReceived);
337 }
338  
339  
340 // Close FTDI connection
341 int jtagClosePort()
342 {
343 if (ftHandleValid)
344 {
345 jtagSetLED(false);
346 // Switch Off the Outputs
347 FT_Purge(ftHandle, FT_PURGE_RX | FT_PURGE_TX); // Purge both Rx and Tx buffers
348 FT_SetBitMode(ftHandle, 0, FT_BITMODE_SYNC_BITBANG);
349 // Close FTDI Lib
350 FT_Close(ftHandle);
351 ftHandleValid = false;
352 }
353 return 0;
354 }
355  
356  
357 // Send data to JTAG port and bring returned data
2940 miho 358 int jtagScan(const unsigned char *TMS, const unsigned char *TDI, unsigned char *TDO, unsigned int bits)
2697 miho 359 {
360 FT_STATUS ftStatus;
361 DWORD BytesWritten;
362 DWORD BytesReceived;
2940 miho 363 unsigned int r, t;
2697 miho 364  
365 // Decompose TDI and TMS byte array to raw bitstream
366 //(1 TDI bit + 1 TMS bit --> 1 byte + 1 byte with TCK)
367 unsigned char buffer[16384];
368 if (bits > sizeof(buffer)/2)
369 {
370 fprintf(stderr, "\n FTDI: Out of Buffer Space for %d bits\n", bits);
371 return -1;
372 }
373  
374 // Switch LED On
375 jtagSetLED(true);
376  
377 // Prepare transmit data to buffer
2940 miho 378 for (unsigned int i = 0; i < bits; ++i)
2697 miho 379 {
380 unsigned char v = 0 | LedMask; // LED On / Off (on DBUS)
381 if (TMS[i/8] & (1<<(i&7)))
382 {
2940 miho 383 v |= PORT_TMS;
2697 miho 384 // printf("T");
385 }
386 else
387 {
388 // printf("t");
389 }
390 if (TDI[i/8] & (1<<(i&7)))
391 {
2940 miho 392 v |= PORT_TDI;
2697 miho 393 // printf("|");
394 }
395 else
396 {
397 // printf(".");
398 }
399 buffer[i * 2 + 0] = v;
2940 miho 400 buffer[i * 2 + 1] = v | PORT_TCK;
2697 miho 401 }
402 PinStatus = buffer[bits*2-1];
403 // printf("\n");
404  
405 // Send data to FTDI
406 r = 0;
407 while (r < bits * 2)
408 {
409 t = bits * 2 - r;
410 if (t > FTDI_MAX_WRITESIZE)
411 {
412 t = FTDI_MAX_WRITESIZE;
413 }
414  
415 // printf("writing %d bytes to FTDI\n", t);
416 ftStatus = FT_Write(ftHandle, buffer+r, t, &BytesWritten);
417 if (ftStatus != FT_OK)
418 {
419 fprintf(stderr, "\n FTDI: Error Writing\n");
420 return -2;
421 }
422  
2940 miho 423 unsigned int i = 0;
2697 miho 424  
425 while (i < t)
426 {
427 FT_SetTimeouts(ftHandle, 5000, 0); // timeout 5 sec
428 ftStatus = FT_Read(ftHandle, buffer+r+i, t-i, &BytesReceived);
429 if (ftStatus == FT_OK)
430 {
431 if (BytesReceived == t-i)
432 {
433 // FT_Read OK
434 // printf("Read from FTDI %d bytes", BytesReceived);
435 }
436 else
437 {
438 // FT_Read Timeout
439 fprintf(stderr, "\n FTDI: Read Timeout\n");
440 return -2;
441 }
442 }
443 else
444 {
445 fprintf(stderr, "\n FTDI: Error Reading\n");// Error
446 return -2;
447 }
448  
449 i += BytesReceived;
450 }
451  
452 r += t;
453 }
454  
455 // Pack TDO bitstream from receive buffer to byte array
456 memset(TDO, 0, (bits + 7) / 8);
457  
2940 miho 458 for (unsigned int i = 0; i < bits; ++i)
2697 miho 459 {
2940 miho 460 if (buffer[i * 2 + 1] & PORT_TDO)
2697 miho 461 {
462 TDO[i/8] |= 1 << (i&7);
463 // printf("H");
464 }
465 else
466 {
467 // printf("L");
468 }
469 }
470 // printf("\n");
471 // printf(" Bits %d ", bit_counter);
472  
473 // Switch LED Off
474 jtagSetLED(false);
475  
476 return 0;
477 }
2935 miho 478  
479 // Check if Cable is still connected and accesible
480 // True is o.k.
481 bool CheckCable()
482 {
483 FT_STATUS ftStatus;
484  
485 DWORD lpdwAmountInRxQueue, lpdwAmountInTxQueue, lpdwEventStatus;
486  
487 ftStatus = FT_GetStatus(ftHandle, &lpdwAmountInRxQueue, &lpdwAmountInTxQueue, &lpdwEventStatus);
488 return (ftStatus==FT_OK);
489 }