diff --git a/src/ftdipp_mpsse.cpp b/src/ftdipp_mpsse.cpp index 3f1fcf6..b4c26f7 100644 --- a/src/ftdipp_mpsse.cpp +++ b/src/ftdipp_mpsse.cpp @@ -335,6 +335,140 @@ int FTDIpp_MPSSE::mpsse_read(unsigned char *rx_buff, int len) return num_read; } +/** + * Read GPIO (xCBUSy + xDBUSy) bank + * @return pins state + */ +uint16_t FTDIpp_MPSSE::gpio_get() +{ + uint8_t tx[2] = {GET_BITS_LOW, GET_BITS_HIGH}; + uint8_t rx[2]; + mpsse_store(tx, 2); + mpsse_read(rx, 2); + + return (rx[1] << 8) | rx[0]; +} + +/** + * Read low (xCBUSy) or high (xDBUSy) pins. + * @param[in] low_pins: if true read low, read high otherwise + * @return pins state + */ +uint8_t FTDIpp_MPSSE::gpio_get(bool low_pins) +{ + uint8_t rx; + + /* select between high and low pins */ + mpsse_store((low_pins) ? GET_BITS_LOW : GET_BITS_HIGH); + mpsse_read(&rx, 1); + return rx; +} + +/** + * Set one or more pins of the full bank (CBUS + DBUS). + * @param[in] pins bitmask + * @return false when error, true otherwise + */ +bool FTDIpp_MPSSE::gpio_set(uint16_t gpios) +{ + _cable.bit_high_val |= (0xff & (gpios >> 8)); + _cable.bit_low_val |= (0xff & gpios); + __gpio_write(true); + __gpio_write(false); + return (mpsse_write() >= 0); +} + +/** + * Set one or more pins of the given half bank (CBUS or BDUS). + * @param[in] pin bitmask + * @param[in] low/high half bank + * @return false when error, true otherwise + */ +bool FTDIpp_MPSSE::gpio_set(uint8_t gpios, bool low_pins) +{ + if (low_pins) + _cable.bit_low_val |= gpios; + else + _cable.bit_high_val |= gpios; + __gpio_write(low_pins); + return (mpsse_write() >= 0); +} + +/** + * Clear one or more pins of the full bank (CBUS + DBUS). + * @param[in] pins bitmask + * @return false when error, true otherwise + */ +bool FTDIpp_MPSSE::gpio_clear(uint16_t gpios) +{ + _cable.bit_high_val &= ~(0xff & (gpios >> 8)); + _cable.bit_low_val &= ~(0xff & gpios); + __gpio_write(true); + __gpio_write(false); + return (mpsse_write() >= 0); +} + +/** + * Clear one or more pins of the given half bank (CBUS or BDUS). + * @param[in] pin bitmask + * @param[in] low/high half bank + * @return false when error, true otherwise + */ +bool FTDIpp_MPSSE::gpio_clear(uint8_t gpios, bool low_pins) +{ + if (low_pins) + _cable.bit_low_val &= ~(gpios); + else + _cable.bit_high_val &= ~(gpios); + + __gpio_write(low_pins); + return (mpsse_write() >= 0); +} + +/** + * Full bank write + * @param[in] GPIOs bitmask + * @return false when error, true otherwise + */ +bool FTDIpp_MPSSE::gpio_write(uint16_t gpio) +{ + _cable.bit_low_val = (0xff & gpio); + _cable.bit_high_val = (0xff & (gpio >> 8)); + __gpio_write(true); + __gpio_write(false); + return (mpsse_write() >= 0); +} + +/** + * Half bank write + * @param[in] gpio: pins values + * @param[in] low_pins: high/low half bank + * @return false when error, true otherwise + */ +bool FTDIpp_MPSSE::gpio_write(uint8_t gpio, bool low_pins) +{ + if (low_pins) + _cable.bit_low_val = gpio; + else + _cable.bit_high_val = gpio; + + __gpio_write(low_pins); + return (mpsse_write() >= 0); +} + +/** + * private method to write ftdi half bank GPIOs (pins state are in _cable) + * @param[in] low or high half bank + */ +bool FTDIpp_MPSSE::__gpio_write(bool low_pins) +{ + uint8_t tx[3]; + tx[0] = ((low_pins) ? SET_BITS_LOW : SET_BITS_HIGH); + tx[1] = ((low_pins) ? _cable.bit_low_val : _cable.bit_high_val); + tx[2] = ((low_pins) ? _cable.bit_low_dir : _cable.bit_high_dir); + return (mpsse_store(tx, 3) >= 0); +} + #ifdef USE_UDEV unsigned int FTDIpp_MPSSE::udevstufftoint(const char *udevstring, int base) { diff --git a/src/ftdipp_mpsse.hpp b/src/ftdipp_mpsse.hpp index fd3ff1e..bf940b3 100644 --- a/src/ftdipp_mpsse.hpp +++ b/src/ftdipp_mpsse.hpp @@ -27,6 +27,19 @@ class FTDIpp_MPSSE { int vid() {return _vid;} int pid() {return _pid;} + /* access gpio */ + /* read gpio */ + uint16_t gpio_get(); + uint8_t gpio_get(bool low_pins); + /* update selected gpio */ + bool gpio_set(uint16_t gpio); + bool gpio_set(uint8_t gpio, bool low_pins); + bool gpio_clear(uint16_t gpio); + bool gpio_clear(uint8_t gpio, bool low_pins); + /* full access */ + bool gpio_write(uint16_t gpio); + bool gpio_write(uint8_t gpio, bool low_pins); + protected: void open_device(const std::string &serial, unsigned int baudrate); void ftdi_usb_close_internal(); @@ -54,6 +67,8 @@ class FTDIpp_MPSSE { int _num; private: unsigned char *_buffer; + /* gpio */ + bool __gpio_write(bool low_pins); }; #endif