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