Updated FSF address in all files. Fixes ticket:51
[debian/gnuradio] / ezdop / src / host / avrdude / ftbb.c
1 /*
2  * avrdude - A Downloader/Uploader for AVR device programmers
3  * Copyright (C) 2003-2004  Theodore A. Roth  <troth@openavr.org>
4  * Copyright (C) 2005 Johnathan Corgan <jcorgan@aeinet.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
19  */
20
21 /*
22  * avrdude interface for serial programming via FTDI bit bang mode operation. 
23  */
24
25 #include "ac_cfg.h"
26 #include "avr.h"
27 #include "pgm.h"
28 #include "ftbb.h"
29 #include <string.h>
30
31 #if FTDI_SUPPORT
32 #define FTBB_DEBUG 0
33
34 #if HAVE_LIBFTD2XX
35 #include <ftd2xx.h>
36 #elif HAVE_FTDI_H
37 #include <ftdi.h>
38 #endif
39
40 #define RESET   (1<<(pgm->pinno[PIN_AVR_RESET]-1))
41 #define SCK     (1<<(pgm->pinno[PIN_AVR_SCK]-1))
42 #define MOSI    (1<<(pgm->pinno[PIN_AVR_MOSI]-1))
43 #define MISO    (1<<(pgm->pinno[PIN_AVR_MISO]-1))
44 #define FTDDR   (MOSI|SCK|RESET)
45
46 #if HAVE_LIBFTD2XX
47 static FT_STATUS status;
48 static FT_HANDLE handle;
49 #elif HAVE_FTDI_H
50 static struct ftdi_context device;
51 static int status;
52 #endif
53
54 static unsigned char txbits;
55
56 /* Send 8 bits over SPI bus with per-bit read back
57  *
58  */
59 static unsigned char ftbb_txrx(PROGRAMMER *pgm, unsigned char val)
60 {
61     int i;
62     unsigned char bits;
63     unsigned char res;    
64
65 #if HAVE_LIBFTD2XX
66     DWORD written;
67 #endif /* HAVE_LIBFTD2XX */
68
69     res = 0;
70     bits = 0;
71     for (i = 0; i < 8; i++) {  // For each bit
72         // Set up data on low phase of SCK
73         txbits &= ~SCK;
74
75         // Set MOSI to high bit of transmit data
76         if (val & 0x80)
77             txbits |= MOSI;
78         else
79             txbits &= ~MOSI;
80
81 #if HAVE_LIBFTD2XX
82         FT_Write(handle, &txbits, 1, &written);
83         // Clock just fell, read previous input bit and shift in
84         FT_GetBitMode(handle, &bits);
85 #elif HAVE_FTDI_H
86         ftdi_write_data(&device, &txbits, 1);
87         // Clock just fell, read previous input bit and shift in
88         ftdi_read_pins(&device, &bits);        
89 #endif /* HAVE_LIBFTD2XX */
90         res = (res << 1) | (bits & MISO);
91
92         // Now raise SCK to latch data in AVR
93         txbits |= SCK;
94
95 #if HAVE_LIBFTD2XX
96         FT_Write(handle, &txbits, 1, &written);
97 #elif HAVE_FTDI_H
98         ftdi_write_data(&device, &txbits, 1);
99 #endif /* HAVE_LIBFTD2XX */
100         // Move on to next bit in transmit data
101         val = val << 1;
102     }
103
104     return res;
105 }
106
107 /* Generic programmer command function for pgm->cmd
108  *
109  * Sends four bytes of command in sequence and collects responses
110  *
111  */
112 static int ftbb_cmd(PROGRAMMER *pgm, unsigned char cmd[4], unsigned char res[4])
113 {
114     int i;
115     
116 #if FTBB_DEBUG
117     printf("CMD: %02X%02X%02X%02X  ", cmd[0], cmd[1], cmd[2], cmd[3]);
118 #endif
119
120     for (i = 0; i < 4; i++) {
121         res[i] = ftbb_txrx(pgm, cmd[i]);
122     }
123     
124 #if FTBB_DEBUG
125     printf("RES: %02X%02X%02X%02X\n", res[0], res[1], res[2], res[3]);
126 #endif
127
128     return 0;
129 }
130
131 /* Programmer initialization command for pgm->initialize
132  *
133  * Pulse RESET with SCK low, then send SPI start programming command
134  *
135  */
136 static int ftbb_initialize(PROGRAMMER *pgm, AVRPART *p)
137 {
138 #if HAVE_LIBFTD2XX
139     DWORD written;
140 #endif /* HAVE_LIBFTD2XX */
141
142     // Atmel documentation says to raise RESET for 2 cpu clocks while sclk is low
143     // then lower RESET and wait 20 ms.
144     txbits |= RESET;
145
146 #if HAVE_LIBFTD2XX
147     FT_Write(handle, &txbits, 1, &written);
148 #elif HAVE_FTDI_H
149     ftdi_write_data(&device, &txbits, 1);
150 #endif /* HAVE_LIBFTD2XX */
151
152     usleep(1000); // 2 AVR cpu clocks at any realistic clock rate
153     txbits &= ~RESET;
154
155 #if HAVE_LIBFTD2XX
156     FT_Write(handle, &txbits, 1, &written);
157 #elif HAVE_FTDI_H
158     ftdi_write_data(&device, &txbits, 1);
159 #endif /* HAVE_LIBFTD2XX */
160
161     usleep(20000);
162
163     pgm->program_enable(pgm, p);
164     return 0;
165 }
166
167 /* Programmer status display for pgm->display
168  *
169  * Not-implemented
170  *
171  */
172 static void ftbb_display(PROGRAMMER *pgm, char *p)
173 {
174 #if FTBB_DEBUG
175     printf("ftbb: display called with: %s\n", p);
176 #endif
177
178     printf("FTBB: RESET mapped to pinno %d\n", pgm->pinno[PIN_AVR_RESET]);
179     printf("FTBB: SCK   mapped to pinno %d\n", pgm->pinno[PIN_AVR_SCK]);
180     printf("FTBB: MOSI  mapped to pinno %d\n", pgm->pinno[PIN_AVR_MOSI]);
181     printf("FTBB: MISO  mapped to pinno %d\n", pgm->pinno[PIN_AVR_MISO]);
182 }  
183
184 /* Programmer enable command for pgm->enable
185  *
186  * Lowers SCK and RESET in preparation for serial programming
187  *
188  */
189 static void ftbb_enable(PROGRAMMER *pgm)
190 {
191 #if HAVE_LIBFTD2XX
192     DWORD written;
193 #endif /* HAVE_LIBFTD2XX */
194
195     // Lower SCK & RESET
196     txbits &= ~SCK;
197     txbits &= ~RESET;
198
199 #if HAVE_LIBFTD2XX
200     FT_Write(handle, &txbits, 1, &written);
201 #elif HAVE_FTDI_H
202     ftdi_write_data(&device, &txbits, 1);
203 #endif /* HAVE_LIBFTD2XX */
204 }
205
206 /* Programmer disable command for pgm->disable
207  *
208  * Raises RESET to return to normal chip operation
209  *
210  */
211 static void ftbb_disable(PROGRAMMER *pgm)
212 {
213 #if HAVE_LIBFTD2XX
214     DWORD written;
215 #endif /* HAVE_LIBFTD2XX */  
216     // Raise RESET to return to normal mode
217     txbits |= RESET;
218
219 #if HAVE_LIBFTD2XX
220     FT_Write(handle, &txbits, 1, &written);
221 #elif HAVE_FTDI_H
222     ftdi_write_data(&device, &txbits, 1);
223 #endif /* HAVE_LIBFTD2XX */
224 }
225
226 /* Programmer programming mode enable function for pgm->program_enable
227  *
228  * Starts SPI programming mode 
229  *
230  */
231 static int ftbb_program_enable(PROGRAMMER *pgm, AVRPART *p)
232 {
233     unsigned char cmd[4];
234     unsigned char res[4];
235   
236     if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
237         fprintf(stderr, "program enable instruction not defined for part \"%s\"\n", p->desc);
238         return -1;
239     }
240
241     memset(cmd, 0, sizeof(cmd));
242     avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
243     pgm->cmd(pgm, cmd, res);
244
245     return 0;
246 }
247
248 /* Progammer erase function for pgm->erase
249  *
250  * Sends chip erase command and sleeps the chip erase delay
251  *
252  */ 
253 static int ftbb_chip_erase(PROGRAMMER *pgm, AVRPART *p)
254 {
255     unsigned char cmd[4];
256     unsigned char res[4];
257
258     if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
259         fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", p->desc);
260         return -1;
261     }
262
263     memset(cmd, 0, sizeof(cmd));
264     avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
265     pgm->cmd(pgm, cmd, res);
266     usleep(p->chip_erase_delay);
267
268     return 0;
269 }
270
271
272 /* Parse routine for device name
273  *
274  * FFFF:FFFF:0
275  *
276  */
277 int ftbb_parse_name(char *name, int *vid, int *pid, int *ifc)
278 {
279     printf("name=%s\n", name);
280     return 0;
281 }
282
283 /* Programmer open command for pgm->open
284  *
285  * Opens FTD2XX device specified by 'name', performs a chip reset, then
286  * sets the baudrate and bit bang mode
287  *
288  */
289 static int ftbb_open(PROGRAMMER *pgm, char *name)
290 {
291     int vid, pid, ifc;
292     ftbb_parse_name(name, &vid, &pid, &ifc);
293     
294 #if HAVE_LIBFTD2XX
295     int devnum = 0;
296     if (strcmp(name, "ft0")) {
297         fprintf(stderr, "ERROR: FTD2XX device selection not yet implemented!\n");
298         return -1;
299     }
300
301     // Call FTD2XX library to open device
302     if ((status = FT_Open(devnum, &handle)) != FT_OK) {
303         fprintf(stderr, "Failed to open FTD2XX device #%d.\n", devnum);
304         return -1;        
305     }
306
307     // Reset chipset
308     if ((status = FT_ResetDevice(handle)) != FT_OK) {
309         fprintf(stderr, "Failed to reset chipset for FTD2XX device #%d.\n", devnum);
310         return -1;
311     }
312
313     // Set baud rate for bit bang interface
314     if ((status = FT_SetBaudRate(handle, pgm->baudrate)) != FT_OK) {
315         fprintf(stderr, "Failed to set baud rate for FTD2XX device #%d.\n", devnum);
316         return -1;
317     }
318
319     // Set bit bang direction and mode
320     if ((status = FT_SetBitMode(handle, FTDDR, 1)) != FT_OK) {
321         fprintf(stderr, "Failed to set bit bang mode for FTD2XX device #%d.\n", devnum);
322         return -1;
323     }
324 #elif HAVE_FTDI_H
325     // Open device via FTDI library *** FIXME *** hardcoded VID and PID
326     if (ftdi_usb_open(&device, EZDOP_VENDORID, EZDOP_PRODUCTID)) {
327         fprintf(stderr, "ftdi_usb_open: %s", device.error_str);
328         return -1;
329     }
330
331     // Reset FTDI chipset
332     if (ftdi_usb_reset(&device)) {
333         fprintf(stderr, "ftdi_usb_reset: %s", device.error_str);
334         return -1;
335     }
336
337     // Set FTDI chipset baudrate for bitbang
338     if (ftdi_set_baudrate(&device, pgm->baudrate)) {
339         fprintf(stderr, "ftdi_set_baudrate: %s", device.error_str);
340         return -1;
341     }
342
343     // Enable bitbang
344     if (ftdi_enable_bitbang(&device, FTDDR)) {
345         fprintf(stderr, "ftdi_enable_bitbang: %s", device.error_str);
346         return -1;
347     }
348
349     // Minimum chunk size for reads to reduce latency
350     if (ftdi_read_data_set_chunksize(&device, 256)) {
351         fprintf(stderr, "ftdi_read_data_set_chunksize: %s", device.error_str);
352         return -1;
353     }
354 #endif /* HAVE_LIBFTD2XX */
355
356     return 0;
357 }
358
359 /* Programmer close function for pgm->close
360  *
361  * Releases FTD2XX device
362  *
363  */
364 static void ftbb_close(PROGRAMMER *pgm)
365 {
366 #if HAVE_LIBFTD2XX
367     FT_Close(handle);
368 #elif HAVE_FTDI_H
369     ftdi_deinit(&device);
370 #endif
371 }
372 #endif /* FTDI_SUPPORT */
373
374 /* Programmer initialization command for startup.
375  *
376  * Sets appropriate function pointers in structure
377  * Tests FTD2XX interface by enumerating number of devices
378  *
379  */
380 void ftbb_initpgm (PROGRAMMER *pgm)
381 {
382 #if FTDI_SUPPORT
383
384 #if HAVE_LIBFTD2XX
385     DWORD num_devices;
386 #endif
387
388     strcpy(pgm->type, "ftbb");
389     pgm->initialize = ftbb_initialize;
390     pgm->display = ftbb_display;
391     pgm->enable = ftbb_enable;
392     pgm->disable = ftbb_disable;
393     pgm->program_enable = ftbb_program_enable;
394     pgm->chip_erase = ftbb_chip_erase;  
395     pgm->cmd = ftbb_cmd;
396     pgm->open = ftbb_open;
397     pgm->close = ftbb_close;  
398
399 #if HAVE_LIBFTD2XX
400     if ((status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY)) != FT_OK)
401         fprintf(stderr, "Failed to initialize FTD2XX interface. (%li)\n", status);
402     else
403         printf("%lu FTD2XX device(s) found.\n", num_devices);
404 #elif HAVE_FTDI_H
405     if ((status = ftdi_init(&device)) < 0)
406         fprintf(stderr, "Failed to initialize FTDI interface. (%i)\n", status);
407 #endif     
408
409     txbits = RESET;
410 #endif /* FTDI_SUPPORT */
411 }
412