+/**
+ * Function buffer_write
+ * writes a byte into the byte buffer, "ft2232_buffer", which must be sent later.
+ * @param val is the byte to send.
+ */
+static inline void buffer_write(uint8_t val)
+{
+ assert(ft2232_buffer);
+ assert((unsigned) ft2232_buffer_size < (unsigned) FT2232_BUFFER_SIZE);
+ ft2232_buffer[ft2232_buffer_size++] = val;
+}
+
+/**
+ * Function buffer_read
+ * returns a byte from the byte buffer.
+ */
+static inline uint8_t buffer_read(void)
+{
+ assert(ft2232_buffer);
+ assert(ft2232_read_pointer < ft2232_buffer_size);
+ return ft2232_buffer[ft2232_read_pointer++];
+}
+
+
+/**
+ * Clocks out \a bit_count bits on the TMS line, starting with the least
+ * significant bit of tms_bits and progressing to more significant bits.
+ * Rigorous state transition logging is done here via tap_set_state().
+ *
+ * @param mpsse_cmd One of the MPSSE TMS oriented commands such as
+ * 0x4b or 0x6b. See the MPSSE spec referenced above for their
+ * functionality. The MPSSE command "Clock Data to TMS/CS Pin (no Read)"
+ * is often used for this, 0x4b.
+ *
+ * @param tms_bits Holds the sequence of bits to send.
+ * @param tms_count Tells how many bits in the sequence.
+ * @param tdi_bit A single bit to pass on to TDI before the first TCK
+ * cycle and held static for the duration of TMS clocking.
+ *
+ * See the MPSSE spec referenced above.
+ */
+static void clock_tms(uint8_t mpsse_cmd, int tms_bits, int tms_count, bool tdi_bit)
+{
+ uint8_t tms_byte;
+ int i;
+ int tms_ndx; /* bit index into tms_byte */
+
+ assert(tms_count > 0);
+
+// LOG_DEBUG("mpsse cmd=%02x, tms_bits=0x%08x, bit_count=%d", mpsse_cmd, tms_bits, tms_count);
+
+ for (tms_byte = tms_ndx = i = 0; i < tms_count; ++i, tms_bits>>=1)
+ {
+ bool bit = tms_bits & 1;
+
+ if (bit)
+ tms_byte |= (1<<tms_ndx);
+
+ /* always do state transitions in public view */
+ tap_set_state(tap_state_transition(tap_get_state(), bit));
+
+ /* we wrote a bit to tms_byte just above, increment bit index. if bit was zero
+ also increment.
+ */
+ ++tms_ndx;
+
+ if (tms_ndx==7 || i==tms_count-1)
+ {
+ buffer_write(mpsse_cmd);
+ buffer_write(tms_ndx - 1);
+
+ /* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of
+ TMS/CS and is held static for the duration of TMS/CS clocking.
+ */
+ buffer_write(tms_byte | (tdi_bit << 7));
+ }
+ }
+}
+
+
+/**
+ * Function get_tms_buffer_requirements
+ * returns what clock_tms() will consume if called with
+ * same \a bit_count.
+ */
+static inline int get_tms_buffer_requirements(int bit_count)
+{
+ return ((bit_count + 6)/7) * 3;
+}
+
+
+/**
+ * Function move_to_state
+ * moves the TAP controller from the current state to a
+ * \a goal_state through a path given by tap_get_tms_path(). State transition
+ * logging is performed by delegation to clock_tms().
+ *
+ * @param goal_state is the destination state for the move.
+ */
+static void move_to_state(tap_state_t goal_state)
+{
+ tap_state_t start_state = tap_get_state();
+
+ /* goal_state is 1/2 of a tuple/pair of states which allow convenient
+ lookup of the required TMS pattern to move to this state from the
+ start state.
+ */
+
+ /* do the 2 lookups */
+ int tms_bits = tap_get_tms_path(start_state, goal_state);
+ int tms_count = tap_get_tms_path_len(start_state, goal_state);
+
+ DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state));
+
+ clock_tms(0x4b, tms_bits, tms_count, 0);
+}
+