Reputation: 63
I am using an FT2232H with libftdi1 on Linux 64b.
I am using the INTERFACE_B in MPSSE bit mode, and transferring large buffers (1024B) over SPI (D2XX command 0x11). When I look at the generated signals with a logic analyzer, it seems that the clock frequency is consistent during the transmission of a byte, but there is some kind of "glitch" between two consecutive bytes, as illustrated in the following screenshot (second curve):
Here is the setup code
static void init_ftdi_context(struct ftdi_context *ctx, unsigned long sample_rate)
{
ftdi_init(ctx);
ftdi_set_interface(ctx, INTERFACE_B);
if (ftdi_usb_open(ctx, 0x0403, 0x6010) != 0){
die("Cannot open FTDI USB device");
}
if (ftdi_usb_reset(ctx) != 0){
die("Cannot reset FTDI USB");
}
if (ftdi_usb_purge_buffers(ctx) != 0){
die("Cannot flush FTDI buffers");
}
if (ftdi_set_latency_timer(ctx, 1) < 0){
die("Cannot set latency timer (%s)", ftdi_get_error_string(ctx));
}
if (ftdi_set_bitmode(ctx, 0xff, BITMODE_MPSSE) < 0) {
die("Failed to set BITMODE_MPSSE on iCE FTDI USB device.\n");
}
/* Clock settings:
* FT2232H has a 60MHz clock. The clock can have a 1/5 prescaler, reducing
* the base clock to 12MHz, the clock divider is defined as:
* base_clock
* Freq = -----------
* 2 * (1+div)
*/
unsigned long divider = (FT2232H_CLOCK_FREQ - 2*sample_rate) / (2*sample_rate);
unsigned long true_sample_rate = FT2232H_CLOCK_FREQ / (2 * (1+divider));
if (true_sample_rate != sample_rate){
fprintf(stderr, "WARNING: Sample rate not precise (%luHz instead of %luHz)\n",
true_sample_rate, sample_rate);
}
if (divider > 0xffff){
die("Sample rate too low (divider cannot exceed 65535)");
}
uint8_t divider_lsb = divider & 0xff;
uint8_t divider_msb = (divider >> 8) & 0xff;
const uint8_t clk_cmd[] = {
0x97, // Disable adaptive clock
0x8d, // Disable 3-phase clock
0x85, // Disable loopback
0x8a, // Disable prescaler mode
0x86, divider_lsb, divider_msb
};
if (ftdi_write_data(ctx, clk_cmd, sizeof(clk_cmd)) != sizeof(clk_cmd)){
die("Cannot configure clock");
}
const uint8_t gpio_cmd[] = {0x80, 0x91, 0x93};
if (ftdi_write_data(ctx, gpio_cmd, sizeof(gpio_cmd)) != sizeof(gpio_cmd)){
die("Cannot configure GPIO");
}
usleep(100000);
}
And the sending code:
typedef struct spi_pkt spi_pkt;
struct spi_pkt {
uint8_t marker;
uint8_t len_lsb;
uint8_t len_msb;
uint8_t payload[BUFSIZE];
uint16_t len;
} __attribute__((packed));
static void send_spi_pkt(struct ftdi_context *ctx, spi_pkt *pkt)
{
if (pkt->len < 1){
return;
}
else if (pkt->len > sizeof(pkt->payload)){
die("Cannot send packets longer than %dkiB (got %d bytes)",
(int) sizeof(pkt->payload)/1024, pkt->len);
}
uint16_t len = pkt->len - 1;
pkt->marker = 0x11;
pkt->len_lsb = (len & 0xff);
pkt->len_msb = (len >> 8) & 0x0f;
len = 3 + pkt->len;
int r = ftdi_write_data(ctx, (const uint8_t *) pkt, len);
if (r != len){
die("Send error (attempting to write %d bytes, but wrote %d) !",
len, r);
}
}
Is there an option to specify the delay to apply between two consecutive bytes being transmitted ?
Upvotes: 1
Views: 1521
Reputation: 177755
Make sure you initialize the initial state of the MPSSE port pins (command 0x80). Specifically, for command 0x11 the SPI clock should start low. Use command 0x10 if the SPI clock starts high. You'll see clock glitches if you don't start in the correct state.
Upvotes: 1