diff --git a/src/Makefile.in b/src/Makefile.in index 25e8434..a2e2c49 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -29,7 +29,7 @@ mpsse.o: support.o $(CC) $(CFLAGS) $(LDFLAGS) -DLIBFTDI1=$(LIBFTDI1) -c mpsse.c fast.o: support.o - $(CC) $(CFLAGS) $(LDFLAGS) -c fast.c + $(CC) $(CFLAGS) $(LDFLAGS) -DLIBFTDI1=$(LIBFTDI1) -c fast.c support.o: $(CC) $(CFLAGS) $(LDFLAGS) -DLIBFTDI1=$(LIBFTDI1) -c support.c diff --git a/src/examples/Makefile b/src/examples/Makefile index 1c03853..5f9e38c 100644 --- a/src/examples/Makefile +++ b/src/examples/Makefile @@ -1,24 +1,25 @@ -LDFLAGS=-lmpsse +LDFLAGS=-lmpsse -lftdi1 +LIBFTDI1=1 all: spiflash spiflashfast i2ceeprom ds1305 gpio bitbang spiflash: - $(CC) $(CFLAGS) spiflash.c -o spiflash $(LDFLAGS) + $(CC) $(CFLAGS) -DLIBFTDI1=$(LIBFTDI1) spiflash.c -o spiflash $(LDFLAGS) spiflashfast: - $(CC) $(CFLAGS) spiflashfast.c -o spiflashfast $(LDFLAGS) + $(CC) $(CFLAGS) -DLIBFTDI1=$(LIBFTDI1) spiflashfast.c -o spiflashfast $(LDFLAGS) i2ceeprom: - $(CC) $(CFLAGS) i2ceeprom.c -o i2ceeprom $(LDFLAGS) + $(CC) $(CFLAGS) -DLIBFTDI1=$(LIBFTDI1) i2ceeprom.c -o i2ceeprom $(LDFLAGS) ds1305: - $(CC) $(CFLAGS) ds1305.c -o ds1305 $(LDFLAGS) + $(CC) $(CFLAGS) -DLIBFTDI1=$(LIBFTDI1) ds1305.c -o ds1305 $(LDFLAGS) gpio: - $(CC) $(CFLAGS) gpio.c -o gpio $(LDFLAGS) + $(CC) $(CFLAGS) -DLIBFTDI1=$(LIBFTDI1) gpio.c -o gpio $(LDFLAGS) bitbang: - $(CC) $(CFLAGS) bitbang.c -o bitbang $(LDFLAGS) + $(CC) $(CFLAGS) -DLIBFTDI1=$(LIBFTDI1) bitbang.c -o bitbang $(LDFLAGS) clean: rm -f *.dSYM diff --git a/src/examples/gpio.py b/src/examples/gpio.py index 4a6deb1..74d120a 100755 --- a/src/examples/gpio.py +++ b/src/examples/gpio.py @@ -4,17 +4,24 @@ from time import sleep # Open mpsse in GPIO mode -io = MPSSE(GPIO) +io = MPSSE() +io.Open(0x403,0x6010, GPIO, interface=IFACE_B) + +pin = GPIOH7 # Toggle the first GPIO pin on/off 10 times for i in range(0, 10): + print "set direction BCBUS7,6 output, other input", io.SetDirectionHigh(0xC0) + print "set direction BDBUS7,6 output, other input", io.SetDirection(0xC0) + io.PinHigh(pin) + print "GPIO State:", io.PinState(pin) + sleep(0.2) - io.PinHigh(GPIOL0) - print "GPIOL0 State:", io.PinState(GPIOL0) - sleep(1) + io.PinLow(pin) + print "GPIO State:", io.PinState(pin) + sleep(0.2) - io.PinLow(GPIOL0) - print "GPIOL0 State:", io.PinState(GPIOL0) - sleep(1) +print bin(io.ReadPins()) +print bin(io.ReadPinsHigh()) io.Close() diff --git a/src/fast.c b/src/fast.c index 8cf66b0..e9a00b0 100644 --- a/src/fast.c +++ b/src/fast.c @@ -64,9 +64,9 @@ int FastWrite(struct mpsse_context *mpsse, char *data, int size) { txsize = mpsse->xsize; } - + if(fast_build_block_buffer(mpsse, mpsse->tx, (unsigned char *) (data + n), txsize, &buf_size) == MPSSE_OK) - { + { if(raw_write(mpsse, fast_rw_buf, buf_size) == MPSSE_OK) { n += txsize; @@ -90,7 +90,7 @@ int FastWrite(struct mpsse_context *mpsse, char *data, int size) } } } - + return MPSSE_FAIL; } @@ -144,11 +144,11 @@ int FastRead(struct mpsse_context *mpsse, char *data, int size) } } } - + return MPSSE_FAIL; } -/* +/* * Function to perform fast transfers in MPSSE. * * @mpsse - libmpsse context pointer. diff --git a/src/mpsse.c b/src/mpsse.c index 456b51b..d3fb263 100644 --- a/src/mpsse.c +++ b/src/mpsse.c @@ -21,9 +21,9 @@ #include "config.h" /* List of known FT2232-based devices */ -struct vid_pid supported_devices[] = { - { 0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd" }, - { 0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd" }, +struct vid_pid supported_devices[] = { + { 0x0403, 0x6010, "FT2232 Future Technology Devices International, Ltd" }, + { 0x0403, 0x6011, "FT4232 Future Technology Devices International, Ltd" }, { 0x0403, 0x6014, "FT232H Future Technology Devices International, Ltd" }, /* These devices are based on FT2232 chips, but have not been tested. */ @@ -31,7 +31,7 @@ struct vid_pid supported_devices[] = { { 0x0403, 0x8879, "Bus Blaster v2 (channel B)" }, { 0x0403, 0xBDC8, "Turtelizer JTAG/RS232 Adapter A" }, { 0x0403, 0xCFF8, "Amontec JTAGkey" }, - { 0x0403, 0x8A98, "TIAO Multi Protocol Adapter"}, + { 0x0403, 0x8A98, "TIAO Multi Protocol Adapter"}, { 0x15BA, 0x0003, "Olimex Ltd. OpenOCD JTAG" }, { 0x15BA, 0x0004, "Olimex Ltd. OpenOCD JTAG TINY" }, @@ -40,12 +40,12 @@ struct vid_pid supported_devices[] = { /* * Opens and initializes the first FTDI device found. - * + * * @mode - Mode to open the device in. One of enum modes. * @freq - Clock frequency to use for the specified mode. * @endianess - Specifies how data is clocked in/out (MSB, LSB). * - * Returns a pointer to an MPSSE context structure. + * Returns a pointer to an MPSSE context structure. * On success, mpsse->open will be set to 1. * On failure, mpsse->open will be set to 0. */ @@ -75,7 +75,7 @@ struct mpsse_context *MPSSE(enum modes mode, int freq, int endianess) return mpsse; } -/* +/* * Open device by VID/PID * * @vid - Device vendor ID. @@ -87,7 +87,7 @@ struct mpsse_context *MPSSE(enum modes mode, int freq, int endianess) * @description - Device product description (set to NULL if not needed). * @serial - Device serial number (set to NULL if not needed). * - * Returns a pointer to an MPSSE context structure. + * Returns a pointer to an MPSSE context structure. * On success, mpsse->open will be set to 1. * On failure, mpsse->open will be set to 0. */ @@ -96,7 +96,7 @@ struct mpsse_context *Open(int vid, int pid, enum modes mode, int freq, int endi return OpenIndex(vid, pid, mode, freq, endianess, interface, description, serial, 0); } -/* +/* * Open device by VID/PID/index * * @vid - Device vendor ID. @@ -109,7 +109,7 @@ struct mpsse_context *Open(int vid, int pid, enum modes mode, int freq, int endi * @serial - Device serial number (set to NULL if not needed). * @index - Device index (set to 0 if not needed). * - * Returns a pointer to an MPSSE context structure. + * Returns a pointer to an MPSSE context structure. * On success, mpsse->open will be set to 1. * On failure, mpsse->open will be set to 0. */ @@ -150,7 +150,7 @@ struct mpsse_context *OpenIndex(int vid, int pid, enum modes mode, int freq, int { mpsse->xsize = SPI_RW_SIZE; } - + status |= ftdi_usb_reset(&mpsse->ftdi); status |= ftdi_set_latency_timer(&mpsse->ftdi, LATENCY_MS); status |= ftdi_write_data_set_chunksize(&mpsse->ftdi, CHUNK_SIZE); @@ -161,7 +161,7 @@ struct mpsse_context *OpenIndex(int vid, int pid, enum modes mode, int freq, int { /* Set the read and write timeout periods */ set_timeouts(mpsse, USB_TIMEOUT); - + if(mpsse->mode != BITBANG) { ftdi_set_bitmode(&mpsse->ftdi, 0, BITMODE_MPSSE); @@ -175,9 +175,9 @@ struct mpsse_context *OpenIndex(int vid, int pid, enum modes mode, int freq, int /* Give the chip a few mS to initialize */ usleep(SETUP_DELAY); - /* + /* * Not all FTDI chips support all the commands that SetMode may have sent. - * This clears out any errors from unsupported commands that might have been sent during set up. + * This clears out any errors from unsupported commands that might have been sent during set up. */ ftdi_usb_purge_buffers(&mpsse->ftdi); } @@ -199,7 +199,7 @@ struct mpsse_context *OpenIndex(int vid, int pid, enum modes mode, int freq, int return mpsse; } -/* +/* * Closes the device, deinitializes libftdi, and frees the MPSSE context pointer. * * @mpsse - MPSSE context pointer. @@ -365,32 +365,32 @@ int SetMode(struct mpsse_context *mpsse, int endianess) { retval = raw_write(mpsse, setup_commands, setup_commands_size); } - + if(retval == MPSSE_OK) { /* Set the idle pin states */ set_bits_low(mpsse, mpsse->pidle); - - /* All GPIO pins are outputs, set low */ - mpsse->trish = 0xFF; - mpsse->gpioh = 0x00; - - buf[i++] = SET_BITS_HIGH; - buf[i++] = mpsse->gpioh; - buf[i++] = mpsse->trish; - + + /* All GPIO pins are inputs, set high */ + mpsse->trish = 0x00; + mpsse->gpioh = 0xff; + + buf[i++] = SET_BITS_HIGH; + buf[i++] = mpsse->gpioh; + buf[i++] = mpsse->trish; + retval = raw_write(mpsse, buf, i); } } else { retval = MPSSE_FAIL; - } + } return retval; } -/* +/* * Sets the appropriate divisor for the desired clock frequency. * * @mpsse - MPSSE context pointer. @@ -419,7 +419,7 @@ int SetClock(struct mpsse_context *mpsse, uint32_t freq) buf[0] = TCK_D5; system_clock = TWELVE_MHZ; } - + if(raw_write(mpsse, buf, 1) == MPSSE_OK) { if(freq <= 0) @@ -430,11 +430,11 @@ int SetClock(struct mpsse_context *mpsse, uint32_t freq) { divisor = freq2div(system_clock, freq); } - + buf[0] = TCK_DIVISOR; buf[1] = (divisor & 0xFF); buf[2] = ((divisor >> 8) & 0xFF); - + if(raw_write(mpsse, buf, 3) == MPSSE_OK) { mpsse->clock = div2freq(system_clock, divisor); @@ -442,11 +442,11 @@ int SetClock(struct mpsse_context *mpsse, uint32_t freq) } } } - + return retval; } -/* +/* * Retrieves the last error string from libftdi. * * @mpsse - MPSSE context pointer. @@ -463,7 +463,7 @@ const char *ErrorString(struct mpsse_context *mpsse) return NULL_CONTEXT_ERROR_MSG; } -/* +/* * Gets the currently configured clock rate. * * @mpsse - MPSSE context pointer. @@ -484,7 +484,7 @@ int GetClock(struct mpsse_context *mpsse) /* * Returns the vendor ID of the FTDI chip. - * + * * @mpsse - MPSSE context pointer. * * Returns the integer value of the vendor ID. @@ -530,7 +530,7 @@ int GetPid(struct mpsse_context *mpsse) const char *GetDescription(struct mpsse_context *mpsse) { char *description = NULL; - + if(is_valid_context(mpsse)) { description = mpsse->description; @@ -539,9 +539,9 @@ const char *GetDescription(struct mpsse_context *mpsse) return description; } -/* +/* * Enable / disable internal loopback. - * + * * @mpsse - MPSSE context pointer. * @enable - Zero to disable loopback, 1 to enable loopback. * @@ -601,7 +601,7 @@ void SetCSIdle(struct mpsse_context *mpsse, int idle) return; } -/* +/* * Enables or disables flushing of the FTDI chip's RX buffers after each read operation. * Flushing is disable by default. * @@ -635,7 +635,7 @@ int Start(struct mpsse_context *mpsse) { /* Set the default pin states while the clock is low since this is an I2C repeated start condition */ status |= set_bits_low(mpsse, (mpsse->pidle & ~SK)); - + /* Make sure the pins are in their default idle state */ status |= set_bits_low(mpsse, mpsse->pidle); } @@ -643,9 +643,9 @@ int Start(struct mpsse_context *mpsse) /* Set the start condition */ status |= set_bits_low(mpsse, mpsse->pstart); - /* + /* * Hackish work around to properly support SPI mode 3. - * SPI3 clock idles high, but needs to be set low before sending out + * SPI3 clock idles high, but needs to be set low before sending out * data to prevent unintenteded clock glitches from the FT2232. */ if(mpsse->mode == SPI3) @@ -661,7 +661,7 @@ int Start(struct mpsse_context *mpsse) { status |= set_bits_low(mpsse, (mpsse->pstart | SK)); } - + mpsse->status = STARTED; } else @@ -673,7 +673,7 @@ int Start(struct mpsse_context *mpsse) return status; } -/* +/* * Performs a bit-wise write of up to 8 bits at a time. * * @mpsse - MPSSE context pointer. @@ -743,28 +743,28 @@ int Write(struct mpsse_context *mpsse, char *data, int size) { txsize = mpsse->xsize; } - - /* - * For I2C we need to send each byte individually so that we can + + /* + * For I2C we need to send each byte individually so that we can * read back each individual ACK bit, so set the transmit size to 1. */ if(mpsse->mode == I2C) { txsize = 1; } - + buf = build_block_buffer(mpsse, mpsse->tx, (unsigned char *) (data + n), txsize, &buf_size); if(buf) - { + { retval = raw_write(mpsse, buf, buf_size); n += txsize; free(buf); - + if(retval == MPSSE_FAIL) { break; } - + /* Read in the ACK bit and store it in mpsse->rack */ if(mpsse->mode == I2C) { @@ -777,13 +777,13 @@ int Write(struct mpsse_context *mpsse, char *data, int size) } } } - + if(retval == MPSSE_OK && n == size) { retval = MPSSE_OK; } } - + return retval; } @@ -802,7 +802,7 @@ char *InternalRead(struct mpsse_context *mpsse, int size) if(buf) { memset(buf, 0, size); - + while(n < size) { rxsize = size - n; @@ -810,13 +810,13 @@ char *InternalRead(struct mpsse_context *mpsse, int size) { rxsize = mpsse->xsize; } - + data = build_block_buffer(mpsse, mpsse->rx, sbuf, rxsize, &data_size); if(data) { retval = raw_write(mpsse, data, data_size); free(data); - + if(retval == MPSSE_OK) { n += raw_read(mpsse, buf+n, rxsize); @@ -840,7 +840,7 @@ char *InternalRead(struct mpsse_context *mpsse, int size) /* * Reads data over the selected serial protocol. - * + * * @mpsse - MPSSE context pointer. * @size - Number of bytes to read. * @@ -867,7 +867,7 @@ char *Read(struct mpsse_context *mpsse, int size) #endif } -/* +/* * Performs a bit-wise read of up to 8 bits. * * @mpsse - MPSSE context pointer. @@ -904,13 +904,13 @@ char ReadBits(struct mpsse_context *mpsse, int size) } else if(mpsse->endianess == LSB) { - /* + /* * In LSB mode, bits are shifted in from the right. If less than 8 bits were * read, we need to shift them right accordingly. */ bits = bits >> (8-size); } - + free(rdata); } @@ -919,7 +919,7 @@ char ReadBits(struct mpsse_context *mpsse, int size) /* * Reads and writes data over the selected serial protocol (SPI only). - * + * * @mpsse - MPSSE context pointer. * @data - Buffer containing bytes to write. * @size - Number of bytes to transfer. @@ -997,7 +997,7 @@ char *Transfer(struct mpsse_context *mpsse, char *data, int size) * Returns either an ACK (0) or a NACK (1). */ int GetAck(struct mpsse_context *mpsse) -{ +{ int ack = 0; if(is_valid_context(mpsse)) @@ -1085,7 +1085,7 @@ int Stop(struct mpsse_context *mpsse) /* Restore the pins to their idle states */ retval |= set_bits_low(mpsse, mpsse->pidle); } - + mpsse->status = STOPPED; } else @@ -1097,12 +1097,12 @@ int Stop(struct mpsse_context *mpsse) return retval; } -/* - * Sets the specified pin high. +/* + * Sets the specified pin high. * * @mpsse - MPSSE context pointer. * @pin - Pin number to set high. - * + * * Returns MPSSE_OK on success. * Returns MPSSE_FAIL on failure. */ @@ -1130,7 +1130,7 @@ int PinHigh(struct mpsse_context *mpsse, int pin) int PinLow(struct mpsse_context *mpsse, int pin) { int retval = MPSSE_FAIL; - + if(is_valid_context(mpsse)) { retval = gpio_write(mpsse, pin, LOW); @@ -1140,14 +1140,14 @@ int PinLow(struct mpsse_context *mpsse, int pin) } /* - * Sets the input/output direction of all pins. For use in BITBANG mode only. + * Sets the input/output direction of all pins. * * @mpsse - MPSSE context pointer. * @direction - Byte indicating input/output direction of each bit. 1 is out. * * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. */ -int SetDirection(struct mpsse_context *mpsse, uint8_t direction) +int SetDirection(struct mpsse_context *mpsse, int direction) { int retval = MPSSE_FAIL; @@ -1155,25 +1155,41 @@ int SetDirection(struct mpsse_context *mpsse, uint8_t direction) { if(mpsse->mode == BITBANG) { - if(ftdi_set_bitmode(&mpsse->ftdi, direction, BITMODE_BITBANG) == 0) - { + if(ftdi_set_bitmode(&mpsse->ftdi, (uint8_t)direction, BITMODE_BITBANG) == 0) + { retval = MPSSE_OK; } + } else { + mpsse->tris = (uint8_t)direction; + retval = set_bits_low(mpsse, mpsse->pidle); } } return retval; } +int SetDirectionHigh(struct mpsse_context *mpsse, int direction) // uint8_t +{ + int retval = MPSSE_FAIL; + + if(is_valid_context(mpsse)) + { + mpsse->trish = (uint8_t)direction; + retval = set_bits_high(mpsse, mpsse->pidle); + } + + return retval; +} + /* - * Sets the input/output value of all pins. For use in BITBANG mode only. + * Sets the input/output value of all pins. * * @mpsse - MPSSE context pointer. * @data - Byte indicating bit hi/low value of each bit. * * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. */ -int WritePins(struct mpsse_context *mpsse, uint8_t data) +int WritePins(struct mpsse_context *mpsse, int data) { int retval = MPSSE_FAIL; @@ -1181,18 +1197,54 @@ int WritePins(struct mpsse_context *mpsse, uint8_t data) { if(mpsse->mode == BITBANG) { - if(ftdi_write_data(&mpsse->ftdi, &data, 1) == 0) + uint8_t _data; + _data = (uint8_t)data; + if(ftdi_write_data(&mpsse->ftdi, &_data, 1) == 0) { retval = MPSSE_OK; } + } else { + retval = set_bits_low(mpsse, (uint8_t)data); } } - + return retval; } +/* + * Sets the input/output value of all high pins. + * + * @mpsse - MPSSE context pointer. + * @data - Byte indicating bit hi/low value of each bit. + * + * Returns MPSSE_OK if direction could be set, MPSSE_FAIL otherwise. + */ +int WritePinsHigh(struct mpsse_context *mpsse, int data) +{ + int retval = MPSSE_FAIL; + if(is_valid_context(mpsse)) + { + retval = set_bits_high(mpsse, (uint8_t)data); + } + + return retval; +} + +// read high pins stae +int _read_high_byte_data(struct mpsse_context *mpsse, uint8_t *data) +{ + struct ftdi_context *ftdi = &mpsse->ftdi; + uint8_t obuf; + int ret; + + obuf = GET_BITS_HIGH; + ret = ftdi_write_data(ftdi, &obuf, 1); + ret = ftdi_read_data(ftdi, data, 1); + + return ret; +} /* - * Reads the state of the chip's pins. For use in BITBANG mode only. + * Reads the state of the chip's pins. * * @mpsse - MPSSE context pointer. * @@ -1210,8 +1262,17 @@ int ReadPins(struct mpsse_context *mpsse) return (int) val; } +int ReadPinsHigh(struct mpsse_context *mpsse) +{ + uint8_t val = 0; + if(is_valid_context(mpsse)){ + _read_high_byte_data(mpsse, &val); + } + return (int)val; +} + /* - * Checks if a specific pin is high or low. For use in BITBANG mode only. + * Checks if a specific pin is high or low. * * @mpsse - MPSSE context pointer. * @pin - The pin number. @@ -1222,17 +1283,24 @@ int ReadPins(struct mpsse_context *mpsse) */ int PinState(struct mpsse_context *mpsse, int pin, int state) { - if(state == -1) - { - state = ReadPins(mpsse); - } - - /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert these defines into an absolute pin number. */ - if(mpsse->mode != BITBANG) + if(mpsse->mode == BITBANG) { + if(state == -1) + { + state = ReadPins(mpsse); + } + } else { + /* If not in bitbang mode, the specified pin should be one of GPIOLx. Convert these defines into an absolute pin number. */ pin += NUM_GPIOL_PINS; - } + uint8_t _state; + _state = (uint8_t)state; + if (pin > 7){ + _read_high_byte_data(mpsse, &_state); + pin -= 8; + state = (int)_state; + } + } return ((state & (1 << pin)) >> pin); } @@ -1255,8 +1323,8 @@ int Tristate(struct mpsse_context *mpsse) return raw_write(mpsse, cmd, sizeof(cmd)); } -/* - * Returns the libmpsse version number. +/* + * Returns the libmpsse version number. * High nibble is major version, low nibble is minor version. */ char Version(void) @@ -1275,7 +1343,7 @@ char Version(void) } major = atoi(version_string); - + free(version_string); } diff --git a/src/mpsse.h b/src/mpsse.h index 4a00eed..4fe16dc 100644 --- a/src/mpsse.h +++ b/src/mpsse.h @@ -1,4 +1,4 @@ -#ifndef _LIBMPSSE_H_ +#ifndef _LIBMPSSE_H_ #define _LIBMPSSE_H_ #include @@ -16,7 +16,7 @@ #define LSB 0x08 #define CHUNK_SIZE 65535 -#define SPI_RW_SIZE (63 * 1024) +#define SPI_RW_SIZE (63 * 1024) #define SPI_TRANSFER_SIZE 512 #define I2C_TRANSFER_SIZE 64 @@ -111,8 +111,8 @@ enum i2c_ack NACK = 1 }; -#define DEFAULT_TRIS (SK | DO | CS | GPIO0 | GPIO1 | GPIO2 | GPIO3) /* SK/DO/CS and GPIOs are outputs, DI is an input */ -#define DEFAULT_PORT (SK | CS) /* SK and CS are high, all others low */ +#define DEFAULT_TRIS (SK | DO | CS) /* SK/DO/CS are outputs, DI and GPIOLs are input */ +#define DEFAULT_PORT (SK | CS) /* SK and CS are high, all others low */ enum mpsse_commands { @@ -196,11 +196,14 @@ void SendNacks(struct mpsse_context *mpsse); void FlushAfterRead(struct mpsse_context *mpsse, int tf); int PinHigh(struct mpsse_context *mpsse, int pin); int PinLow(struct mpsse_context *mpsse, int pin); -int SetDirection(struct mpsse_context *mpsse, uint8_t direction); +int SetDirection(struct mpsse_context *mpsse, int direction); +int SetDirectionHigh(struct mpsse_context *mpsse, int direction); int WriteBits(struct mpsse_context *mpsse, char bits, int size); char ReadBits(struct mpsse_context *mpsse, int size); -int WritePins(struct mpsse_context *mpsse, uint8_t data); +int WritePins(struct mpsse_context *mpsse, int data); +int WritePinsHigh(struct mpsse_context *mpsse, int data); int ReadPins(struct mpsse_context *mpsse); +int ReadPinsHigh(struct mpsse_context *mpsse); int PinState(struct mpsse_context *mpsse, int pin, int state); int Tristate(struct mpsse_context *mpsse); char Version(void); diff --git a/src/mpsse.i b/src/mpsse.i index 976a583..7d91569 100644 --- a/src/mpsse.i +++ b/src/mpsse.i @@ -1,6 +1,8 @@ %module pylibmpsse +%include %{ #include "mpsse.h" +#include %} %typemap(in) (char *data, int size) diff --git a/src/mpsse.py b/src/mpsse.py index bc67f8b..1fd87d2 100644 --- a/src/mpsse.py +++ b/src/mpsse.py @@ -2,7 +2,7 @@ MPSSE_OK = _mpsse.MPSSE_OK MPSSE_FAIL = _mpsse.MPSSE_FAIL - + MSB = _mpsse.MSB LSB = _mpsse.LSB @@ -111,7 +111,7 @@ def Close(self): """ retval = _mpsse.Close(self.context) self.context = None - + def ErrorString(self): """ Returns the last libftdi error string. @@ -125,7 +125,7 @@ def SetMode(self, mode, endianess): @mode - The MPSSE mode to use, one of: SPI0, SPI1, SPI2, SPI3, I2C, GPIO, BITBANG. @endianess - The endianess of data transfers, one of: MSB, LSB. - + Returns MPSSE_OK on success. Raises an exception on failure. """ @@ -188,7 +188,7 @@ def GetPid(self): def GetDescription(self): """ - Returns the description of the FTDI chip, if any. + Returns the description of the FTDI chip, if any. This will only be populated if __init__ was used to open the device. """ return _mpsse.GetDescription(self.context) @@ -241,7 +241,7 @@ def Stop(self): def Write(self, data): """ Writes bytes out via the selected serial protocol. - + @data - A string of bytes to be written. Returns MPSSE_OK on success. @@ -310,7 +310,7 @@ def GetAck(self): def PinHigh(self, pin): """ Sets the specified GPIO pin high. - + @pin - Pin number 0 - 11 in GPIO mode. In all other modes, one of: GPIOL0, GPIOL1, GPIOL2, GPIOL3, GPIOH0, GPIOH1, GPIOH2, GPIOH3, GPIOH4, GPIOH5, GPIOH6, GPIOH7. @@ -324,10 +324,10 @@ def PinHigh(self, pin): def PinLow(self, pin): """ Sets the specified GPIO pin low. - + @pin - Pin number 0 - 11 in GPIO mode. In all other modes, one of: GPIOL0, GPIOL1, GPIOL2, GPIOL3, GPIOH0, GPIOH1, GPIOH2, GPIOH3, GPIOH4, GPIOH5, GPIOH6, GPIOH7. - + Returns MPSSE_OK on success. Raises an exception on failure. """ @@ -337,10 +337,9 @@ def PinLow(self, pin): def SetDirection(self, direction): """ - Sets the input/output direction of pins as determined by direction (1 = Output, 0 = Input). - For use in BITBANG mode only. + Sets the input/output direction of pins as determined by direction (1 = Output, 0 = Input). - @direction - Byte indicating input/output direction of each bit (1 is output, 0 is input). + @direction - Byte indicating input/output direction of each bit (1 is output, 0 is input). Returns MPSSE_OK on success. Raises an exception on failure. @@ -349,10 +348,23 @@ def SetDirection(self, direction): raise Exception, self.ErrorString() return MPSSE_OK + def SetDirectionHigh(self, direction): + """ + Sets the input/output direction of high pins as determined by direction (1 = Output, 0 = Input). + + @direction - Byte indicating input/output direction of each bit (1 is output, 0 is input). + + Returns MPSSE_OK on success. + Raises an exception on failure. + """ + if _mpsse.SetDirectionHigh(self.context, direction) == MPSSE_FAIL: + raise Exception, self.ErrorString() + return MPSSE_OK + def WriteBits(self, bits, n): """ Performs a bitwise write of up to 8 bits at a time. - + @bits - An integer of bits to be written. @n - Transmit n number of least-significant bits. @@ -376,7 +388,6 @@ def ReadBits(self, n): def WritePins(self, data): """ Writes a new state to the chip's pins. - For use in BITBANG mode only. @data - An integer with the bits set to the desired pin states (1 = output, 0 = input). @@ -387,22 +398,41 @@ def WritePins(self, data): raise Exception, self.ErrorString() return MPSSE_OK + def WritePinsHigh(self, data): + """ + Writes a new state to the chip's high pins. + + @data - An integer with the bits set to the desired pin states (1 = output, 0 = input). + + Returns MPSSE_OK on success. + Raises an exception on failure. + """ + if _mpsse.WritePinsHigh(self.context, data) == MPSSE_FAIL: + raise Exception, self.ErrorString() + return MPSSE_OK + def ReadPins(self): """ Reads the current state of the chip's pins. - For use in BITBANG mode only. Returns an integer with the corresponding pin's bits set. """ return _mpsse.ReadPins(self.context) + def ReadPinsHigh(self): + """ + Reads the current state of the chip's high pins. + + Returns an integer with the corresponding pin's bits set. + """ + return _mpsse.ReadPinsHigh(self.context) + def PinState(self, pin, state=-1): """ Checks the current state of the pins. - For use in BITBANG mode only. - @pin - The pin number whose state you want to check. - @state - The value returned by ReadPins. If not specified, ReadPins will be called automatically. + @pin - The pin number whose state you want to check. + @state - pins Value. GPIOL[0-3], GPIOH[0-7] support Returns a 1 if the pin is high, 0 if the pin is low. """ diff --git a/src/support.c b/src/support.c index d34f8b3..238c3ec 100644 --- a/src/support.c +++ b/src/support.c @@ -48,9 +48,9 @@ int raw_read(struct mpsse_context *mpsse, unsigned char *buf, int size) if(mpsse->flush_after_read) { - /* + /* * Make sure the buffers are cleared after a read or subsequent reads may fail. - * + * * Is this needed anymore? It slows down repetitive read operations by ~8%. */ ftdi_usb_purge_rx_buffer(&mpsse->ftdi); @@ -139,7 +139,7 @@ unsigned char *build_block_buffer(struct mpsse_context *mpsse, uint8_t cmd, unsi { buf[i++] = SET_BITS_LOW; buf[i++] = mpsse->pstart & ~SK; - + /* On receive, we need to ensure that the data out line is set as an input to avoid contention on the bus */ if(cmd == mpsse->rx) { @@ -240,11 +240,11 @@ int gpio_write(struct mpsse_context *mpsse, int pin, int direction) { mpsse->bitbang |= (1 << pin); } - else + else { mpsse->bitbang &= ~(1 << pin); } - + if(set_bits_high(mpsse, mpsse->bitbang) == MPSSE_OK) { retval = raw_write(mpsse, (unsigned char *) &mpsse->bitbang, 1); @@ -286,8 +286,8 @@ int gpio_write(struct mpsse_context *mpsse, int pin, int direction) { mpsse->gpioh &= ~(1 << pin); } - - retval = set_bits_high(mpsse, mpsse->gpioh); + + retval = set_bits_high(mpsse, mpsse->gpioh); } }