mpsse.c revision b9e482ca1162cccedcc0bbd9bd5ee9073372190d
1771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
2771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Main libmpsse source file.
3771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
4771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Craig Heffner
5771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 27 December 2011
6771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
7771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
8771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <stdlib.h>
9771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <string.h>
10771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <stdint.h>
11771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <unistd.h>
12771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
13771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#if LIBFTDI1 == 1
14771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <libftdi1/ftdi.h>
15771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
16771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <ftdi.h>
17771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
18771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
19771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include "mpsse.h"
20771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include "support.h"
21771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include "config.h"
22771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
23771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* List of known FT2232-based devices */
24771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct vid_pid supported_devices[] = {
25771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd"},
26771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd"},
27771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x6014, "FT232H Future Technology Devices International, Ltd"},
28771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
29771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* These devices are based on FT2232 chips, but have not been tested. */
30771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x8878, "Bus Blaster v2 (channel A)"},
31771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x8879, "Bus Blaster v2 (channel B)"},
32771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A"},
33771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0xCFF8, "Amontec JTAGkey"},
34771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x0403, 0x8A98, "TIAO Multi Protocol Adapter"},
35771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG"},
36771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY"},
37771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
38771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    {0, 0, NULL}};
39771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
40771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
41771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Opens and initializes the first FTDI device found.
42771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
43771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode      - Mode to open the device in. One of enum modes.
44771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq      - Clock frequency to use for the specified mode.
45771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - Specifies how data is clocked in/out (MSB, LSB).
46771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
47771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to an MPSSE context structure.
48771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On success, mpsse->open will be set to 1.
49771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On failure, mpsse->open will be set to 0.
50771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
51b9e482ca1162cccedcc0bbd9bd5ee9073372190dVadim Bendeburystruct mpsse_context* MPSSE(enum modes mode, int freq, int endianess) {
52771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int i = 0;
53771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  struct mpsse_context* mpsse = NULL;
54771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
55771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  for (i = 0; supported_devices[i].vid != 0; i++) {
56771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if ((mpsse = Open(supported_devices[i].vid, supported_devices[i].pid, mode,
57b9e482ca1162cccedcc0bbd9bd5ee9073372190dVadim Bendebury                      freq, endianess, IFACE_A, NULL, NULL)) != NULL) {
58771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (mpsse->open) {
59771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->description = supported_devices[i].description;
60771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
61771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
62771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* If there is another device still left to try, free the context pointer
63771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         and try again */
64771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      else if (supported_devices[i + 1].vid != 0) {
65771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        Close(mpsse);
66771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse = NULL;
67771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
68771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
69771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
70771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
71771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return mpsse;
72771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
73771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
74771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
75771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Open device by VID/PID
76771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
77771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @vid         - Device vendor ID.
78771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pid         - Device product ID.
79771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode        - MPSSE mode, one of enum modes.
80771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq        - Clock frequency to use for the specified mode.
81771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess   - Specifies how data is clocked in/out (MSB, LSB).
82771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @interface   - FTDI interface to use (IFACE_A - IFACE_D).
83771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @description - Device product description (set to NULL if not needed).
84771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @serial      - Device serial number (set to NULL if not needed).
85771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
86771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to an MPSSE context structure.
87771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On success, mpsse->open will be set to 1.
88771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On failure, mpsse->open will be set to 0.
89771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
90771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct mpsse_context* Open(int vid,
91771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int pid,
92771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           enum modes mode,
93771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int freq,
94771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int endianess,
95771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           int interface,
96771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           const char* description,
97771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                           const char* serial) {
98771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return OpenIndex(vid, pid, mode, freq, endianess, interface, description,
99771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                   serial, 0);
100771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
101771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
102771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
103771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Open device by VID/PID/index
104771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
105771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @vid         - Device vendor ID.
106771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pid         - Device product ID.
107771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode        - MPSSE mode, one of enum modes.
108771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq        - Clock frequency to use for the specified mode.
109771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess   - Specifies how data is clocked in/out (MSB, LSB).
110771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @interface   - FTDI interface to use (IFACE_A - IFACE_D).
111771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @description - Device product description (set to NULL if not needed).
112771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @serial      - Device serial number (set to NULL if not needed).
113771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @index       - Device index (set to 0 if not needed).
114771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
115771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to an MPSSE context structure.
116771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On success, mpsse->open will be set to 1.
117771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On failure, mpsse->open will be set to 0.
118771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
119771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct mpsse_context* OpenIndex(int vid,
120771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int pid,
121771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                enum modes mode,
122771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int freq,
123771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int endianess,
124771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int interface,
125771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                const char* description,
126771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                const char* serial,
127771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                int index) {
128771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int status = 0;
129771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  struct mpsse_context* mpsse = NULL;
130771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
131771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  mpsse = malloc(sizeof(struct mpsse_context));
132771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse) {
133771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    memset(mpsse, 0, sizeof(struct mpsse_context));
134771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
135771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Legacy; flushing is no longer needed, so disable it by default. */
136771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    FlushAfterRead(mpsse, 0);
137771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
138771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* ftdilib initialization */
139771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (ftdi_init(&mpsse->ftdi) == 0) {
140771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Set the FTDI interface  */
141771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      ftdi_set_interface(&mpsse->ftdi, interface);
142771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
143771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Open the specified device */
144771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (ftdi_usb_open_desc_index(&mpsse->ftdi, vid, pid, description, serial,
145771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                   index) == 0) {
146771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->mode = mode;
147771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->vid = vid;
148771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pid = pid;
149771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->status = STOPPED;
150771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->endianess = endianess;
151771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
152771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Set the appropriate transfer size for the requested protocol */
153771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (mpsse->mode == I2C) {
154771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          mpsse->xsize = I2C_TRANSFER_SIZE;
155771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        } else {
156771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          mpsse->xsize = SPI_RW_SIZE;
157771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
158771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
159771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        status |= ftdi_usb_reset(&mpsse->ftdi);
160771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        status |= ftdi_set_latency_timer(&mpsse->ftdi, LATENCY_MS);
161771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        status |= ftdi_write_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE);
162771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        status |= ftdi_read_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE);
163771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        status |= ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET);
164771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
165771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (status == 0) {
166771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          /* Set the read and write timeout periods */
167771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          set_timeouts(mpsse, USB_TIMEOUT);
168771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
169771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (mpsse->mode != BITBANG) {
170771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_MPSSE);
171771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
172771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            if (SetClock(mpsse, freq) == MPSSE_OK) {
173771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              if (SetMode(mpsse, endianess) == MPSSE_OK) {
174771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                mpsse->open = 1;
175771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
176771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                /* Give the chip a few mS to initialize */
177771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                usleep(SETUP_DELAY);
178771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
179771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                /*
180771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                 * Not all FTDI chips support all the commands that SetMode may
181771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                 * have sent.
182771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                 * This clears out any errors from unsupported commands that
183771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                 * might have been sent during set up.
184771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                 */
185771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                ftdi_usb_purge_buffers(&mpsse->ftdi);
186771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              }
187771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            }
188771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          } else {
189771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            /* Skip the setup functions if we're just operating in BITBANG mode
190771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury             */
191771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            if (ftdi_set_bitmode(&mpsse->ftdi, 0xFF, BITMODE_BITBANG) == 0) {
192771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              mpsse->open = 1;
193771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            }
194771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
195771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
196771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
197771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
198771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
199771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
200771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return mpsse;
201771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
202771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
203771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
204771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Closes the device, deinitializes libftdi, and frees the MPSSE context
205771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *pointer.
206771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
207771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
208771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
209771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
210771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
211771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid Close(struct mpsse_context* mpsse) {
212771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse) {
213771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->open) {
214771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET);
215b9e482ca1162cccedcc0bbd9bd5ee9073372190dVadim Bendebury      ftdi_usb_close(&mpsse->ftdi);
216771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      ftdi_deinit(&mpsse->ftdi);
217771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
218771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
219771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    free(mpsse);
220771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse = NULL;
221771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
222771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
223771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
224771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
225771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
226771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Enables bit-wise data transfers.
227771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Must be called after MPSSE() / Open() / OpenIndex().
228771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
229771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
230771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
231771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid EnableBitmode(struct mpsse_context* mpsse, int tf) {
232771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
233771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (tf) {
234771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tx |= MPSSE_BITMODE;
235771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->rx |= MPSSE_BITMODE;
236771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->txrx |= MPSSE_BITMODE;
237771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
238771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tx &= ~MPSSE_BITMODE;
239771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->rx &= ~MPSSE_BITMODE;
240771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->txrx &= ~MPSSE_BITMODE;
241771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
242771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
243771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
244771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
245771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
246771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the appropriate transmit and receive commands based on the requested
247771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *mode and byte order.
248771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
249771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse     - MPSSE context pointer.
250771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - MPSSE_MSB or MPSSE_LSB.
251771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
252771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
253771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
254771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
255771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetMode(struct mpsse_context* mpsse, int endianess) {
256771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_OK, i = 0, setup_commands_size = 0;
257771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char buf[CMD_SIZE] = {0};
258771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char setup_commands[CMD_SIZE * MAX_SETUP_COMMANDS] = {0};
259771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
260771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Do not call is_valid_context() here, as the FTDI chip may not be completely
261771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury   * configured when SetMode is called */
262771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse) {
263771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Read and write commands need to include endianess */
264771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->tx = MPSSE_DO_WRITE | endianess;
265771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->rx = MPSSE_DO_READ | endianess;
266771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->txrx = MPSSE_DO_WRITE | MPSSE_DO_READ | endianess;
267771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
268771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Clock, data out, chip select pins are outputs; all others are inputs. */
269771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->tris = DEFAULT_TRIS;
270771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
271771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Clock and chip select pins idle high; all others are low */
272771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->pidle = mpsse->pstart = mpsse->pstop = DEFAULT_PORT;
273771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
274771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* During reads and writes the chip select pin is brought low */
275771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->pstart &= ~CS;
276771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
277771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Disable FTDI internal loopback */
278771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    SetLoopback(mpsse, 0);
279771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
280771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Send ACKs by default */
281771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    SetAck(mpsse, ACK);
282771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
283771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Ensure adaptive clock is disabled */
284771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    setup_commands[setup_commands_size++] = DISABLE_ADAPTIVE_CLOCK;
285771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
286771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    switch (mpsse->mode) {
287771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI0:
288771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 0 clock idles low */
289771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle &= ~SK;
290771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart &= ~SK;
291771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop &= ~SK;
292771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 0 propogates data on the falling edge and read data on the
293771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * rising edge of the clock */
294771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx |= MPSSE_WRITE_NEG;
295771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx &= ~MPSSE_READ_NEG;
296771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_WRITE_NEG;
297771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_READ_NEG;
298771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
299771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI3:
300771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 3 clock idles high */
301771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle |= SK;
302771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart |= SK;
303771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Keep the clock low while the CS pin is brought high to ensure we
304771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * don't accidentally clock out an extra bit */
305771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop &= ~SK;
306771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 3 propogates data on the falling edge and read data on the
307771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * rising edge of the clock */
308771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx |= MPSSE_WRITE_NEG;
309771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx &= ~MPSSE_READ_NEG;
310771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_WRITE_NEG;
311771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_READ_NEG;
312771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
313771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI1:
314771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI mode 1 clock idles low */
315771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle &= ~SK;
316771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Since this mode idles low, the start condition should ensure that the
317771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * clock is low */
318771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart &= ~SK;
319771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Even though we idle low in this mode, we need to keep the clock line
320771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * high when we set the CS pin high to prevent
321771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * an unintended clock cycle from being sent by the FT2232. This way,
322771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * the clock goes high, but does not go low until
323771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * after the CS pin goes high.
324771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         */
325771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop |= SK;
326771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Data read on falling clock edge */
327771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx |= MPSSE_READ_NEG;
328771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx &= ~MPSSE_WRITE_NEG;
329771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_READ_NEG;
330771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_WRITE_NEG;
331771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
332771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case SPI2:
333771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* SPI 2 clock idles high */
334771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle |= SK;
335771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart |= SK;
336771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop |= SK;
337771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Data read on falling clock edge */
338771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx |= MPSSE_READ_NEG;
339771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx &= ~MPSSE_WRITE_NEG;
340771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx |= MPSSE_READ_NEG;
341771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->txrx &= ~MPSSE_WRITE_NEG;
342771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
343771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case I2C:
344771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* I2C propogates data on the falling clock edge and reads data on the
345771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * falling (or rising) clock edge */
346771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->tx |= MPSSE_WRITE_NEG;
347771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->rx &= ~MPSSE_READ_NEG;
348771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* In I2C, both the clock and the data lines idle high */
349771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pidle |= DO | DI;
350771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* I2C start bit == data line goes from high to low while clock line is
351771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * high */
352771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstart &= ~DO & ~DI;
353771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* I2C stop bit == data line goes from low to high while clock line is
354771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * high - set data line low here, so the transition to the idle state
355771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * triggers the stop condition. */
356771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->pstop &= ~DO & ~DI;
357771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /* Enable three phase clock to ensure that I2C data is available on both
358771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * the rising and falling clock edges */
359771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        setup_commands[setup_commands_size++] = ENABLE_3_PHASE_CLOCK;
360771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
361771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      case GPIO:
362771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        break;
363771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      default:
364771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_FAIL;
365771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
366771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
367771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Send any setup commands to the chip */
368771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK && setup_commands_size > 0) {
369771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval = raw_write(mpsse, setup_commands, setup_commands_size);
370771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
371771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
372771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK) {
373771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Set the idle pin states */
374771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      set_bits_low(mpsse, mpsse->pidle);
375771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
376771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* All GPIO pins are outputs, set low */
377771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->trish = 0xFF;
378771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->gpioh = 0x00;
379771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
380771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[i++] = SET_BITS_HIGH;
381771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[i++] = mpsse->gpioh;
382771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[i++] = mpsse->trish;
383771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
384771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval = raw_write(mpsse, buf, i);
385771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
386771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  } else {
387771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = MPSSE_FAIL;
388771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
389771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
390771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
391771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
392771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
393771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
394771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the appropriate divisor for the desired clock frequency.
395771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
396771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
397771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq  - Desired clock frequency in hertz.
398771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
399771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
400771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
401771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
402771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetClock(struct mpsse_context* mpsse, uint32_t freq) {
403771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
404771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  uint32_t system_clock = 0;
405771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  uint16_t divisor = 0;
406771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char buf[CMD_SIZE] = {0};
407771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
408771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Do not call is_valid_context() here, as the FTDI chip may not be completely
409771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury   * configured when SetClock is called */
410771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse) {
411771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (freq > SIX_MHZ) {
412771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = TCK_X5;
413771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      system_clock = SIXTY_MHZ;
414771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
415771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = TCK_D5;
416771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      system_clock = TWELVE_MHZ;
417771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
418771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
419771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (raw_write(mpsse, buf, 1) == MPSSE_OK) {
420771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (freq <= 0) {
421771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        divisor = 0xFFFF;
422771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      } else {
423771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        divisor = freq2div(system_clock, freq);
424771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
425771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
426771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = TCK_DIVISOR;
427771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[1] = (divisor & 0xFF);
428771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[2] = ((divisor >> 8) & 0xFF);
429771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
430771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (raw_write(mpsse, buf, 3) == MPSSE_OK) {
431771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        mpsse->clock = div2freq(system_clock, divisor);
432771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_OK;
433771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
434771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
435771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
436771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
437771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
438771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
439771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
440771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
441771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Retrieves the last error string from libftdi.
442771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
443771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
444771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
445771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the last error string.
446771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
447771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyconst char* ErrorString(struct mpsse_context* mpsse) {
448771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse != NULL) {
449771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    return ftdi_get_error_string(&mpsse->ftdi);
450771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
451771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
452771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return NULL_CONTEXT_ERROR_MSG;
453771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
454771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
455771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
456771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Gets the currently configured clock rate.
457771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
458771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
459771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
460771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the existing clock rate in hertz.
461771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
462771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetClock(struct mpsse_context* mpsse) {
463771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int clock = 0;
464771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
465771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
466771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    clock = mpsse->clock;
467771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
468771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
469771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return clock;
470771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
471771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
472771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
473771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the vendor ID of the FTDI chip.
474771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
475771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
476771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
477771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the integer value of the vendor ID.
478771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
479771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetVid(struct mpsse_context* mpsse) {
480771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int vid = 0;
481771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
482771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
483771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    vid = mpsse->vid;
484771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
485771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
486771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return vid;
487771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
488771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
489771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
490771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the product ID of the FTDI chip.
491771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
492771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
493771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
494771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the integer value of the product ID.
495771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
496771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetPid(struct mpsse_context* mpsse) {
497771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int pid = 0;
498771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
499771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
500771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    pid = mpsse->pid;
501771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
502771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
503771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return pid;
504771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
505771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
506771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
507771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the description of the FTDI chip, if any.
508771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
509771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
510771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
511771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the description of the FTDI chip.
512771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
513771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyconst char* GetDescription(struct mpsse_context* mpsse) {
514771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char* description = NULL;
515771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
516771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
517771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    description = mpsse->description;
518771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
519771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
520771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return description;
521771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
522771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
523771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
524771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Enable / disable internal loopback.
525771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
526771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse  - MPSSE context pointer.
527771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @enable - Zero to disable loopback, 1 to enable loopback.
528771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
529771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
530771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
531771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
532771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetLoopback(struct mpsse_context* mpsse, int enable) {
533771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char buf[1] = {0};
534771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
535771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
536771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
537771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (enable) {
538771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = LOOPBACK_START;
539771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
540771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf[0] = LOOPBACK_END;
541771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
542771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
543771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = raw_write(mpsse, buf, 1);
544771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
545771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
546771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
547771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
548771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
549771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
550771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the idle state of the chip select pin. CS idles high by default.
551771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
552771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
553771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @idle  - Set to 1 to idle high, 0 to idle low.
554771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
555771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
556771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
557771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SetCSIdle(struct mpsse_context* mpsse, int idle) {
558771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
559771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (idle > 0) {
560771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Chip select idles high, active low */
561771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pidle |= CS;
562771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstop |= CS;
563771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstart &= ~CS;
564771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
565771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Chip select idles low, active high */
566771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pidle &= ~CS;
567771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstop &= ~CS;
568771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->pstart |= CS;
569771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
570771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
571771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
572771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
573771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
574771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
575771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
576771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Enables or disables flushing of the FTDI chip's RX buffers after each read
577771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *operation.
578771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Flushing is disable by default.
579771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
580771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
581771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @tf    - Set to 1 to enable flushing, or 0 to disable flushing.
582771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
583771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
584771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
585771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid FlushAfterRead(struct mpsse_context* mpsse, int tf) {
586771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  mpsse->flush_after_read = tf;
587771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
588771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
589771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
590771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
591771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data start condition.
592771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
593771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
594771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
595771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
596771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
597771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
598771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Start(struct mpsse_context* mpsse) {
599771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int status = MPSSE_OK;
600771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
601771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
602771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == I2C && mpsse->status == STARTED) {
603771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Set the default pin states while the clock is low since this is an I2C
604771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * repeated start condition */
605771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, (mpsse->pidle & ~SK));
606771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
607771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Make sure the pins are in their default idle state */
608771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, mpsse->pidle);
609771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
610771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
611771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Set the start condition */
612771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    status |= set_bits_low(mpsse, mpsse->pstart);
613771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
614771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /*
615771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * Hackish work around to properly support SPI mode 3.
616771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * SPI3 clock idles high, but needs to be set low before sending out
617771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * data to prevent unintenteded clock glitches from the FT2232.
618771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     */
619771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == SPI3) {
620771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, (mpsse->pstart & ~SK));
621771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
622771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /*
623771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * Hackish work around to properly support SPI mode 1.
624771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * SPI1 clock idles low, but needs to be set high before sending out
625771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * data to preven unintended clock glitches from the FT2232.
626771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     */
627771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    else if (mpsse->mode == SPI1) {
628771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      status |= set_bits_low(mpsse, (mpsse->pstart | SK));
629771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
630771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
631771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STARTED;
632771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  } else {
633771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    status = MPSSE_FAIL;
634771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STOPPED;
635771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
636771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
637771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return status;
638771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
639771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
640771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
641771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Performs a bit-wise write of up to 8 bits at a time.
642771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
643771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
644771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @bits  - A byte containing the desired bits to write.
645771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - The number of bits from the 'bits' byte to write.
646771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
647771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success, MPSSE_FAIL on failure.
648771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
649771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint WriteBits(struct mpsse_context* mpsse, char bits, int size) {
650771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char data[8] = {0};
651771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int i = 0, retval = MPSSE_OK;
652771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
653771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (size > sizeof(data)) {
654771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    size = sizeof(data);
655771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
656771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
657771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Convert each bit in bits to an array of bytes */
658771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  for (i = 0; i < size; i++) {
659771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (bits & (1 << i)) {
660771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Be sure to honor endianess */
661771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (mpsse->endianess == LSB) {
662771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        data[i] = '\xFF';
663771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      } else {
664771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        data[size - i - 1] = '\xFF';
665771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
666771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
667771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
668771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
669771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Enable bit mode before writing, then disable it afterwards. */
670771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 1);
671771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  retval = Write(mpsse, data, size);
672771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 0);
673771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
674771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
675771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
676771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
677771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
678771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data out via the selected serial protocol.
679771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
680771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
681771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data  - Buffer of data to send.
682771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Size of data.
683771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
684771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
685771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
686771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
687771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Write(struct mpsse_context* mpsse, char* data, int size) {
688771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char* buf = NULL;
689771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL, buf_size = 0, txsize = 0, n = 0;
690771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
691771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
692771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode) {
693771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      while (n < size) {
694771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        txsize = size - n;
695771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (txsize > mpsse->xsize) {
696771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          txsize = mpsse->xsize;
697771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
698771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
699771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        /*
700771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * For I2C we need to send each byte individually so that we can
701771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         * read back each individual ACK bit, so set the transmit size to 1.
702771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury         */
703771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (mpsse->mode == I2C) {
704771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          txsize = 1;
705771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
706771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
707771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        buf = build_block_buffer(mpsse, mpsse->tx, (unsigned char*)(data + n),
708771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                 txsize, &buf_size);
709771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        if (buf) {
710771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          retval = raw_write(mpsse, buf, buf_size);
711771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          n += txsize;
712771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          free(buf);
713771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
714771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (retval == MPSSE_FAIL) {
715771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            break;
716771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
717771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
718771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          /* Read in the ACK bit and store it in mpsse->rack */
719771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (mpsse->mode == I2C) {
720771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            raw_read(mpsse, (unsigned char*)&mpsse->rack, 1);
721771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
722771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        } else {
723771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          break;
724771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
725771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
726771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
727771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
728771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK && n == size) {
729771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval = MPSSE_OK;
730771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
731771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
732771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
733771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
734771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
735771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
736771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Performs a read. For internal use only; see Read() and ReadBits(). */
737771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar* InternalRead(struct mpsse_context* mpsse, int size) {
738771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char *data = NULL, *buf = NULL;
739771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char sbuf[SPI_RW_SIZE] = {0};
740771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int n = 0, rxsize = 0, data_size = 0, retval = 0;
741771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
742771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
743771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode) {
744771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf = malloc(size);
745771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (buf) {
746771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        memset(buf, 0, size);
747771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
748771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        while (n < size) {
749771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          rxsize = size - n;
750771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (rxsize > mpsse->xsize) {
751771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            rxsize = mpsse->xsize;
752771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
753771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
754771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          data = build_block_buffer(mpsse, mpsse->rx, sbuf, rxsize, &data_size);
755771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (data) {
756771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            retval = raw_write(mpsse, data, data_size);
757771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            free(data);
758771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
759771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            if (retval == MPSSE_OK) {
760771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              n += raw_read(mpsse, buf + n, rxsize);
761771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            } else {
762771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              break;
763771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            }
764771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          } else {
765771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            break;
766771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
767771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
768771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
769771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
770771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
771771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
772771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return (char*)buf;
773771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
774771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
775771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
776771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads data over the selected serial protocol.
777771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
778771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
779771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Number of bytes to read.
780771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
781771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the read data on success.
782771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns NULL on failure.
783771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
784771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
785771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyswig_string_data Read(struct mpsse_context* mpsse, int size)
786771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
787771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar* Read(struct mpsse_context* mpsse, int size)
788771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
789771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury{
790771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char* buf = NULL;
791771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
792771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  buf = InternalRead(mpsse, size);
793771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
794771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
795771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  swig_string_data sdata = {0};
796771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.size = size;
797771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.data = buf;
798771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return sdata;
799771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
800771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return buf;
801771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
802771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
803771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
804771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
805771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Performs a bit-wise read of up to 8 bits.
806771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
807771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
808771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Number of bits to read.
809771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
810771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns an 8-bit byte containing the read bits.
811771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
812771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar ReadBits(struct mpsse_context* mpsse, int size) {
813771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char bits = 0;
814771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char* rdata = NULL;
815771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
816771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (size > 8) {
817771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    size = 8;
818771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
819771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
820771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 1);
821771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  rdata = InternalRead(mpsse, size);
822771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  EnableBitmode(mpsse, 0);
823771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
824771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (rdata) {
825771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* The last byte in rdata will have all the read bits set or unset as
826771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * needed. */
827771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    bits = rdata[size - 1];
828771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
829771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->endianess == MSB) {
830771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /*
831771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * In MSB mode, bits are sifted in from the left. If less than 8 bits were
832771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * read, we need to shift them left accordingly.
833771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       */
834771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      bits = bits << (8 - size);
835771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else if (mpsse->endianess == LSB) {
836771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /*
837771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * In LSB mode, bits are shifted in from the right. If less than 8 bits
838771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * were
839771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       * read, we need to shift them right accordingly.
840771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury       */
841771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      bits = bits >> (8 - size);
842771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
843771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
844771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    free(rdata);
845771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
846771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
847771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return bits;
848771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
849771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
850771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
851771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads and writes data over the selected serial protocol (SPI only).
852771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
853771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
854771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data  - Buffer containing bytes to write.
855771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size  - Number of bytes to transfer.
856771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
857771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the read data on success.
858771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns NULL on failure.
859771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
860771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
861771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyswig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size)
862771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
863771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar* Transfer(struct mpsse_context* mpsse, char* data, int size)
864771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
865771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury{
866771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char *txdata = NULL, *buf = NULL;
867771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int n = 0, data_size = 0, rxsize = 0, retval = 0;
868771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
869771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
870771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Make sure we're configured for one of the SPI modes */
871771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode >= SPI0 && mpsse->mode <= SPI3) {
872771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      buf = malloc(size);
873771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (buf) {
874771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        memset(buf, 0, size);
875771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
876771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        while (n < size) {
877771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          /* When sending and recieving, FTDI chips don't seem to like large
878771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury           * data blocks. Limit the size of each block to SPI_TRANSFER_SIZE */
879771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          rxsize = size - n;
880771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (rxsize > SPI_TRANSFER_SIZE) {
881771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            rxsize = SPI_TRANSFER_SIZE;
882771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
883771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
884771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          txdata =
885771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              build_block_buffer(mpsse, mpsse->txrx, (unsigned char*)(data + n),
886771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury                                 rxsize, &data_size);
887771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          if (txdata) {
888771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            retval = raw_write(mpsse, txdata, data_size);
889771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            free(txdata);
890771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
891771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            if (retval == MPSSE_OK) {
892771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              n += raw_read(mpsse, (buf + n), rxsize);
893771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            } else {
894771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury              break;
895771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            }
896771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          } else {
897771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury            break;
898771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury          }
899771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        }
900771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
901771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
902771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
903771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
904771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON
905771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  swig_string_data sdata = {0};
906771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.size = n;
907771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  sdata.data = (char*)buf;
908771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return sdata;
909771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else
910771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return (char*)buf;
911771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif
912771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
913771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
914771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
915771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the last received ACK bit.
916771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
917771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
918771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
919771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns either an ACK (0) or a NACK (1).
920771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
921771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetAck(struct mpsse_context* mpsse) {
922771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int ack = 0;
923771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
924771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
925771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    ack = (mpsse->rack & 0x01);
926771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
927771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
928771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return ack;
929771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
930771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
931771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
932771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the transmitted ACK bit.
933771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
934771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
935771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @ack   - 0 to send ACKs, 1 to send NACKs.
936771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
937771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
938771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
939771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SetAck(struct mpsse_context* mpsse, int ack) {
940771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
941771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (ack == NACK) {
942771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tack = 0xFF;
943771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    } else {
944771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      mpsse->tack = 0x00;
945771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
946771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
947771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
948771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return;
949771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
950771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
951771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
952771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Causes libmpsse to send ACKs after each read byte in I2C mode.
953771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
954771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
955771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
956771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
957771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
958771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SendAcks(struct mpsse_context* mpsse) {
959771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return SetAck(mpsse, ACK);
960771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
961771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
962771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
963771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Causes libmpsse to send NACKs after each read byte in I2C mode.
964771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
965771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
966771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
967771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void.
968771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
969771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SendNacks(struct mpsse_context* mpsse) {
970771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return SetAck(mpsse, NACK);
971771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
972771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
973771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
974771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data stop condition.
975771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
976771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
977771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
978771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
979771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
980771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
981771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Stop(struct mpsse_context* mpsse) {
982771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_OK;
983771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
984771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
985771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* In I2C mode, we need to ensure that the data line goes low while the
986771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury     * clock line is low to avoid sending an inadvertent start condition */
987771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == I2C) {
988771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval |= set_bits_low(mpsse, (mpsse->pidle & ~DO & ~SK));
989771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
990771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
991771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    /* Send the stop condition */
992771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval |= set_bits_low(mpsse, mpsse->pstop);
993771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
994771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (retval == MPSSE_OK) {
995771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      /* Restore the pins to their idle states */
996771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      retval |= set_bits_low(mpsse, mpsse->pidle);
997771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
998771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
999771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STOPPED;
1000771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  } else {
1001771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = MPSSE_FAIL;
1002771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    mpsse->status = STOPPED;
1003771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1004771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1005771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1006771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1007771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1008771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1009771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the specified pin high.
1010771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1011771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1012771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin   - Pin number to set high.
1013771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1014771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
1015771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
1016771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1017771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinHigh(struct mpsse_context* mpsse, int pin) {
1018771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1019771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1020771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1021771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = gpio_write(mpsse, pin, HIGH);
1022771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1023771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1024771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1025771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1026771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1027771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1028771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the specified pin low.
1029771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1030771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1031771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin   - Pin number to set low.
1032771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1033771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success.
1034771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure.
1035771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1036771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinLow(struct mpsse_context* mpsse, int pin) {
1037771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1038771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1039771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1040771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    retval = gpio_write(mpsse, pin, LOW);
1041771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1042771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1043771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1044771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1045771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1046771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1047771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the input/output direction of all pins. For use in BITBANG mode only.
1048771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1049771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse     - MPSSE context pointer.
1050771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @direction - Byte indicating input/output direction of each bit.  1 is out.
1051771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1052771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise.
1053771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1054771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetDirection(struct mpsse_context* mpsse, uint8_t direction) {
1055771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1056771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1057771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1058771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == BITBANG) {
1059771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (ftdi_set_bitmode(&mpsse->ftdi, direction, BITMODE_BITBANG) == 0) {
1060771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_OK;
1061771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
1062771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
1063771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1064771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1065771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1066771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1067771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1068771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1069771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the input/output value of all pins. For use in BITBANG mode only.
1070771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1071771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1072771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data  - Byte indicating bit hi/low value of each bit.
1073771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1074771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise.
1075771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1076771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint WritePins(struct mpsse_context* mpsse, uint8_t data) {
1077771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int retval = MPSSE_FAIL;
1078771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1079771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1080771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (mpsse->mode == BITBANG) {
1081771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      if (ftdi_write_data(&mpsse->ftdi, &data, 1) == 0) {
1082771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury        retval = MPSSE_OK;
1083771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      }
1084771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
1085771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1086771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1087771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return retval;
1088771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1089771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1090771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1091771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads the state of the chip's pins. For use in BITBANG mode only.
1092771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1093771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1094771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1095771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a byte with the corresponding pin's bits set to 1 or 0.
1096771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1097771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint ReadPins(struct mpsse_context* mpsse) {
1098771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  uint8_t val = 0;
1099771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1100771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (is_valid_context(mpsse)) {
1101771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    ftdi_read_pins((struct ftdi_context*)&mpsse->ftdi, (unsigned char*)&val);
1102771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1103771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1104771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return (int)val;
1105771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1106771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1107771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1108771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Checks if a specific pin is high or low. For use in BITBANG mode only.
1109771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1110771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1111771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin   - The pin number.
1112771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @state - The state of the pins, as returned by ReadPins.
1113771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *          If set to -1, ReadPins will automatically be called.
1114771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1115771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a 1 if the pin is high, 0 if the pin is low.
1116771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1117771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinState(struct mpsse_context* mpsse, int pin, int state) {
1118771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (state == -1) {
1119771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    state = ReadPins(mpsse);
1120771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1121771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1122771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert
1123771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury   * these defines into an absolute pin number. */
1124771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (mpsse->mode != BITBANG) {
1125771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    pin += NUM_GPIOL_PINS;
1126771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1127771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1128771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return ((state & (1 << pin)) >> pin);
1129771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1130771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1131771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1132771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Places all I/O pins into a tristate mode.
1133771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1134771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer.
1135771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *
1136771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success, MPSSE_FAIL on failure.
1137771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1138771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Tristate(struct mpsse_context* mpsse) {
1139771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  unsigned char cmd[CMD_SIZE] = {0};
1140771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1141771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  /* Tristate the all I/O pins (FT232H only) */
1142771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  cmd[0] = TRISTATE_IO;
1143771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  cmd[1] = 0xFF;
1144771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  cmd[2] = 0xFF;
1145771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1146771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return raw_write(mpsse, cmd, sizeof(cmd));
1147771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1148771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1149771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/*
1150771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the libmpsse version number.
1151771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * High nibble is major version, low nibble is minor version.
1152771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */
1153771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar Version(void) {
1154771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  int major = 0, minor = 0;
1155771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  char version = 0, *version_string = NULL, *decimal_ptr = NULL;
1156771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1157771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  version_string = strdup(PACKAGE_VERSION);
1158771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  if (version_string) {
1159771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    decimal_ptr = strchr(version_string, '.');
1160771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    if (decimal_ptr && strlen(decimal_ptr) > 1) {
1161771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      memset(decimal_ptr, 0, 1);
1162771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury      minor = atoi(decimal_ptr + 1);
1163771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    }
1164771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1165771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    major = atoi(version_string);
1166771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1167771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury    free(version_string);
1168771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  }
1169771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1170771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  version = (char)((major << 4) + (minor & 0x0F));
1171771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury
1172771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury  return version;
1173771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury}
1174