#include "remote_bitbang.h"
-#define DEBUG
-#ifdef DEBUG
-# define D(x) x
-#else
-# define D(x)
-#endif // DEBUG
-
/////////// Circular buffer
template <typename T>
}
}
+template <typename T>
+void circular_buffer_t<T>::append(T value)
+{
+ append(&value, 1);
+}
+
/////////// remote_bitbang_t
remote_bitbang_t::remote_bitbang_t(uint16_t port, sim_t *sim) :
{
if (client_fd > 0) {
this->read();
+ process_input();
this->write();
} else {
this->accept();
}
}
+
+void remote_bitbang_t::process_input()
+{
+ for (unsigned i = 0; i < recv_buf.size(); i++) {
+ uint8_t command = recv_buf[i];
+
+ switch (command) {
+ case 'B': fprintf(stderr, "*BLINK*\n"); break;
+ case 'b': fprintf(stderr, "_______\n"); break;
+ case 'r': tap.reset(); break;
+ case '0': tap.set_pins(0, 0, 0); break;
+ case '1': tap.set_pins(0, 0, 1); break;
+ case '2': tap.set_pins(0, 1, 0); break;
+ case '3': tap.set_pins(0, 1, 1); break;
+ case '4': tap.set_pins(1, 0, 0); break;
+ case '5': tap.set_pins(1, 0, 1); break;
+ case '6': tap.set_pins(1, 1, 0); break;
+ case '7': tap.set_pins(1, 1, 1); break;
+ case 'R': send_buf.append(tap.tdo() ? '1' : '0'); break;
+ default:
+ fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", command);
+ }
+ }
+ recv_buf.reset();
+}
#include <stdint.h>
+#define DEBUG
+#ifdef DEBUG
+# define D(x) x
+#else
+# define D(x)
+#endif // DEBUG
+
class sim_t;
template <typename T>
T operator[](unsigned int i) const { return data[(start + i) % capacity]; }
void append(const T *src, unsigned int count);
+ void append(T value);
+};
+
+typedef enum {
+ TEST_LOGIC_RESET,
+ RUN_TEST_IDLE,
+ SELECT_DR_SCAN,
+ CAPTURE_DR,
+ SHIFT_DR,
+ EXIT1_DR,
+ PAUSE_DR,
+ EXIT2_DR,
+ UPDATE_DR,
+ SELECT_IR_SCAN,
+ CAPTURE_IR,
+ SHIFT_IR,
+ EXIT1_IR,
+ PAUSE_IR,
+ EXIT2_IR,
+ UPDATE_IR
+} jtag_state_t;
+
+class jtag_tap_t
+{
+ public:
+ jtag_tap_t() :
+ state(TEST_LOGIC_RESET) {}
+
+ void reset() {
+ state = TEST_LOGIC_RESET;
+ }
+
+ void set_pins(bool tck, bool tms, bool tdi) {
+ if (!_tck && tck) {
+ // Positive clock edge.
+
+ D(fprintf(stderr, "Next state: %d\n", state));
+
+ state = next[state][_tms];
+
+ switch (state) {
+ case TEST_LOGIC_RESET:
+ ir = 1;
+ break;
+ case CAPTURE_DR:
+ dr = 0xdeadbeef;
+ dr_length = 32;
+ break;
+ case SHIFT_DR:
+ _tdo = dr & 1;
+ dr >>= 1;
+ dr |= (uint64_t) _tdi << (dr_length-1);
+ break;
+ case UPDATE_DR:
+ break;
+ case CAPTURE_IR:
+ break;
+ case SHIFT_IR:
+ _tdo = ir & 1;
+ ir >>= 1;
+ ir = ir | (_tdi << (ir_length-1));
+ break;
+ case UPDATE_IR:
+ break;
+ default:
+ break;
+ }
+ }
+ _tck = tck;
+ _tms = tms;
+ _tdi = tdi;
+
+ D(fprintf(stderr, "tck=%d tms=%d tdi=%d tdo=%d ir=0x%x dr=0x%lx\n",
+ _tck, _tms, _tdi, _tdo, ir, dr));
+ }
+
+ bool tdo() const { return _tdo; }
+
+ private:
+ bool _tck, _tms, _tdi, _tdo;
+ uint32_t ir;
+ unsigned ir_length;
+ uint64_t dr;
+ unsigned dr_length;
+
+ jtag_state_t state;
+ const jtag_state_t next[16][2] = {
+ /* TEST_LOGIC_RESET */ { RUN_TEST_IDLE, TEST_LOGIC_RESET },
+ /* RUN_TEST_IDLE */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
+ /* SELECT_DR_SCAN */ { CAPTURE_DR, SELECT_IR_SCAN },
+ /* CAPTURE_DR */ { SHIFT_DR, EXIT1_DR },
+ /* SHIFT_DR */ { SHIFT_DR, EXIT1_DR },
+ /* EXIT1_DR */ { PAUSE_DR, UPDATE_DR },
+ /* PAUSE_DR */ { PAUSE_DR, EXIT2_DR },
+ /* EXIT2_DR */ { SHIFT_DR, UPDATE_DR },
+ /* UPDATE_DR */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
+ /* SELECT_IR_SCAN */ { CAPTURE_IR, TEST_LOGIC_RESET },
+ /* CAPTURE_IR */ { SHIFT_IR, EXIT1_IR },
+ /* SHIFT_IR */ { SHIFT_IR, EXIT1_IR },
+ /* EXIT1_IR */ { PAUSE_IR, UPDATE_IR },
+ /* PAUSE_IR */ { PAUSE_IR, EXIT2_IR },
+ /* EXIT2_IR */ { SHIFT_IR, UPDATE_IR },
+ /* UPDATE_IR */ { RUN_TEST_IDLE, SELECT_DR_SCAN }
+ };
};
class remote_bitbang_t
void tick();
private:
+ jtag_tap_t tap;
+
int socket_fd;
int client_fd;
circular_buffer_t<uint8_t> recv_buf;
void read();
// Write as much of send_buf as possible.
void write();
+
+ // Process the input buffer.
+ void process_input();
};
#endif