Follow along with the video below to see how to install our site as a web app on your home screen.
Nota: This feature currently requires accessing the site using the built-in Safari browser.
/*
* Clone of usb blaster driver
*
* Copyright (C) 2009 Setec Astronomy Project - who are not aware of the donation of this code
* to their cause, but can be notified by sending this file to them.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version, with the exception of
* any individual providing services to a corporation, or the corporation itself,
* if the name of the corporation starts with:
*
* "ARR" or "ALTER"
*
* These corporations and their employees, assigns, contractors, shareholders,
* rightsholders, attorneys and associates are specifically excluded by this
* license. This is not discriminatory; they can obtain software to perform
* interoperability and necessary functionality by pursuing internal licensing
* within their corporations or with all relevant rightsholders.
*
* Copyright infringement by the above corporations and their employees, assigns,
* contractors, shareholders, rightsholders, attorneys and associates will be
* prosecuted to the fullest extent of the law. This license shall be governed
* by the laws of the State of California. If any part of this license
* is deemed to be invalid under applicable law, the remainder of the license
* shall be deemed severable and remain in force.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
*
* Please read to the bottom of the file for instructions on how to use this.
*/
#include <string.h>
#include <dlfcn.h>
/*
* The following section is pasted verbatim from libftdi.h, part of the package
* libftdi-0.18
*
* If you prefer, you can use the file installed on your system using:
* #include "libftdi-0.18.h"
*
* libftdi.so must also be installed from the same package. It is dynamically loaded
* below.
*
* The following is Copyright (C) 2003 by Intra2net AG, and is licensed under
* the GNU Lesser General Public License.
*
* The derived work, namely, the whole of this file, is governed by the copyright above,
* under the compatible but more restrictive GNU Affero General Public License.
*/
/***************************************************************************
ftdi.h - description
-------------------
begin : Fri Apr 4 2003
copyright : (C) 2003 by Intra2net AG
email : opensource@intra2net.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License *
* version 2.1 as published by the Free Software Foundation; *
* *
***************************************************************************/
#ifndef __libftdi_h__
#define __libftdi_h__
#include <usb.h>
#define FTDI_DEFAULT_EEPROM_SIZE 128
/** FTDI chip type */
enum ftdi_chip_type { TYPE_AM=0, TYPE_BM=1, TYPE_2232C=2, TYPE_R=3, TYPE_2232H=4, TYPE_4232H=5 };
/** Parity mode for ftdi_set_line_property() */
enum ftdi_parity_type { NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4 };
/** Number of stop bits for ftdi_set_line_property() */
enum ftdi_stopbits_type { STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2 };
/** Number of bits for ftdi_set_line_property() */
enum ftdi_bits_type { BITS_7=7, BITS_8=8 };
/** Break type for ftdi_set_line_property2() */
enum ftdi_break_type { BREAK_OFF=0, BREAK_ON=1 };
/** MPSSE bitbang modes */
enum ftdi_mpsse_mode
{
BITMODE_RESET = 0x00, /**< switch off bitbang mode, back to regular serial/FIFO */
BITMODE_BITBANG= 0x01, /**< classical asynchronous bitbang mode, introduced with B-type chips */
BITMODE_MPSSE = 0x02, /**< MPSSE mode, available on 2232x chips */
BITMODE_SYNCBB = 0x04, /**< synchronous bitbang mode, available on 2232x and R-type chips */
BITMODE_MCU = 0x08, /**< MCU Host Bus Emulation mode, available on 2232x chips */
/* CPU-style fifo mode gets set via EEPROM */
BITMODE_OPTO = 0x10, /**< Fast Opto-Isolated Serial Interface Mode, available on 2232x chips */
BITMODE_CBUS = 0x20, /**< Bitbang on CBUS pins of R-type chips, configure in EEPROM before */
BITMODE_SYNCFF = 0x40, /**< Single Channel Synchronous FIFO mode, available on 2232H chips */
};
/** Port interface for chips with multiple interfaces */
enum ftdi_interface
{
INTERFACE_ANY = 0,
INTERFACE_A = 1,
INTERFACE_B = 2,
INTERFACE_C = 3,
INTERFACE_D = 4
};
/* Shifting commands IN MPSSE Mode*/
#define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/
#define MPSSE_BITMODE 0x02 /* Write bits, not bytes */
#define MPSSE_READ_NEG 0x04 /* Sample TDO/DI on negative TCK/SK edge */
#define MPSSE_LSB 0x08 /* LSB first */
#define MPSSE_DO_WRITE 0x10 /* Write TDI/DO */
#define MPSSE_DO_READ 0x20 /* Read TDO/DI */
#define MPSSE_WRITE_TMS 0x40 /* Write TMS/CS */
/* FTDI MPSSE commands */
#define SET_BITS_LOW 0x80
/*BYTE DATA*/
/*BYTE Direction*/
#define SET_BITS_HIGH 0x82
/*BYTE DATA*/
/*BYTE Direction*/
#define GET_BITS_LOW 0x81
#define GET_BITS_HIGH 0x83
#define LOOPBACK_START 0x84
#define LOOPBACK_END 0x85
#define TCK_DIVISOR 0x86
/* Value Low */
/* Value HIGH */ /*rate is 12000000/((1+value)*2) */
#define DIV_VALUE(rate) (rate > 6000000)?0:((6000000/rate -1) > 0xffff)? 0xffff: (6000000/rate -1)
/* Commands in MPSSE and Host Emulation Mode */
#define SEND_IMMEDIATE 0x87
#define WAIT_ON_HIGH 0x88
#define WAIT_ON_LOW 0x89
/* Commands in Host Emulation Mode */
#define READ_SHORT 0x90
/* Address_Low */
#define READ_EXTENDED 0x91
/* Address High */
/* Address Low */
#define WRITE_SHORT 0x92
/* Address_Low */
#define WRITE_EXTENDED 0x93
/* Address High */
/* Address Low */
/* Definitions for flow control */
#define SIO_RESET 0 /* Reset the port */
#define SIO_MODEM_CTRL 1 /* Set the modem control register */
#define SIO_SET_FLOW_CTRL 2 /* Set flow control register */
#define SIO_SET_BAUD_RATE 3 /* Set baud rate */
#define SIO_SET_DATA 4 /* Set the data characteristics of the port */
#define FTDI_DEVICE_OUT_REQTYPE (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT)
#define FTDI_DEVICE_IN_REQTYPE (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN)
/* Requests */
#define SIO_RESET_REQUEST SIO_RESET
#define SIO_SET_BAUDRATE_REQUEST SIO_SET_BAUD_RATE
#define SIO_SET_DATA_REQUEST SIO_SET_DATA
#define SIO_SET_FLOW_CTRL_REQUEST SIO_SET_FLOW_CTRL
#define SIO_SET_MODEM_CTRL_REQUEST SIO_MODEM_CTRL
#define SIO_POLL_MODEM_STATUS_REQUEST 0x05
#define SIO_SET_EVENT_CHAR_REQUEST 0x06
#define SIO_SET_ERROR_CHAR_REQUEST 0x07
#define SIO_SET_LATENCY_TIMER_REQUEST 0x09
#define SIO_GET_LATENCY_TIMER_REQUEST 0x0A
#define SIO_SET_BITMODE_REQUEST 0x0B
#define SIO_READ_PINS_REQUEST 0x0C
#define SIO_READ_EEPROM_REQUEST 0x90
#define SIO_WRITE_EEPROM_REQUEST 0x91
#define SIO_ERASE_EEPROM_REQUEST 0x92
#define SIO_RESET_SIO 0
#define SIO_RESET_PURGE_RX 1
#define SIO_RESET_PURGE_TX 2
#define SIO_DISABLE_FLOW_CTRL 0x0
#define SIO_RTS_CTS_HS (0x1 << 8)
#define SIO_DTR_DSR_HS (0x2 << 8)
#define SIO_XON_XOFF_HS (0x4 << 8)
#define SIO_SET_DTR_MASK 0x1
#define SIO_SET_DTR_HIGH ( 1 | ( SIO_SET_DTR_MASK << 8))
#define SIO_SET_DTR_LOW ( 0 | ( SIO_SET_DTR_MASK << 8))
#define SIO_SET_RTS_MASK 0x2
#define SIO_SET_RTS_HIGH ( 2 | ( SIO_SET_RTS_MASK << 8 ))
#define SIO_SET_RTS_LOW ( 0 | ( SIO_SET_RTS_MASK << 8 ))
#define SIO_RTS_CTS_HS (0x1 << 8)
/* marker for unused usb urb structures
(taken from libusb) */
#define FTDI_URB_USERCONTEXT_COOKIE ((void *)0x1)
#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif
/**
\brief Main context structure for all libftdi functions.
Do not access directly if possible.
*/
struct ftdi_context
{
/* USB specific */
/** libusb's usb_dev_handle */
struct usb_dev_handle *usb_dev;
/** usb read timeout */
int usb_read_timeout;
/** usb write timeout */
int usb_write_timeout;
/* FTDI specific */
/** FTDI chip type */
enum ftdi_chip_type type;
/** baudrate */
int baudrate;
/** bitbang mode state */
unsigned char bitbang_enabled;
/** pointer to read buffer for ftdi_read_data */
unsigned char *readbuffer;
/** read buffer offset */
unsigned int readbuffer_offset;
/** number of remaining data in internal read buffer */
unsigned int readbuffer_remaining;
/** read buffer chunk size */
unsigned int readbuffer_chunksize;
/** write buffer chunk size */
unsigned int writebuffer_chunksize;
/** maximum packet size. Needed for filtering modem status bytes every n packets. */
unsigned int max_packet_size;
/* FTDI FT2232C requirecments */
/** FT2232C interface number: 0 or 1 */
int interface; /* 0 or 1 */
/** FT2232C index number: 1 or 2 */
int index; /* 1 or 2 */
/* Endpoints */
/** FT2232C end points: 1 or 2 */
int in_ep;
int out_ep; /* 1 or 2 */
/** Bitbang mode. 1: (default) Normal bitbang mode, 2: FT2232C SPI bitbang mode */
unsigned char bitbang_mode;
/** EEPROM size. Default is 128 bytes for 232BM and 245BM chips */
int eeprom_size;
/** String representation of last error */
char *error_str;
/** Buffer needed for async communication */
char *async_usb_buffer;
/** Number of URB-structures we can buffer */
unsigned int async_usb_buffer_size;
};
/**
\brief list of usb devices created by ftdi_usb_find_all()
*/
struct ftdi_device_list
{
/** pointer to next entry */
struct ftdi_device_list *next;
/** pointer to libusb's usb_device */
struct usb_device *dev;
};
/**
\brief FTDI eeprom structure
*/
struct ftdi_eeprom
{
/** vendor id */
int vendor_id;
/** product id */
int product_id;
/** self powered */
int self_powered;
/** remote wakeup */
int remote_wakeup;
/** chip type */
int BM_type_chip;
/** input in isochronous transfer mode */
int in_is_isochronous;
/** output in isochronous transfer mode */
int out_is_isochronous;
/** suspend pull downs */
int suspend_pull_downs;
/** use serial */
int use_serial;
/** fake usb version */
int change_usb_version;
/** usb version */
int usb_version;
/** maximum power */
int max_power;
/** manufacturer name */
char *manufacturer;
/** product name */
char *product;
/** serial number */
char *serial;
/** eeprom size in bytes. This doesn't get stored in the eeprom
but is the only way to pass it to ftdi_eeprom_build. */
int size;
};
#ifdef __cplusplus
extern "C"
{
#endif
int ftdi_init(struct ftdi_context *ftdi);
struct ftdi_context *ftdi_new(void);
int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface);
void ftdi_deinit(struct ftdi_context *ftdi);
void ftdi_free(struct ftdi_context *ftdi);
void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usbdev);
int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devlist,
int vendor, int product);
void ftdi_list_free(struct ftdi_device_list **devlist);
void ftdi_list_free2(struct ftdi_device_list *devlist);
int ftdi_usb_get_strings(struct ftdi_context *ftdi, struct usb_device *dev,
char * manufacturer, int mnf_len,
char * description, int desc_len,
char * serial, int serial_len);
int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product);
int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product,
const char* description, const char* serial);
int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product,
const char* description, const char* serial, unsigned int index);
int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev);
int ftdi_usb_open_string(struct ftdi_context *ftdi, const char* description);
int ftdi_usb_close(struct ftdi_context *ftdi);
int ftdi_usb_reset(struct ftdi_context *ftdi);
int ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi);
int ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi);
int ftdi_usb_purge_buffers(struct ftdi_context *ftdi);
int ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate);
int ftdi_set_line_property(struct ftdi_context *ftdi, enum ftdi_bits_type bits,
enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity);
int ftdi_set_line_property2(struct ftdi_context *ftdi, enum ftdi_bits_type bits,
enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity,
enum ftdi_break_type break_type);
int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size);
int ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize);
int ftdi_read_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunksize);
int ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size);
int ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize);
int ftdi_write_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunksize);
int ftdi_write_data_async(struct ftdi_context *ftdi, unsigned char *buf, int size);
void ftdi_async_complete(struct ftdi_context *ftdi, int wait_for_more);
int DEPRECATED(ftdi_enable_bitbang(struct ftdi_context *ftdi, unsigned char bitmask));
int ftdi_disable_bitbang(struct ftdi_context *ftdi);
int ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode);
int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins);
int ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency);
int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency);
int ftdi_poll_modem_status(struct ftdi_context *ftdi, unsigned short *status);
/* flow control */
int ftdi_setflowctrl(struct ftdi_context *ftdi, int flowctrl);
int ftdi_setdtr_rts(struct ftdi_context *ftdi, int dtr, int rts);
int ftdi_setdtr(struct ftdi_context *ftdi, int state);
int ftdi_setrts(struct ftdi_context *ftdi, int state);
int ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable);
int ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable);
/* set eeprom size */
void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, int size);
/* init and build eeprom from ftdi_eeprom structure */
void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom);
void ftdi_eeprom_free(struct ftdi_eeprom *eeprom);
int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output);
int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *output, int size);
/* "eeprom" needs to be valid 128 byte eeprom (generated by the eeprom generator)
the checksum of the eeprom is valided */
int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom);
int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid);
int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char *eeprom, int maxsize);
int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom);
int ftdi_erase_eeprom(struct ftdi_context *ftdi);
int ftdi_read_eeprom_location (struct ftdi_context *ftdi, int eeprom_addr, unsigned short *eeprom_val);
int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr, unsigned short eeprom_val);
char *ftdi_get_error_string(struct ftdi_context *ftdi);
#ifdef __cplusplus
}
#endif
#endif /* __libftdi_h__ */
/* end of libftdi.h */
#include <stdint.h>
#include <stdio.h>
#define ATTR_CDECL __attribute__((cdecl))
struct ftdi_so_st { /* pointers to libftdi.so */
ATTR_CDECL int (* p_ftdi_init)(struct ftdi_context *ftdi);
ATTR_CDECL uint32_t (* p_ftdi_interface_write)(void * unused_void, unsigned long const * buf, unsigned long count);
ATTR_CDECL int (* p_ftdi_set_interface)(struct ftdi_context *ftdi, enum ftdi_interface interface);
ATTR_CDECL void (* p_ftdi_deinit)(struct ftdi_context *ftdi);
ATTR_CDECL int (* p_ftdi_usb_open)(struct ftdi_context *ftdi, int vendor, int product);
ATTR_CDECL char (* p_ftdi_interface_close)(void * unused_void);
ATTR_CDECL int (* p_ftdi_usb_close)(struct ftdi_context *ftdi);
ATTR_CDECL int (* p_ftdi_usb_reset)(struct ftdi_context *ftdi);
ATTR_CDECL int (* p_ftdi_usb_purge_buffers)(struct ftdi_context *ftdi);
ATTR_CDECL int (* p_ftdi_read_data)(struct ftdi_context *ftdi, unsigned char *buf, int size);
ATTR_CDECL int (* p_ftdi_read_data_set_chunksize)(struct ftdi_context *ftdi, unsigned int chunksize);
ATTR_CDECL int (* p_ftdi_write_data)(struct ftdi_context *ftdi, unsigned char *buf, int size);
ATTR_CDECL int (* p_ftdi_write_data_set_chunksize)(struct ftdi_context *ftdi, unsigned int chunksize);
ATTR_CDECL int (* p_ftdi_write_data_get_chunksize)(struct ftdi_context *ftdi, unsigned int *chunksize);
ATTR_CDECL int (* p_ftdi_set_bitmode)(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode);
ATTR_CDECL char * (* p_ftdi_get_error_string)(struct ftdi_context *ftdi);
void * handle; /* handle to libftdi DSO returned from dlopen() */
unsigned chunksize; /* cached from ftdi_write_data_get_chunksize */
};
typedef ATTR_CDECL char (* fn_find_devs)(uint32_t dev_index, char * out_desc, uint32_t api_ver);
typedef ATTR_CDECL char (* fn_find_descriptions)(const char * description);
typedef ATTR_CDECL int (* fn_init_dev)(uint32_t * p_exit_status, const char * desc, struct ftdi_so_st * s_server_ops, void * parent);
typedef ATTR_CDECL void (* fn_close)(void * unused_void);
typedef ATTR_CDECL void (* fn_pkt_wr_pattern)(void * unused_void, uint32_t jtag_tms, uint32_t v, unsigned long len);
typedef ATTR_CDECL void (* fn_pkt_wr_bits)(void * unused_void, unsigned jtag_tms, unsigned long * p_bits, unsigned long len, unsigned long field_144_minus_len);
typedef ATTR_CDECL char (* fn_do_flush)(void * unused_void, int bool_val, uint32_t index_val);
struct virtual_fns_st { /* ABI to pass data in and out of driver */
uint32_t st_size; /* to check ABI compatibility */
char dev_description[32];
uint32_t st_flags;
void * reserved01[2];
fn_find_devs p_find_devs;
fn_find_descriptions p_find_descriptions;
fn_init_dev p_init_dev;
fn_close p_close;
void * reserved02[3];
fn_pkt_wr_pattern p_pkt_wr_pattern;
fn_pkt_wr_bits p_pkt_wr_bits;
void * reserved03[1];
fn_do_flush p_do_flush;
void * reserved04[5];
};
struct driver_st
{
uint32_t num_devs;
struct virtual_fns_st vfns;
struct ftdi_so_st ffns, str_fns;
struct ftdi_context dev_info;
void * parent;
uint8_t w_buf[0x10000]; /* FT2232D can receive up to 64KB in one USB transfer */
uint32_t w_buf_use, want_read, last_tms, last_cmd, chain_3d;
uint8_t r_buf_2[0x10000], r_nbits[0x10000];
};
extern struct driver_st d;
int do_ftdi_write(uint8_t * c, size_t s)
{
if (!d.ffns.chunksize) return 1;
int r;
if (d.ffns.chunksize < ((s + 0xff) & ~0xff)) {
if ((r = d.ffns.p_ftdi_write_data_set_chunksize(&d.dev_info, (s + 0xff) & ~0xff)) < 0) return 1;
}
size_t i;
if ((r = d.ffns.p_ftdi_write_data(&d.dev_info, c, s)) < 0) return 1;
if (!d.want_read) return 0;
unsigned got_read;
for (got_read = 0, i = 0; got_read < d.want_read; got_read += r, i++) {
if ((r = d.ffns.p_ftdi_read_data(&d.dev_info, &d.r_buf_2[got_read], sizeof(d.r_buf_2)/sizeof(d.r_buf_2[0]) - got_read)) < 0) return 1;
if (i >= 10) return 1;
}
return 0;
}
ATTR_CDECL char find_devs(uint32_t dev_index, char * out_desc, uint32_t api_ver)
{
if (api_ver < 4) return 0;
if (dev_index >= d.num_devs) return 0;
strcpy(out_desc, "bus-instance");
return 1;
}
ATTR_CDECL char find_descriptions(const char * description)
{
return !strcmp(description, "bus-instance");
}
inline void init_w_buf_red_on()
{
d.w_buf[0] = 0x80;
d.w_buf[1] = 0x10;
d.w_buf[2] = 0x9b;
d.w_buf_use = 3;
d.last_tms = 0;
d.last_cmd = 0;
d.chain_3d = 0;
d.want_read = 0;
}
ATTR_CDECL int init_dev(uint32_t * p_exit_status, const char * desc, struct ftdi_so_st * s_server_ops, void * parent)
{
if (!parent) return 1;
if (strcmp(desc, "bus-instance") != 0) return 1;
init_w_buf_red_on();
if (d.ffns.chunksize) return 1;
memset(&d.str_fns, 0, sizeof(d.str_fns));
d.str_fns.p_ftdi_interface_write = s_server_ops->p_ftdi_interface_write;
d.str_fns.p_ftdi_interface_close = s_server_ops->p_ftdi_interface_close;
d.parent = parent;
if (d.ffns.chunksize) return 1;
if (d.ffns.p_ftdi_write_data_get_chunksize(&d.dev_info, &d.ffns.chunksize) < 0 || d.ffns.p_ftdi_set_bitmode(&d.dev_info, 0x0b, 2) < 0) return 1;
d.want_read = 0;
uint8_t cmd[] = { 0x80, 0x90, 0x9b, 0x82, 0x07, 0x07, 0x86, 0, 0, 0x85, };
if (do_ftdi_write(cmd, sizeof(cmd)) || d.ffns.p_ftdi_usb_purge_buffers(&d.dev_info) < 0) return 1;
*p_exit_status = 1;
return 0;
}
ATTR_CDECL void do_close(void * unused_void)
{
}
ATTR_CDECL char do_flush(void * unused_void, int bool_val, uint32_t index_val)
{
if (!d.num_devs) return 1;
uint8_t * wp = &d.w_buf[d.w_buf_use];
*(wp++) = 0x80; *(wp++) = 0x10; *(wp++) = 0x9b; *(wp++) = 0x87;
do_ftdi_write(&d.w_buf[0], d.w_buf_use + 3);
unsigned ulout_use = 0, bit = 0, i, q;
for (i = 0; i < d.want_read; i++) {
uint8_t bv = d.r_buf_2[i];
for (q = 0; q < d.r_nbits[i]; q++) {
if (!bit) d.r_buf_2[ulout_use] = 0; /* prepare next byte to receive bits */
if (bv & (0x80 >> (d.r_nbits[i] - q - 1))) d.r_buf_2[ulout_use] |= 1 << bit;
bit++;
if (bit & 8) {
bit = 0;
ulout_use++;
}
}
}
if (d.str_fns.p_ftdi_interface_write) d.str_fns.p_ftdi_interface_write(d.parent, (unsigned long *) d.r_buf_2, ulout_use * 8 + bit);
if (d.str_fns.p_ftdi_interface_close) d.str_fns.p_ftdi_interface_close(d.parent);
init_w_buf_red_on();
return 1;
}
void send_bit(unsigned tms, unsigned v)
{
if (d.last_tms != tms) {
if (d.last_cmd == 0 && d.w_buf_use == 3) d.w_buf_use = 0;
/* datasheet: TMS should be asserted before rising edge of first clock */
d.w_buf[d.w_buf_use++] = 0x80; d.w_buf[d.w_buf_use++] = 0x10 | (tms ? 0x08 : 0); d.w_buf[d.w_buf_use++] = 0x9b;
d.last_tms = !!tms;
d.chain_3d = 0;
} else if (d.w_buf_use > 3 && d.w_buf[d.last_cmd] == 0x3e) {
if (d.w_buf[d.last_cmd + 1] < 6) {
d.w_buf[d.last_cmd + 2] |= (v ? 1 : 0) << (++d.w_buf[d.last_cmd + 1]);
d.r_nbits[d.want_read - 1]++;
} else {
if (!d.chain_3d) {
d.w_buf[d.last_cmd] = 0x3d;
d.w_buf[d.w_buf_use] = d.w_buf[d.w_buf_use - 1] | (v ? 0x80 : 0); d.w_buf[d.w_buf_use - 1] = 0x00; d.w_buf[d.w_buf_use - 2] = 0x00;
d.w_buf_use++;
d.r_nbits[d.want_read - 1]++;
d.chain_3d = d.last_cmd;
} else {
unsigned chain = (d.w_buf[d.chain_3d + 1] | (d.w_buf[d.chain_3d + 2] << 8)) + 1;
d.w_buf[d.chain_3d + 1] = chain & 0xff; d.w_buf[d.chain_3d + 2] = (chain >> 8) & 0xff; d.w_buf[d.chain_3d + 3 + chain] = d.w_buf[d.last_cmd + 2] | (v ? 0x80 : 0);
d.w_buf_use = d.chain_3d + chain + 4;
d.last_cmd = d.chain_3d;
d.r_nbits[d.want_read - 1]++;
}
}
return;
}
d.last_cmd = d.w_buf_use;
d.w_buf[d.w_buf_use++] = 0x3e; d.w_buf[d.w_buf_use++] = 0x00; d.w_buf[d.w_buf_use++] = (v ? 1 : 0);
d.r_nbits[d.want_read++] = 1;
if (d.want_read > 128) do_flush(0, 0, 0);
}
ATTR_CDECL void pkt_wr_pattern(void * unused_void, uint32_t jtag_tms, uint32_t v, unsigned long len)
{
if (!d.num_devs || len < 1) return;
unsigned long i;
for (i = 0; i < len; i++) send_bit(jtag_tms, v);
}
ATTR_CDECL void pkt_wr_bits(void * unused_void, unsigned jtag_tms, unsigned long * p_bits, unsigned long len, unsigned long field_144_minus_len)
{
if (!d.num_devs || len < 1) return;
unsigned long i;
for (i = 0; i < len; i++) send_bit(jtag_tms, (p_bits[i / 32] >> (i & 31)) & 1);
}
int do_set_interface()
{
if (d.ffns.p_ftdi_set_interface(&d.dev_info, INTERFACE_A) < 0 || d.ffns.p_ftdi_usb_open(&d.dev_info, Vendor, ProdID) < 0)
{
d.ffns.p_ftdi_deinit(&d.dev_info);
return 1;
}
if (d.ffns.p_ftdi_usb_reset(&d.dev_info) < 0 || d.ffns.p_ftdi_read_data_set_chunksize(&d.dev_info, 65536) < 0)
{
d.ffns.p_ftdi_usb_close(&d.dev_info);
d.ffns.p_ftdi_deinit(&d.dev_info);
return 1;
}
return 0;
}
struct driver_st d = {
.vfns = {
.st_size = sizeof(struct virtual_fns_st),
.dev_description = "usb-blaster-clone",
.st_flags = 0x800,
.p_find_devs = find_devs,
.p_find_descriptions = find_descriptions,
.p_init_dev = init_dev,
.p_close = do_close,
.p_pkt_wr_pattern = pkt_wr_pattern,
.p_pkt_wr_bits = pkt_wr_bits,
.p_do_flush = do_flush,
},
};
#define STRINGIFIER_DSO_METHOD_NAME(x) #x
#define STRINGIFY_DSO_METHOD_NAME(y) STRINGIFIER_DSO_METHOD_NAME(y)
#define STRING_DSO_METHOD_NAME STRINGIFY_DSO_METHOD_NAME(DSO_METHOD_NAME)
#define VISIBILITY_DEFAULT_EXTERN __attribute__((visibility("default"))) extern
VISIBILITY_DEFAULT_EXTERN struct virtual_fns_st * DSO_METHOD_NAME(uint32_t hw_type)
{
if (hw_type != 0) return 0;
if (d.ffns.handle) return &d.vfns;
d.ffns.handle = dlopen("libftdi.so", RTLD_NOW);
if (!d.ffns.handle) {
#if 0
If you have libftdi.so installed and you get this error, try a test:
Create a file test.c:
int main() { return 0; }
Next, compile it with: gcc -o test -lftdi test.c
Use google to fix any problems, then make sure libftdi.so is in /usr/lib
As a last resort, change the call to dlopen() above so it has the full file path
#endif
return 0;
}
#define load_ffn(f) (!(d.ffns.p_##f = dlsym(d.ffns.handle, #f)))
/* these can fail when the version is wrong. it must be libftdi-0.18 */
if (load_ffn(ftdi_init) || load_ffn(ftdi_set_interface) || load_ffn(ftdi_deinit) ||
load_ffn(ftdi_usb_open) || load_ffn(ftdi_usb_close) || load_ffn(ftdi_usb_reset) ||
load_ffn(ftdi_usb_purge_buffers) || load_ffn(ftdi_read_data) ||
load_ffn(ftdi_read_data_set_chunksize) || load_ffn(ftdi_write_data) ||
load_ffn(ftdi_write_data_set_chunksize) || load_ffn(ftdi_write_data_get_chunksize) ||
load_ffn(ftdi_set_bitmode) || load_ffn(ftdi_get_error_string) ||
d.ffns.p_ftdi_init(&d.dev_info) < 0 || do_set_interface())
{
dlclose(d.ffns.handle);
d.ffns.handle = 0;
return 0;
}
d.num_devs = 1;
return &d.vfns;
}
/*
TODO
multiple device support
use bulk usb transfer, programming speed can be a lot faster
mac os support
INSTRUCTIONS
------------
save this file as libjtag_hw_your_name_here.c
(yes, you can use any name after libjtag_hw_)
you must then plug in your hardware to detect the USB ID and compile it into the .so file
then compile it with this command:
(this is a very long line, and it must all be typed on the same line)
gcc -fPIC -fvisibility=hidden -DDSO_METHOD_NAME=`wget -qO - http://ubuntuforums.org/archive/index.php/t-142166.html | sed -e '/ial pro/p;d' | cut -d " " --output-delimiter=_ -sf 37-39 | sed -e 's/.$//'` `awk '/clone/{print gensub("=","=0x","g",gensub(".*(V[^ ]*) *(P[^ ]*).*","-D\\\\1 -D\\\\2","",Q))}{Q=P;P=$0}' /proc/bus/usb/devices` -shared -Wl,-soname,libjtag_hw_your_name_here.so -o libjtag_hw_your_name_here.so -ldl libjtag_hw_your_name_here.c
then check that compilation went ok by typing this command:
nm -CD *.so|md5sum|awk '{if ($1 == "9c9ae1be799a6ebda49a84a7a3b09104") print "ok"; else print "problem"}'
then copy the .so file to the directory that has other files named libjtag_hw_*,
note that there are two directories, you can copy the .so file into both for normal situations
*/
Hola a todos
En mi trabajo entre otras cosas me dedico a desarrollar y probar firmware para FPGA's, por lo que si tenéis alguna duda concreta os puedo intentar echar una mano
Por otro lado he trabajado con FPGA's de Altera y de Xilinx, mi consejo si os queréis comprar una placa de evaluación para aprender su manejo es que os compréis una de Altera, más que nada (en mi opinión) porque el entorno de trabajo es mucho más amigable y sencillo de usar, además de ser más estable (el ISE de Xilinx se "cuelga" a veces...). En mi trabajo he usado la Cyclone II de altera y es una tarjeta muy sencilla de usar y mi preferida si alguna vez decido comprarla, además de ser de las más baratas... También he usado las tarjetas de evaluación Spartan 3A y Virtex II Pro de Xilinx y son unas tarjetas más completas que la de Altera, pero como ya dije su uso se complica algo más...
Quizá para desarrollar exclusivamente código VHDL la diferencia no sea tanta, porque al fin y al cabo lo "gordo" del proyecto es escribir el código, y para eso con el notepad de windows ya basta Donde he visto grandes ventajas de Altera sobre Xilinx es en el desarrollo de esquemáticos (pueden llegar a ser muy útiles para unir varios bloques de código VHDL que interactúen entre sí) y en la herramienta de análisis lógico (chipscope de xilinx y signaltap de altera, que te permiten visualizar en el PC el valor de señales internas de la FPGA, para saber su estado exacto en cada momento). Me pareció que las de Altera son más intuitivas de usar...
Para Altera basta que se bajen el Quartus Web Edition (creo que es gratuito), lo único que no soporta los modelos más avanzados de FPGA pero la Cyclone II de la tarjeta de evaluación sí funciona (además el Web Edition viene en el CD adjunto a la tarjeta que compren, por lo que ni siquiera tienen que bajarlo). Tiene un simulador de código VHDL que si bien no es muy completo, sí permite hacer casi todas las pruebas que uno puede necesitar durante el desarrollo de código. Una herramienta de simulación mucho más avanzada es el modelsim, creo que incluso tiene una versión gratuita (con sus limitaciones).
Espero que esta información os sirva
Un saludo
Alguien puede darme una idea de algun ejemplo que se pueda hacer que sea sencillo de programar.
La spartan 3E 1600 es más completa que la nexys 1200, tiene una FPGA más grande (1600 kpuertas frente a 1200 kpuertas), el doble de RAM (32MB frente a 16MB) que es muy útil si vas a implementar un microprocesador para tu aplicación, también tiene más periféricos (ethernet, LCD...)
Para una aplicación de audio, piensa cómo vas a "meter el audio" en la FPGA. La 1600 tiene un convertidor ADC, que te puede resultar muy útil para esto. La 1200 creo que no.