diff -u -r --new-file uisp-20030220cvs/configure.in uisp.patched/configure.in --- uisp-20030220cvs/configure.in 2003-03-24 19:32:42.000000000 +0100 +++ uisp.patched/configure.in 2004-03-25 17:57:18.000000000 +0100 @@ -44,6 +44,31 @@ AC_TYPE_SIZE_T AC_HEADER_TIME +AC_ARG_WITH(ftdi-bitbang, +[ --with-ftdi-bitbang enable FTDI bitbang programming mode (needs ftdi_sio.h from kernel source)], +[ + AC_MSG_CHECKING(for FTDI bitbang support) + if test "$withval" != "no"; then + CXXFLAGS="$CXXFLAGS -DFTDI_BITBANG" + AC_MSG_RESULT(yes) + + dnl check for libftdi-config + AC_PATH_PROG(HAVELIBFTDI, libftdi-config, $PATH) + + if test ! -z "$HAVELIBFTDI"; then + dnl LIBFTDI_CFLAGS=`$HAVELIBFTDI --cflags` + LIBFTDI_LIBS=`$HAVELIBFTDI --libs` + + CFLAGS="$CFLAGS $LIBFTDI_CFLAGS" + LIBS="$LIBS $LIBFTDI_LIBS" + else + AC_MSG_ERROR([*** libftdi-config not found. You need a working libftdi installation.]) + fi + else + AC_MSG_RESULT(no) + fi +]) + dnl Checks for library functions. AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP diff -u -r --new-file uisp-20030220cvs/src/DAPA.C uisp.patched/src/DAPA.C --- uisp-20030220cvs/src/DAPA.C 2003-03-04 04:22:26.000000000 +0100 +++ uisp.patched/src/DAPA.C 2004-03-25 17:57:50.000000000 +0100 @@ -302,6 +302,30 @@ #define XIL_ENA 0x08 /* D3: ENABLE# */ #define XIL_DIN PARPORT_STATUS_SELECT /* SLCT: TDO */ +/* + FTDI USB FT232BM and FT245BM bitbang mode programming + Values may vary, please adjust to your wiring + + The needed bitbang mode bitmask is automatically calculated + using the values of FTDI_XXX +*/ +#ifdef FTDI_BITBANG +#include + +ftdi_context ftdi; + +unsigned char *ftdi_buffer = NULL; +unsigned int ftdi_buffer_size = 0; +unsigned int ftdi_buffer_pos = 0; + +#endif + +/* todo: these should be configurable via the command line */ +unsigned char FTDI_DOUT = 0x10; +unsigned char FTDI_DIN = 0x20; +unsigned char FTDI_SCK = 0x40; +unsigned char FTDI_RESET = 0x80; + /* Default value for minimum SCK high/low time in microseconds. */ #ifndef SCK_DELAY #define SCK_DELAY 5 @@ -378,6 +402,11 @@ void TDAPA::ParportWriteCtrl() { + #ifdef FTDI_BITBANG + if (pa_type == PAT_FTDI) + return; + #endif + if (ppdev_fd != -1) par_write_ctrl(ppdev_fd, &par_ctrl); else @@ -387,6 +416,13 @@ void TDAPA::ParportWriteData() { + #ifdef FTDI_BITBANG + if (pa_type == PAT_FTDI) { + ftdi_write_data (&ftdi, (unsigned char *)&par_data, 1); + return; + } + #endif + if (ppdev_fd != -1) par_write_data(ppdev_fd, &par_data); else @@ -396,6 +432,11 @@ void TDAPA::ParportReadStatus() { + #ifdef FTDI_BITBANG + ftdi_read_pins(&ftdi, &par_status); + return; + #endif + if (ppdev_fd != -1) par_read_status(ppdev_fd, &par_status); else @@ -477,6 +518,11 @@ ParportWriteData(); break; + case PAT_FTDI: + if (b) par_data |= FTDI_RESET; else par_data &= ~FTDI_RESET; + ParportWriteData(); + break; + #ifdef TIOCMGET case PAT_DASA: SerialReadCtrl(); @@ -551,6 +597,11 @@ ParportWriteData(); break; + case PAT_FTDI: + if (b) par_data |= FTDI_SCK; else par_data &= ~FTDI_SCK; + ParportWriteData(); + break; + #ifdef TIOCMGET case PAT_DASA: SerialReadCtrl(); @@ -671,6 +722,7 @@ } break; + case PAT_FTDI: case PAT_DASA: case PAT_DASA2: break; @@ -698,6 +750,7 @@ case PAT_ETT: case PAT_MAXI: case PAT_XIL: + case PAT_FTDI: case PAT_DASA: case PAT_DASA2: /* no separate enable for SCK nad MOSI */ @@ -781,6 +834,11 @@ ParportWriteData(); break; + case PAT_FTDI: + if (b) par_data |= FTDI_DOUT; else par_data &= ~FTDI_DOUT; + ParportWriteData(); + break; + #ifdef TIOCMGET case PAT_DASA: ioctl(ppdev_fd, b ? TIOCSBRK : TIOCCBRK, 0); @@ -822,6 +880,10 @@ ParportReadStatus(); b = (par_status & PARPORT_STATUS_SELECT); break; + case PAT_FTDI: + ParportReadStatus(); + b = (par_status & FTDI_DIN); + break; case PAT_DASA: case PAT_DASA2: #ifdef TIOCMGET @@ -890,6 +952,11 @@ par_data = 0xFF & ~(XIL_ENA | XIL_SCK | XIL_RESET); break; + case PAT_FTDI: + par_ctrl = 0; + par_data = 0; + break; + case PAT_DASA: case PAT_DASA2: break; @@ -911,11 +978,76 @@ PulseReset(); } + + int -TDAPA::SendRecv(int b) +TDAPA::SendRecv(int b, bool skip_read) { unsigned int mask, received=0; + #ifdef FTDI_BITBANG + /* + calculate buffer size in 1024 byte blocks + remember: one byte takes 24 bytes in the buffer + */ + if (ftdi_buffer_pos+1024 > ftdi_buffer_size) { + unsigned char *new_ftdi_buffer = (unsigned char *)realloc (ftdi_buffer, ftdi_buffer_size+1024); + + if (new_ftdi_buffer == NULL) { + Info (0, "Current FTDI buffer size: %d\n", ftdi_buffer_size); + + if (ftdi_buffer_size >= 1024) { + Info (0, "Sorry, out of memory for ftdi_buffer. Flushing old data\n"); + ftdi_write_data (&ftdi, ftdi_buffer, ftdi_buffer_pos); + ftdi_buffer_pos = 0; + } else if (new_ftdi_buffer == NULL && ftdi_buffer_size < 1024) { + Info (0, "Sorry, out of memory for ftdi_buffer. Aborting\n"); + exit(-1); + } + } else { + ftdi_buffer_size += 1024; + ftdi_buffer = new_ftdi_buffer; + } + } + + if ((skip_read == false && ftdi_buffer_pos > 0)) { + ftdi_write_data (&ftdi, ftdi_buffer, ftdi_buffer_pos); + ftdi_buffer_pos = 0; + } + + for (mask = 0x80; mask; mask >>= 1) { + if (b & mask) + par_data |= FTDI_DOUT; + else + par_data &= ~FTDI_DOUT; + + ftdi_buffer[ftdi_buffer_pos] = par_data; + ftdi_buffer_pos++; + + par_data |= FTDI_SCK; + ftdi_buffer[ftdi_buffer_pos] = par_data; + ftdi_buffer_pos++; + + if (skip_read == false) + { + ftdi_write_data (&ftdi, ftdi_buffer, ftdi_buffer_pos); + ftdi_buffer_pos = 0; + if(InData()) + received |= mask; + + par_data &= ~FTDI_SCK; + ftdi_buffer[ftdi_buffer_pos] = par_data; + ftdi_write_data (&ftdi, ftdi_buffer, 1); + } else { + par_data &= ~FTDI_SCK; + ftdi_buffer[ftdi_buffer_pos] = par_data; + ftdi_buffer_pos++; + } + } + + return received; + #endif + for (mask = 0x80; mask; mask >>= 1) { OutData(b & mask); SckDelay(); @@ -925,7 +1057,8 @@ /* ... here we have more room for propagation delays (almost the whole SCK period, instead of half of it) - good for long cables, slow RS232 drivers/receivers, opto-isolated interfaces, etc. */ - if (InData()) + if (skip_read == false) + if(InData()) received |= mask; OutSck(0); } @@ -938,6 +1071,17 @@ unsigned char *p = queue, ch; int i = queueSize; + unsigned char saved0 = queue[0]; + bool need_read = false; + /* + Optimize I/O performance by avoiding reads till they are needed. + The serial programming read commands are identified by their first byte. + All known Atmel serial programming (read) commands read input only on the fourth byte. + Special case: Programming enable needs read at third byte. + */ + if (saved0 == 0xAC || saved0 == 0x20 || saved0 == 0x28 || saved0 == 0xA0 || saved0 == 0x58 || saved0 == 0x30 || saved0 == 0x50 || saved0 == 0x38) + need_read = true; + if (rec_queueSize==-1){rec_queueSize = queueSize;} #ifdef DEBUG printf ("send(recv): "); @@ -946,7 +1090,14 @@ #ifdef DEBUG printf ("%02X(", (unsigned int)*p); #endif - ch = SendRecv(*p); + if (need_read == true) { + if (saved0 != 0xAC && p-queue < 3) // saved0 != 0xAC: Special case, programming enable needs read back at third byte + ch = SendRecv(*p, true); + else + ch = SendRecv(*p, false); + } else + ch = SendRecv(*p, true); + #ifdef DEBUG printf ("%02X) ", (unsigned int)ch); #endif @@ -994,6 +1145,8 @@ pa_type = PAT_MAXI; else if (val && strcmp(val, "xil") == 0) pa_type = PAT_XIL; + else if (val && strcmp(val, "ftdi") == 0) + pa_type = PAT_FTDI; else if (val && strcmp(val, "dasa") == 0) pa_type = PAT_DASA; else if (val && strcmp(val, "dasa2") == 0) @@ -1059,13 +1212,49 @@ if (fcntl(ppdev_fd, F_SETFL, flags) == -1) { throw Error_C(); } } } else { + if (pa_type == PAT_FTDI) { + #ifdef FTDI_BITBANG + ftdi_init(&ftdi); + + int i = ftdi_usb_open (&ftdi, 0x0403, 0xF8A8); + if (i != 0) { + Info(0, "FTDI open failed: %d\n", i); + exit (-1); + } else { + Info(3, "Found FTDI USB chip\n"); + } + + unsigned char bitbang_bitmask = 0; + bitbang_bitmask |= FTDI_DOUT; + bitbang_bitmask |= FTDI_SCK; + bitbang_bitmask |= FTDI_RESET; + + i = ftdi_enable_bitbang(&ftdi, bitbang_bitmask); + if (i != 0) { + Info (0, "Unable to enable bitbang mode: %d\n", i); + exit (-1); + } else { + Info (0, "Enabled FTDI bitbang mode using this bitmask: 0x%X\n", bitbang_bitmask); + } + + i = ftdi_set_baudrate(&ftdi, 9600); + if (i == 0) { + Info (3, "Set FTDI baudrate to 9600\n"); + } else { + Info (0, "Unable to change FTDI baudrate: %d\n", i); + exit (-1); + } + #else + throw Error_Device ("Please recompile uisp with ./configure --with-ftdi-bitbang"); + #endif + } else ppdev_fd = open(ppdev_name, O_RDWR, 0); } - if (ppdev_fd == -1) { + if (pa_type != PAT_FTDI && ppdev_fd == -1) { perror(ppdev_name); throw Error_Device("Failed to open ppdev."); } - if (!pa_type_is_serial && par_claim(ppdev_fd) != 0) { + if (!pa_type_is_serial && pa_type != PAT_FTDI && par_claim(ppdev_fd) != 0) { perror("ioctl PPCLAIM"); close(ppdev_fd); ppdev_fd = -1; @@ -1124,6 +1313,32 @@ OutReset(1); OutEnaReset(0); + #ifdef FTDI_BITBANG + if (pa_type == PAT_FTDI) { + // paranoia, should never happen + if (ftdi_buffer_pos > 0) { + Info(3, "Flushing %d bytes from the FTDI buffer\n", ftdi_buffer_pos); + ftdi_write_data(&ftdi, ftdi_buffer, ftdi_buffer_pos); + ftdi_buffer_pos = 0; + } + + Info(3, "FTDI buffer size is %d bytes\n", ftdi_buffer_size); + free (ftdi_buffer); + ftdi_buffer = NULL; + ftdi_buffer_size = 0; + + Info(3, "Disabling FTDI bitbang mode: "); + if (ftdi_disable_bitbang(&ftdi) == 0) + Info (3, "OK\n"); + else + Info (3, "failed\n"); + + ftdi_usb_close(&ftdi); + ftdi_deinit(&ftdi); + return; + } + #endif + if (ppdev_fd != -1) { if (pa_type_is_serial) tcsetattr(ppdev_fd, TCSADRAIN, &saved_modes); diff -u -r --new-file uisp-20030220cvs/src/DAPA.h uisp.patched/src/DAPA.h --- uisp-20030220cvs/src/DAPA.h 2003-03-04 04:22:26.000000000 +0100 +++ uisp.patched/src/DAPA.h 2004-03-25 17:57:18.000000000 +0100 @@ -45,7 +45,7 @@ public: enum TPaType{ PAT_DAPA, PAT_STK200, PAT_ABB, PAT_AVRISP, PAT_BSD, PAT_FBPRG, PAT_DT006, PAT_ETT, PAT_MAXI, PAT_XIL, - PAT_DASA, PAT_DASA2 }; + PAT_DASA, PAT_DASA2, PAT_FTDI }; private: int mosi_invert; @@ -64,7 +64,7 @@ unsigned int ser_ctrl; /* TIOCMGET/TIOCMSET */ private: - int SendRecv(int); + int SendRecv(int, bool skip_read); /* low level access to parallel port lines */ void OutReset(int); void OutSck(int); diff -u -r --new-file uisp-20030220cvs/src/Main.C uisp.patched/src/Main.C --- uisp-20030220cvs/src/Main.C 2003-03-04 04:22:26.000000000 +0100 +++ uisp.patched/src/Main.C 2004-03-25 17:57:18.000000000 +0100 @@ -85,7 +85,7 @@ " pavr http://avr.jpk.co.nz/pavr/pavr.html\n" " stk500 Atmel STK500\n" #ifndef NO_DAPA -" -dprog=dapa|stk200|abb|avrisp|bsd|fbprg|dt006|maxi|xil|dasa|dasa2\n" +" -dprog=dapa|stk200|abb|avrisp|bsd|fbprg|dt006|maxi|xil|ftdi|dasa|dasa2\n" " Programmer type:\n" " dapa Direct AVR Parallel Access\n" " stk200 Parallel Starter Kit STK200, STK300\n" @@ -97,6 +97,7 @@ " maxi Investment Technologies Maxi (parallel)\n" " xil Xilinx HW-JTAG-PC Cable (parallel)\n" " ett ETT AVR Programmer V2.0 [from Futurtec] (parallel)\n" +" ftdi FTDI FT232BM and FT245BM bitbang mode\n" " dasa serial (RESET=RTS SCK=DTR MOSI=TXD MISO=CTS)\n" " dasa2 serial (RESET=!TXD SCK=RTS MOSI=DTR MISO=CTS)\n" "\n"