static int do_request(PROGRAMMER * pgm, AVRMEM *m) { struct ft245r_request *p; int addr, bytes, j, n; char buf[FT245R_FRAGMENT_SIZE+1+128]; if (!req_head) return 0; p = req_head; req_head = p->next; if (!req_head) req_tail = req_head; addr = p->addr; bytes = p->bytes; n = p->n; memset(p, 0, sizeof(struct ft245r_request)); p->next = req_pool; req_pool = p; ft245r_recv(pgm, buf, bytes); for (j=0; j<n; j++) { m->buf[addr++] = extract_data(buf , (j * 4 + 3)); } #if 0 if (n == 0) // paged_write fprintf(stderr, "recv addr 0x%04x buf size %d \n",addr, bytes); #endif return 1; }
static int set_reset(PROGRAMMER * pgm, int val) { unsigned char buf[1]; buf[0] = 0; if (val) buf[0] |= ft245r_reset; ft245r_send (pgm, buf, 1); ft245r_recv (pgm, buf, 1); return 0; }
static int set_pin(PROGRAMMER * pgm, int pinname, int val) { unsigned char buf[1]; if (pgm->pin[pinname].mask[0] == 0) { // ignore not defined pins (might be the led or vcc or buff if not needed) return 0; } ft245r_out = SET_BITS_0(ft245r_out,pgm,pinname,val); buf[0] = ft245r_out; ft245r_send (pgm, buf, 1); ft245r_recv (pgm, buf, 1); return 0; }
static int ft245r_drain(PROGRAMMER * pgm, int display) { int r; unsigned char t; // flush the buffer in the chip by changing the mode..... r = ftdi_set_bitmode(handle, 0, BITMODE_RESET); // reset if (r) return -1; r = ftdi_set_bitmode(handle, ft245r_ddr, BITMODE_SYNCBB); // set Synchronuse BitBang if (r) return -1; // drain our buffer. while (head != tail) { ft245r_recv (pgm, &t, 1); } return 0; }
/* * transmit an AVR device command and return the results; 'cmd' and * 'res' must point to at least a 4 byte data buffer */ static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char *res) { int i,buf_pos; unsigned char buf[128]; buf_pos = 0; for (i=0; i<4; i++) { buf_pos += set_data(pgm, buf+buf_pos, cmd[i]); } buf[buf_pos] = 0; buf_pos++; ft245r_send (pgm, buf, buf_pos); ft245r_recv (pgm, buf, buf_pos); res[0] = extract_data(pgm, buf, 0); res[1] = extract_data(pgm, buf, 1); res[2] = extract_data(pgm, buf, 2); res[3] = extract_data(pgm, buf, 3); return 0; }
static int do_request(PROGRAMMER * pgm, AVRMEM *m) { struct ft245r_request *p; int addr, bytes, j, n; unsigned char buf[FT245R_FRAGMENT_SIZE+1+128]; if (!req_head) return 0; p = req_head; req_head = p->next; if (!req_head) req_tail = req_head; addr = p->addr; bytes = p->bytes; n = p->n; memset(p, 0, sizeof(struct ft245r_request)); p->next = req_pool; req_pool = p; ft245r_recv(pgm, buf, bytes); for (j=0; j<n; j++) { m->buf[addr++] = extract_data(pgm, buf , (j * 4 + 3)); } return 1; }
static int ft245r_open(PROGRAMMER * pgm, char * port) { int rv; int devnum = -1; rv = pins_check(pgm,pin_checklist,sizeof(pin_checklist)/sizeof(pin_checklist[0]), true); if(rv) { pgm->display(pgm, progbuf); return rv; } strcpy(pgm->port, port); if (strcmp(port,DEFAULT_USB) != 0) { if (strncasecmp("ft", port, 2) == 0) { char *startptr = port + 2; char *endptr = NULL; devnum = strtol(startptr,&endptr,10); if ((startptr==endptr) || (*endptr != '\0')) { devnum = -1; } } if (devnum < 0) { avrdude_message(MSG_INFO, "%s: invalid portname '%s': use 'ft[0-9]+'\n", progname,port); return -1; } } else { devnum = 0; } handle = malloc (sizeof (struct ftdi_context)); ftdi_init(handle); LNODEID usbpid = lfirst(pgm->usbpid); int pid; if (usbpid) { pid = *(int *)(ldata(usbpid)); if (lnext(usbpid)) avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n", progname, pid); } else { pid = USB_DEVICE_FT245; } rv = ftdi_usb_open_desc_index(handle, pgm->usbvid?pgm->usbvid:USB_VENDOR_FTDI, pid, pgm->usbproduct[0]?pgm->usbproduct:NULL, pgm->usbsn[0]?pgm->usbsn:NULL, devnum); if (rv) { avrdude_message(MSG_INFO, "can't open ftdi device %d. (%s)\n", devnum, ftdi_get_error_string(handle)); goto cleanup_no_usb; } ft245r_ddr = pgm->pin[PIN_AVR_SCK].mask[0] | pgm->pin[PIN_AVR_MOSI].mask[0] | pgm->pin[PIN_AVR_RESET].mask[0] | pgm->pin[PPI_AVR_BUFF].mask[0] | pgm->pin[PPI_AVR_VCC].mask[0] | pgm->pin[PIN_LED_ERR].mask[0] | pgm->pin[PIN_LED_RDY].mask[0] | pgm->pin[PIN_LED_PGM].mask[0] | pgm->pin[PIN_LED_VFY].mask[0]; /* set initial values for outputs, no reset everything else is off */ ft245r_out = 0; ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_RESET,1); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_BUFF,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_VCC,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_ERR,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_RDY,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_PGM,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_VFY,0); rv = ftdi_set_bitmode(handle, ft245r_ddr, BITMODE_SYNCBB); // set Synchronous BitBang if (rv) { avrdude_message(MSG_INFO, "%s: Synchronous BitBangMode is not supported (%s)\n", progname, ftdi_get_error_string(handle)); goto cleanup; } rv = ft245r_set_bitclock(pgm); if (rv) { goto cleanup; } /* We start a new thread to read the output from the FTDI. This is * necessary because otherwise we'll deadlock. We cannot finish * writing because the ftdi cannot send the results because we * haven't provided a read buffer yet. */ sem_init (&buf_data, 0, 0); sem_init (&buf_space, 0, BUFSIZE); pthread_create (&readerthread, NULL, reader, handle); /* * drain any extraneous input */ ft245r_drain (pgm, 0); ft245r_send (pgm, &ft245r_out, 1); ft245r_recv (pgm, &ft245r_in, 1); return 0; cleanup: ftdi_usb_close(handle); cleanup_no_usb: ftdi_deinit (handle); free(handle); handle = NULL; return -1; }