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