mpsse.c revision 4dc4629c415e7ca90ff146d7bb75b5646ecd8b17
1771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 29caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *Copyright (C) 2015 The Android Open Source Project 39caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn * 49caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *Licensed under the Apache License, Version 2.0 (the "License"); 59caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *you may not use this file except in compliance with the License. 69caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *You may obtain a copy of the License at 79caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn * 89caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn * http://www.apache.org/licenses/LICENSE-2.0 99caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn * 109caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *Unless required by applicable law or agreed to in writing, software 119caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *distributed under the License is distributed on an "AS IS" BASIS, 129caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *See the License for the specific language governing permissions and 149caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn *limitations under the License. 1526f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * 1626f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * This file was copied from https://github.com/devttys0/libmpsse.git (sha1 1726f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * f1a6744b), and modified to suite the Chromium OS project. 1826f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury * 19771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Main libmpsse source file. 20771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 21771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Craig Heffner 22771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 27 December 2011 23771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 24771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 25771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <stdlib.h> 26771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <string.h> 27771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <stdint.h> 28771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#include <unistd.h> 29771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 3026f26f5ae2c7a76aa199206dece12f65aa67da12Vadim Bendebury#include "trunks/ftdi/support.h" 31771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 32771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* List of known FT2232-based devices */ 33771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct vid_pid supported_devices[] = { 34771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd"}, 35771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd"}, 36771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0x6014, "FT232H Future Technology Devices International, Ltd"}, 37771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 38771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* These devices are based on FT2232 chips, but have not been tested. */ 39771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0x8878, "Bus Blaster v2 (channel A)"}, 40771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0x8879, "Bus Blaster v2 (channel B)"}, 41771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A"}, 42771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0xCFF8, "Amontec JTAGkey"}, 43771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x0403, 0x8A98, "TIAO Multi Protocol Adapter"}, 44771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG"}, 45771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY"}, 46771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 47771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury {0, 0, NULL}}; 48771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 49771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 50771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Opens and initializes the first FTDI device found. 51771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 52771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode - Mode to open the device in. One of enum modes. 53771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq - Clock frequency to use for the specified mode. 54771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - Specifies how data is clocked in/out (MSB, LSB). 55771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 563f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * Returns a pointer to an MPSSE context structure if succeeded, NULL otherwise. 57771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 58b9e482ca1162cccedcc0bbd9bd5ee9073372190dVadim Bendeburystruct mpsse_context* MPSSE(enum modes mode, int freq, int endianess) { 59771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int i = 0; 60771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury struct mpsse_context* mpsse = NULL; 61771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 62771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury for (i = 0; supported_devices[i].vid != 0; i++) { 634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn mpsse = Open(supported_devices[i].vid, supported_devices[i].pid, mode, freq, 644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn endianess, IFACE_A, NULL, NULL); 653f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (mpsse) { 663f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->description = supported_devices[i].description; 673f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury return mpsse; 68771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 69771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 70771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 713f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury return NULL; 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 * 863f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * Returns a pointer to an MPSSE context structure on success. 87771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 88771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct mpsse_context* Open(int vid, 89771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int pid, 90771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury enum modes mode, 91771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int freq, 92771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int endianess, 93771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int interface, 94771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury const char* description, 95771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury const char* serial) { 96771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return OpenIndex(vid, pid, mode, freq, endianess, interface, description, 97771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury serial, 0); 98771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 99771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 100771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 101771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Open device by VID/PID/index 102771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 103771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @vid - Device vendor ID. 104771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pid - Device product ID. 105771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mode - MPSSE mode, one of enum modes. 106771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq - Clock frequency to use for the specified mode. 107771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - Specifies how data is clocked in/out (MSB, LSB). 108771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @interface - FTDI interface to use (IFACE_A - IFACE_D). 109771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @description - Device product description (set to NULL if not needed). 110771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @serial - Device serial number (set to NULL if not needed). 111771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @index - Device index (set to 0 if not needed). 112771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 113771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to an MPSSE context structure. 114771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On success, mpsse->open will be set to 1. 115771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * On failure, mpsse->open will be set to 0. 116771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 117771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburystruct mpsse_context* OpenIndex(int vid, 118771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int pid, 119771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury enum modes mode, 120771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int freq, 121771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int endianess, 122771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int interface, 123771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury const char* description, 124771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury const char* serial, 125771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int index) { 1261ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury int status = 0; 127771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury struct mpsse_context* mpsse = NULL; 128771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 129771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse = malloc(sizeof(struct mpsse_context)); 1303f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (!mpsse) 1313f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury return NULL; 1323f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1333f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury memset(mpsse, 0, sizeof(struct mpsse_context)); 1343f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1353f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Legacy; flushing is no longer needed, so disable it by default. */ 1363f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury FlushAfterRead(mpsse, 0); 137771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1383f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* ftdilib initialization */ 1393f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (ftdi_init(&mpsse->ftdi)) { 1403f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury free(mpsse); 1413f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury return NULL; 1423f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury } 1433f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1443f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Set the FTDI interface */ 1453f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury ftdi_set_interface(&mpsse->ftdi, interface); 1463f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1473f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Open the specified device */ 1483f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (!ftdi_usb_open_desc_index(&mpsse->ftdi, vid, pid, description, serial, 1493f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury index)) { 1503f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->mode = mode; 1513f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->vid = vid; 1523f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->pid = pid; 1533f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->status = STOPPED; 1543f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->endianess = endianess; 1553f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1563f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Set the appropriate transfer size for the requested protocol */ 1573f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (mpsse->mode == I2C) 1583f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->xsize = I2C_TRANSFER_SIZE; 1593f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury else 1603f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse->xsize = SPI_RW_SIZE; 1613f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1623f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury status |= ftdi_usb_reset(&mpsse->ftdi); 1633f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury status |= ftdi_set_latency_timer(&mpsse->ftdi, LATENCY_MS); 1643f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury status |= ftdi_write_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE); 1653f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury status |= ftdi_read_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE); 1663f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury status |= ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET); 1673f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1683f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (status == 0) { 1693f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Set the read and write timeout periods */ 1703f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury set_timeouts(mpsse, USB_TIMEOUT); 1713f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1723f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (mpsse->mode != BITBANG) { 1733f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_MPSSE); 1743f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1753f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (SetClock(mpsse, freq) == MPSSE_OK) { 1763f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (SetMode(mpsse, endianess) == MPSSE_OK) { 1771ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury mpsse->opened = 1; 1783f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1793f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Give the chip a few mS to initialize */ 1803f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury usleep(SETUP_DELAY); 1813f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 1823f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* 1833f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * Not all FTDI chips support all the commands that SetMode may 1843f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * have sent. 1853f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * This clears out any errors from unsupported commands that 1863f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury * might have been sent during set up. 187771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1883f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury ftdi_usb_purge_buffers(&mpsse->ftdi); 189771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 190771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1913f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury } else { 1923f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury /* Skip the setup functions if we're just operating in BITBANG mode 1933f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury */ 1943f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (!ftdi_set_bitmode(&mpsse->ftdi, 0xFF, BITMODE_BITBANG)) 1951ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury mpsse->opened = 1; 196771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 197771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 198771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 199771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 2001ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury if (mpsse && !mpsse->opened) { 2013f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury Close(mpsse); 2023f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury mpsse = NULL; 2033f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury } 2043f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury 205771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return mpsse; 206771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 207771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 208771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 209771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Closes the device, deinitializes libftdi, and frees the MPSSE context 210771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *pointer. 211771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 212771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 213771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 214771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 215771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 216771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid Close(struct mpsse_context* mpsse) { 2173f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury if (!mpsse) 2183f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury return; 219771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 2201ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury if (mpsse->opened) { 2211ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury /* Shut these down only if initialization succeeded before. */ 2221ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_RESET); 2231ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury ftdi_usb_close(&mpsse->ftdi); 2241ea6ecdb07697096d9d3d67f3599e062b01590c2Vadim Bendebury } 2253f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury ftdi_deinit(&mpsse->ftdi); 2263f61c78a14b3d938e177e0cb2225d90114d59bc5Vadim Bendebury free(mpsse); 227771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 228771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 229771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Enables bit-wise data transfers. 230771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Must be called after MPSSE() / Open() / OpenIndex(). 231771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 232771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 233771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 234771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid EnableBitmode(struct mpsse_context* mpsse, int tf) { 235771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 236771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (tf) { 237771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx |= MPSSE_BITMODE; 238771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx |= MPSSE_BITMODE; 239771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx |= MPSSE_BITMODE; 240771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 241771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx &= ~MPSSE_BITMODE; 242771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx &= ~MPSSE_BITMODE; 243771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx &= ~MPSSE_BITMODE; 244771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 245771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 246771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 247771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 248771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 249771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the appropriate transmit and receive commands based on the requested 250771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *mode and byte order. 251771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 252771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 253771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @endianess - MPSSE_MSB or MPSSE_LSB. 254771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 255771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 256771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 257771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 258771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetMode(struct mpsse_context* mpsse, int endianess) { 259771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_OK, i = 0, setup_commands_size = 0; 260c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t buf[CMD_SIZE] = {0}; 261c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t setup_commands[CMD_SIZE * MAX_SETUP_COMMANDS] = {0}; 262771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 263771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Do not call is_valid_context() here, as the FTDI chip may not be completely 264771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * configured when SetMode is called */ 265771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse) { 266771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Read and write commands need to include endianess */ 267771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx = MPSSE_DO_WRITE | endianess; 268771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx = MPSSE_DO_READ | endianess; 269771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx = MPSSE_DO_WRITE | MPSSE_DO_READ | endianess; 270771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 271771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Clock, data out, chip select pins are outputs; all others are inputs. */ 272771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tris = DEFAULT_TRIS; 273771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 274771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Clock and chip select pins idle high; all others are low */ 275771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle = mpsse->pstart = mpsse->pstop = DEFAULT_PORT; 276771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 277771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* During reads and writes the chip select pin is brought low */ 278771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart &= ~CS; 279771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 280771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Disable FTDI internal loopback */ 281771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury SetLoopback(mpsse, 0); 282771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 283771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Send ACKs by default */ 284771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury SetAck(mpsse, ACK); 285771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 286771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Ensure adaptive clock is disabled */ 287771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury setup_commands[setup_commands_size++] = DISABLE_ADAPTIVE_CLOCK; 288771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 289771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury switch (mpsse->mode) { 290771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury case SPI0: 291771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* SPI mode 0 clock idles low */ 292771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle &= ~SK; 293771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart &= ~SK; 294771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop &= ~SK; 295771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* SPI mode 0 propogates data on the falling edge and read data on the 296771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * rising edge of the clock */ 297771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx |= MPSSE_WRITE_NEG; 298771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx &= ~MPSSE_READ_NEG; 299771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx |= MPSSE_WRITE_NEG; 300771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx &= ~MPSSE_READ_NEG; 301771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 302771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury case SPI3: 303771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* SPI mode 3 clock idles high */ 304771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle |= SK; 305771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart |= SK; 306771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Keep the clock low while the CS pin is brought high to ensure we 307771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * don't accidentally clock out an extra bit */ 308771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop &= ~SK; 309771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* SPI mode 3 propogates data on the falling edge and read data on the 310771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * rising edge of the clock */ 311771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx |= MPSSE_WRITE_NEG; 312771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx &= ~MPSSE_READ_NEG; 313771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx |= MPSSE_WRITE_NEG; 314771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx &= ~MPSSE_READ_NEG; 315771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 316771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury case SPI1: 317771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* SPI mode 1 clock idles low */ 318771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle &= ~SK; 319771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Since this mode idles low, the start condition should ensure that the 320771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * clock is low */ 321771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart &= ~SK; 322771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Even though we idle low in this mode, we need to keep the clock line 323771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * high when we set the CS pin high to prevent 324771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * an unintended clock cycle from being sent by the FT2232. This way, 325771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * the clock goes high, but does not go low until 326771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * after the CS pin goes high. 327771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 328771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop |= SK; 329771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Data read on falling clock edge */ 330771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx |= MPSSE_READ_NEG; 331771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx &= ~MPSSE_WRITE_NEG; 332771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx |= MPSSE_READ_NEG; 333771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx &= ~MPSSE_WRITE_NEG; 334771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 335771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury case SPI2: 336771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* SPI 2 clock idles high */ 337771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle |= SK; 338771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart |= SK; 339771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop |= SK; 340771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Data read on falling clock edge */ 341771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx |= MPSSE_READ_NEG; 342771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx &= ~MPSSE_WRITE_NEG; 343771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx |= MPSSE_READ_NEG; 344771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->txrx &= ~MPSSE_WRITE_NEG; 345771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 346771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury case I2C: 347771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* I2C propogates data on the falling clock edge and reads data on the 348771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * falling (or rising) clock edge */ 349771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tx |= MPSSE_WRITE_NEG; 350771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->rx &= ~MPSSE_READ_NEG; 351771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* In I2C, both the clock and the data lines idle high */ 352771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle |= DO | DI; 353771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* I2C start bit == data line goes from high to low while clock line is 354771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * high */ 355771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart &= ~DO & ~DI; 356771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* I2C stop bit == data line goes from low to high while clock line is 357771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * high - set data line low here, so the transition to the idle state 358771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * triggers the stop condition. */ 359771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop &= ~DO & ~DI; 360771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Enable three phase clock to ensure that I2C data is available on both 361771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * the rising and falling clock edges */ 362771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury setup_commands[setup_commands_size++] = ENABLE_3_PHASE_CLOCK; 363771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 364771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury case GPIO: 365771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 366771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury default: 367771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_FAIL; 368771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 369771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 370771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Send any setup commands to the chip */ 371771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_OK && setup_commands_size > 0) { 372771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = raw_write(mpsse, setup_commands, setup_commands_size); 373771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 374771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 375771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_OK) { 376771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Set the idle pin states */ 377771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury set_bits_low(mpsse, mpsse->pidle); 378771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 379771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* All GPIO pins are outputs, set low */ 380771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->trish = 0xFF; 381771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->gpioh = 0x00; 382771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 383771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[i++] = SET_BITS_HIGH; 384771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[i++] = mpsse->gpioh; 385771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[i++] = mpsse->trish; 386771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 387771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = raw_write(mpsse, buf, i); 388771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 389771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 390771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_FAIL; 391771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 392771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 393771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 394771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 395771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 396771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 397771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the appropriate divisor for the desired clock frequency. 398771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 399771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 400771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @freq - Desired clock frequency in hertz. 401771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 402771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 403771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 404771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 405771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetClock(struct mpsse_context* mpsse, uint32_t freq) { 406771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL; 407771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury uint32_t system_clock = 0; 408771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury uint16_t divisor = 0; 409c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t buf[CMD_SIZE] = {0}; 410771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 411771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Do not call is_valid_context() here, as the FTDI chip may not be completely 412771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * configured when SetClock is called */ 413771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse) { 414771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (freq > SIX_MHZ) { 415771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[0] = TCK_X5; 416771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury system_clock = SIXTY_MHZ; 417771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 418771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[0] = TCK_D5; 419771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury system_clock = TWELVE_MHZ; 420771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 421771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 422771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (raw_write(mpsse, buf, 1) == MPSSE_OK) { 423771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (freq <= 0) { 424771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury divisor = 0xFFFF; 425771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 426771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury divisor = freq2div(system_clock, freq); 427771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 428771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 429771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[0] = TCK_DIVISOR; 430771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[1] = (divisor & 0xFF); 431771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[2] = ((divisor >> 8) & 0xFF); 432771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 433771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (raw_write(mpsse, buf, 3) == MPSSE_OK) { 434771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->clock = div2freq(system_clock, divisor); 435771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_OK; 436771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 437771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 438771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 439771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 440771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 441771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 442771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 443771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 444771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Retrieves the last error string from libftdi. 445771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 446771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 447771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 448771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the last error string. 449771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 450771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyconst char* ErrorString(struct mpsse_context* mpsse) { 451771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse != NULL) { 452771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return ftdi_get_error_string(&mpsse->ftdi); 453771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 454771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 455771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return NULL_CONTEXT_ERROR_MSG; 456771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 457771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 458771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 459771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Gets the currently configured clock rate. 460771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 461771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 462771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 463771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the existing clock rate in hertz. 464771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 465771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetClock(struct mpsse_context* mpsse) { 466771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int clock = 0; 467771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 468771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 469771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury clock = mpsse->clock; 470771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 471771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 472771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return clock; 473771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 474771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 475771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 476771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the vendor ID of the FTDI chip. 477771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 478771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 479771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 480771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the integer value of the vendor ID. 481771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 482771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetVid(struct mpsse_context* mpsse) { 483771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int vid = 0; 484771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 485771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 486771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury vid = mpsse->vid; 487771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 488771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 489771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return vid; 490771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 491771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 492771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 493771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the product ID of the FTDI chip. 494771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 495771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 496771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 497771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the integer value of the product ID. 498771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 499771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetPid(struct mpsse_context* mpsse) { 500771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int pid = 0; 501771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 502771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 503771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury pid = mpsse->pid; 504771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 505771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 506771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return pid; 507771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 508771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 509771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 510771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the description of the FTDI chip, if any. 511771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 512771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 513771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 514771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the description of the FTDI chip. 515771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 516771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyconst char* GetDescription(struct mpsse_context* mpsse) { 517771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury char* description = NULL; 518771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 519771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 520771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury description = mpsse->description; 521771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 522771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 523771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return description; 524771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 525771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 526771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 527771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Enable / disable internal loopback. 528771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 529771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 530771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @enable - Zero to disable loopback, 1 to enable loopback. 531771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 532771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 533771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 534771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 535771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetLoopback(struct mpsse_context* mpsse, int enable) { 536c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t buf[1] = {0}; 537771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL; 538771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 539771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 540771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (enable) { 541771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[0] = LOOPBACK_START; 542771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 543771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf[0] = LOOPBACK_END; 544771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 545771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 546771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = raw_write(mpsse, buf, 1); 547771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 548771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 549771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 550771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 551771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 552771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 553771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the idle state of the chip select pin. CS idles high by default. 554771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 555771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 556771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @idle - Set to 1 to idle high, 0 to idle low. 557771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 558771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 559771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 560771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SetCSIdle(struct mpsse_context* mpsse, int idle) { 561771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 562771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (idle > 0) { 563771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Chip select idles high, active low */ 564771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle |= CS; 565771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop |= CS; 566771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart &= ~CS; 567771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 568771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Chip select idles low, active high */ 569771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pidle &= ~CS; 570771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstop &= ~CS; 571771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->pstart |= CS; 572771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 573771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 574771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 575771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return; 576771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 577771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 578771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 579771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Enables or disables flushing of the FTDI chip's RX buffers after each read 580771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury *operation. 581771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Flushing is disable by default. 582771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 583771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 584771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @tf - Set to 1 to enable flushing, or 0 to disable flushing. 585771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 586771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 587771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 588771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid FlushAfterRead(struct mpsse_context* mpsse, int tf) { 589771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->flush_after_read = tf; 590771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return; 591771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 592771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 593771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 594771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data start condition. 595771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 596771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 597771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 598771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 599771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 600771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 601771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Start(struct mpsse_context* mpsse) { 602771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int status = MPSSE_OK; 603771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 604771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 605771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == I2C && mpsse->status == STARTED) { 606771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Set the default pin states while the clock is low since this is an I2C 607771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * repeated start condition */ 608771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury status |= set_bits_low(mpsse, (mpsse->pidle & ~SK)); 609771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 610771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Make sure the pins are in their default idle state */ 611771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury status |= set_bits_low(mpsse, mpsse->pidle); 612771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 613771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 614771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Set the start condition */ 615771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury status |= set_bits_low(mpsse, mpsse->pstart); 616771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 617771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* 618771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Hackish work around to properly support SPI mode 3. 619771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * SPI3 clock idles high, but needs to be set low before sending out 620771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * data to prevent unintenteded clock glitches from the FT2232. 621771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 622771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == SPI3) { 623771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury status |= set_bits_low(mpsse, (mpsse->pstart & ~SK)); 624771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 625771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* 626771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Hackish work around to properly support SPI mode 1. 627771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * SPI1 clock idles low, but needs to be set high before sending out 628771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * data to preven unintended clock glitches from the FT2232. 629771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 630771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury else if (mpsse->mode == SPI1) { 631771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury status |= set_bits_low(mpsse, (mpsse->pstart | SK)); 632771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 633771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 634771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->status = STARTED; 635771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 636771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury status = MPSSE_FAIL; 637771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->status = STOPPED; 638771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 639771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 640771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return status; 641771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 642771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 643771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 644771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Performs a bit-wise write of up to 8 bits at a time. 645771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 646771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 647771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @bits - A byte containing the desired bits to write. 648771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size - The number of bits from the 'bits' byte to write. 649771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 650771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success, MPSSE_FAIL on failure. 651771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 652f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardsonint WriteBits(struct mpsse_context* mpsse, char bits, size_t size) { 653c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t data[8] = {0}; 654f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardson size_t i = 0; 655f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardson int retval = MPSSE_OK; 656771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 657771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (size > sizeof(data)) { 658771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury size = sizeof(data); 659771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 660771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 661771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Convert each bit in bits to an array of bytes */ 662771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury for (i = 0; i < size; i++) { 663771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (bits & (1 << i)) { 664771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Be sure to honor endianess */ 665771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->endianess == LSB) { 666771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury data[i] = '\xFF'; 667771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 668771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury data[size - i - 1] = '\xFF'; 669771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 670771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 671771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 672771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 673771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Enable bit mode before writing, then disable it afterwards. */ 674771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury EnableBitmode(mpsse, 1); 675771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = Write(mpsse, data, size); 676771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury EnableBitmode(mpsse, 0); 677771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 678771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 679771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 680771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 681771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 682771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data out via the selected serial protocol. 683771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 684771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 685771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data - Buffer of data to send. 686771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size - Size of data. 687771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 688771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 689771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 690771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 691f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardsonint Write(struct mpsse_context* mpsse, const void* vdata, int size) { 692f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardson const uint8_t* data = vdata; 693c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t* buf = NULL; 694771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL, buf_size = 0, txsize = 0, n = 0; 695771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 696771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 697771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode) { 698771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury while (n < size) { 699771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury txsize = size - n; 700771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (txsize > mpsse->xsize) { 701771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury txsize = mpsse->xsize; 702771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 703771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 704771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* 705771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * For I2C we need to send each byte individually so that we can 706771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * read back each individual ACK bit, so set the transmit size to 1. 707771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 708771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == I2C) { 709771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury txsize = 1; 710771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 711771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 712c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury buf = build_block_buffer(mpsse, mpsse->tx, data + n, txsize, &buf_size); 713771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (buf) { 714771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = raw_write(mpsse, buf, buf_size); 715771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury n += txsize; 716771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury free(buf); 717771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 718771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_FAIL) { 719771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 720771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 721771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 722771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Read in the ACK bit and store it in mpsse->rack */ 723771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == I2C) { 724c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury raw_read(mpsse, (uint8_t*)&mpsse->rack, 1); 725771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 726771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 727771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 728771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 729771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 730771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 731771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 732771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_OK && n == size) { 733771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_OK; 734771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 735771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 736771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 737771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 738771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 739771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 740771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* Performs a read. For internal use only; see Read() and ReadBits(). */ 741f7e67f3302e19df6c3118d39252b512c09767d79Bill Richardsonstatic uint8_t* InternalRead(struct mpsse_context* mpsse, int size) { 742c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t *data = NULL, *buf = NULL; 743c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t sbuf[SPI_RW_SIZE] = {0}; 744771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int n = 0, rxsize = 0, data_size = 0, retval = 0; 745771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 746771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 747771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode) { 748771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf = malloc(size); 749771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (buf) { 750771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury memset(buf, 0, size); 751771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 752771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury while (n < size) { 753771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury rxsize = size - n; 754771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (rxsize > mpsse->xsize) { 755771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury rxsize = mpsse->xsize; 756771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 757771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 758771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury data = build_block_buffer(mpsse, mpsse->rx, sbuf, rxsize, &data_size); 759771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (data) { 760771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = raw_write(mpsse, data, data_size); 761771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury free(data); 762771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 763771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_OK) { 764771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury n += raw_read(mpsse, buf + n, rxsize); 765771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 766771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 767771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 768771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 769771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 770771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 771771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 772771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 773771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 774771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 775771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 776c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury return buf; 777771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 778771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 779771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 780771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads data over the selected serial protocol. 781771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 782771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 783771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size - Number of bytes to read. 784771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 785771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the read data on success. 786771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns NULL on failure. 787771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 788771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON 789771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyswig_string_data Read(struct mpsse_context* mpsse, int size) 790771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else 791c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendeburyuint8_t* Read(struct mpsse_context* mpsse, int size) 792771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif 793771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury{ 794c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t* buf = NULL; 795771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 796771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf = InternalRead(mpsse, size); 797771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 798771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON 799771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury swig_string_data sdata = {0}; 800771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury sdata.size = size; 801771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury sdata.data = buf; 802771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return sdata; 803771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else 804771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return buf; 805771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif 806771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 807771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 808771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 809771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Performs a bit-wise read of up to 8 bits. 810771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 811771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 812771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size - Number of bits to read. 813771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 814771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns an 8-bit byte containing the read bits. 815771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 816771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburychar ReadBits(struct mpsse_context* mpsse, int size) { 817771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury char bits = 0; 818c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t* rdata = NULL; 819771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 820771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (size > 8) { 821771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury size = 8; 822771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 823771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 824771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury EnableBitmode(mpsse, 1); 825771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury rdata = InternalRead(mpsse, size); 826771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury EnableBitmode(mpsse, 0); 827771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 828771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (rdata) { 829771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* The last byte in rdata will have all the read bits set or unset as 830771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * needed. */ 831771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury bits = rdata[size - 1]; 832771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 833771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->endianess == MSB) { 834771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* 835771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * In MSB mode, bits are sifted in from the left. If less than 8 bits were 836771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * read, we need to shift them left accordingly. 837771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 838771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury bits = bits << (8 - size); 839771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else if (mpsse->endianess == LSB) { 840771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* 841771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * In LSB mode, bits are shifted in from the right. If less than 8 bits 842771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * were 843771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * read, we need to shift them right accordingly. 844771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 845771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury bits = bits >> (8 - size); 846771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 847771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 848771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury free(rdata); 849771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 850771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 851771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return bits; 852771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 853771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 854771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 855771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads and writes data over the selected serial protocol (SPI only). 856771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 857771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 858771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data - Buffer containing bytes to write. 859771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @size - Number of bytes to transfer. 860771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 861771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a pointer to the read data on success. 862771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns NULL on failure. 863771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 864771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON 865771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyswig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size) 866771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else 867c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendeburyuint8_t* Transfer(struct mpsse_context* mpsse, uint8_t* data, int size) 868771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif 869771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury{ 870c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t *txdata = NULL, *buf = NULL; 871771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int n = 0, data_size = 0, rxsize = 0, retval = 0; 872771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 873771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 874771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Make sure we're configured for one of the SPI modes */ 875771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode >= SPI0 && mpsse->mode <= SPI3) { 876771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury buf = malloc(size); 877771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (buf) { 878771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury memset(buf, 0, size); 879771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 880771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury while (n < size) { 881771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* When sending and recieving, FTDI chips don't seem to like large 882771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * data blocks. Limit the size of each block to SPI_TRANSFER_SIZE */ 883771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury rxsize = size - n; 884771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (rxsize > SPI_TRANSFER_SIZE) { 885771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury rxsize = SPI_TRANSFER_SIZE; 886771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 887771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 8884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn txdata = build_block_buffer(mpsse, mpsse->txrx, data + n, rxsize, 8894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn &data_size); 890771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (txdata) { 891771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = raw_write(mpsse, txdata, data_size); 892771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury free(txdata); 893771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 894771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_OK) { 895771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury n += raw_read(mpsse, (buf + n), rxsize); 896771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 897771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 898771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 899771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 900771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury break; 901771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 902771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 903771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 904771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 905771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 906771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 907771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#ifdef SWIGPYTHON 908771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury swig_string_data sdata = {0}; 909771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury sdata.size = n; 910771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury sdata.data = (char*)buf; 911771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return sdata; 912771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#else 913c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury return buf; 914771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury#endif 915771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 916771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 917771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 918771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns the last received ACK bit. 919771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 920771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 921771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 922771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns either an ACK (0) or a NACK (1). 923771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 924771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint GetAck(struct mpsse_context* mpsse) { 925771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int ack = 0; 926771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 927771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 928771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury ack = (mpsse->rack & 0x01); 929771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 930771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 931771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return ack; 932771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 933771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 934771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 935771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the transmitted ACK bit. 936771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 937771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 938771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @ack - 0 to send ACKs, 1 to send NACKs. 939771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 940771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 941771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 942771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SetAck(struct mpsse_context* mpsse, int ack) { 943771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 944771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (ack == NACK) { 945771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tack = 0xFF; 946771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 947771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->tack = 0x00; 948771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 949771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 950771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 951771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return; 952771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 953771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 954771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 955771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Causes libmpsse to send ACKs after each read byte in I2C mode. 956771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 957771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 958771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 959771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 960771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 961771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SendAcks(struct mpsse_context* mpsse) { 962771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return SetAck(mpsse, ACK); 963771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 964771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 965771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 966771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Causes libmpsse to send NACKs after each read byte in I2C mode. 967771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 968771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 969771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 970771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns void. 971771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 972771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyvoid SendNacks(struct mpsse_context* mpsse) { 973771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return SetAck(mpsse, NACK); 974771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 975771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 976771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 977771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Send data stop condition. 978771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 979771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 980771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 981771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 982771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 983771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 984771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Stop(struct mpsse_context* mpsse) { 985771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_OK; 986771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 987771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 988771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* In I2C mode, we need to ensure that the data line goes low while the 989771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * clock line is low to avoid sending an inadvertent start condition */ 990771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == I2C) { 991771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval |= set_bits_low(mpsse, (mpsse->pidle & ~DO & ~SK)); 992771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 993771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 994771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Send the stop condition */ 995771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval |= set_bits_low(mpsse, mpsse->pstop); 996771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 997771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (retval == MPSSE_OK) { 998771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Restore the pins to their idle states */ 999771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval |= set_bits_low(mpsse, mpsse->pidle); 1000771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1001771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1002771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->status = STOPPED; 1003771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } else { 1004771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_FAIL; 1005771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury mpsse->status = STOPPED; 1006771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1007771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1008771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 1009771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1010771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1011771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1012771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the specified pin high. 1013771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1014771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1015771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin - Pin number to set high. 1016771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1017771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 1018771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 1019771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1020771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinHigh(struct mpsse_context* mpsse, int pin) { 1021771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL; 1022771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1023771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 1024771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = gpio_write(mpsse, pin, HIGH); 1025771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1026771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1027771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 1028771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1029771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1030771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1031771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the specified pin low. 1032771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1033771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1034771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin - Pin number to set low. 1035771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1036771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success. 1037771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_FAIL on failure. 1038771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1039771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinLow(struct mpsse_context* mpsse, int pin) { 1040771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL; 1041771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1042771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 1043771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = gpio_write(mpsse, pin, LOW); 1044771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1045771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1046771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 1047771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1048771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1049771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1050771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the input/output direction of all pins. For use in BITBANG mode only. 1051771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1052771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1053771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @direction - Byte indicating input/output direction of each bit. 1 is out. 1054771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1055771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. 1056771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1057771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint SetDirection(struct mpsse_context* mpsse, uint8_t direction) { 1058771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL; 1059771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1060771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 1061771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == BITBANG) { 1062771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (ftdi_set_bitmode(&mpsse->ftdi, direction, BITMODE_BITBANG) == 0) { 1063771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_OK; 1064771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1065771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1066771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1067771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1068771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 1069771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1070771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1071771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1072771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Sets the input/output value of all pins. For use in BITBANG mode only. 1073771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1074771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1075771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @data - Byte indicating bit hi/low value of each bit. 1076771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1077771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. 1078771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1079771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint WritePins(struct mpsse_context* mpsse, uint8_t data) { 1080771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury int retval = MPSSE_FAIL; 1081771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1082771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 1083771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode == BITBANG) { 1084771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (ftdi_write_data(&mpsse->ftdi, &data, 1) == 0) { 1085771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury retval = MPSSE_OK; 1086771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1087771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1088771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1089771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1090771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return retval; 1091771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1092771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1093771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1094771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Reads the state of the chip's pins. For use in BITBANG mode only. 1095771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1096771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1097771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1098771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a byte with the corresponding pin's bits set to 1 or 0. 1099771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1100771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint ReadPins(struct mpsse_context* mpsse) { 1101771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury uint8_t val = 0; 1102771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1103771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (is_valid_context(mpsse)) { 1104c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury ftdi_read_pins((struct ftdi_context*)&mpsse->ftdi, (uint8_t*)&val); 1105771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1106771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1107771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return (int)val; 1108771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1109771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1110771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1111771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Checks if a specific pin is high or low. For use in BITBANG mode only. 1112771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1113771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1114771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @pin - The pin number. 1115771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @state - The state of the pins, as returned by ReadPins. 1116771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * If set to -1, ReadPins will automatically be called. 1117771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1118771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns a 1 if the pin is high, 0 if the pin is low. 1119771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1120771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint PinState(struct mpsse_context* mpsse, int pin, int state) { 1121771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (state == -1) { 1122771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury state = ReadPins(mpsse); 1123771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1124771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1125771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert 1126771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * these defines into an absolute pin number. */ 1127771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury if (mpsse->mode != BITBANG) { 1128771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury pin += NUM_GPIOL_PINS; 1129771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury } 1130771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1131771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return ((state & (1 << pin)) >> pin); 1132771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1133771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1134771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury/* 1135771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Places all I/O pins into a tristate mode. 1136771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1137771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * @mpsse - MPSSE context pointer. 1138771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * 1139771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury * Returns MPSSE_OK on success, MPSSE_FAIL on failure. 1140771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury */ 1141771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendeburyint Tristate(struct mpsse_context* mpsse) { 1142c9aa4123ba0b0e08bec42c3abf48687b51806ba2Vadim Bendebury uint8_t cmd[CMD_SIZE] = {0}; 1143771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1144771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury /* Tristate the all I/O pins (FT232H only) */ 1145771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury cmd[0] = TRISTATE_IO; 1146771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury cmd[1] = 0xFF; 1147771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury cmd[2] = 0xFF; 1148771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury 1149771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury return raw_write(mpsse, cmd, sizeof(cmd)); 1150771df5a65efedd9fb2eb690cfd2e188e3dc3a4ecVadim Bendebury} 1151