7f22cd3223be06176c1229201f90eecfab226b5e
12 #include "remote_bitbang.h"
14 /////////// Circular buffer
17 unsigned int circular_buffer_t
<T
>::size() const
22 return end
+ capacity
- start
;
26 void circular_buffer_t
<T
>::consume(unsigned int bytes
)
28 start
= (start
+ bytes
) % capacity
;
32 unsigned int circular_buffer_t
<T
>::contiguous_empty_size() const
36 return capacity
- end
- 1;
38 return capacity
- end
;
40 return start
- end
- 1;
44 unsigned int circular_buffer_t
<T
>::contiguous_data_size() const
49 return capacity
- start
;
53 void circular_buffer_t
<T
>::data_added(unsigned int bytes
)
56 assert(end
<= capacity
);
62 void circular_buffer_t
<T
>::reset()
69 void circular_buffer_t
<T
>::append(const T
*src
, unsigned int count
)
71 unsigned int copy
= std::min(count
, contiguous_empty_size());
72 memcpy(contiguous_empty(), src
, copy
* sizeof(T
));
76 assert(count
< contiguous_empty_size());
77 memcpy(contiguous_empty(), src
+copy
, count
* sizeof(T
));
83 void circular_buffer_t
<T
>::append(T value
)
88 /////////// remote_bitbang_t
90 remote_bitbang_t::remote_bitbang_t(uint16_t port
, sim_t
*sim
) :
96 socket_fd
= socket(AF_INET
, SOCK_STREAM
, 0);
97 if (socket_fd
== -1) {
98 fprintf(stderr
, "remote_bitbang failed to make socket: %s (%d)\n",
99 strerror(errno
), errno
);
103 fcntl(socket_fd
, F_SETFL
, O_NONBLOCK
);
105 if (setsockopt(socket_fd
, SOL_SOCKET
, SO_REUSEADDR
, &reuseaddr
,
106 sizeof(int)) == -1) {
107 fprintf(stderr
, "remote_bitbang failed setsockopt: %s (%d)\n",
108 strerror(errno
), errno
);
112 struct sockaddr_in addr
;
113 memset(&addr
, 0, sizeof(addr
));
114 addr
.sin_family
= AF_INET
;
115 addr
.sin_addr
.s_addr
= INADDR_ANY
;
116 addr
.sin_port
= htons(port
);
118 if (bind(socket_fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) == -1) {
119 fprintf(stderr
, "remote_bitbang failed to bind socket: %s (%d)\n",
120 strerror(errno
), errno
);
124 if (listen(socket_fd
, 1) == -1) {
125 fprintf(stderr
, "remote_bitbang failed to listen on socket: %s (%d)\n",
126 strerror(errno
), errno
);
131 void remote_bitbang_t::accept()
133 client_fd
= ::accept(socket_fd
, NULL
, NULL
);
134 if (client_fd
== -1) {
135 if (errno
== EAGAIN
) {
136 // No client waiting to connect right now.
138 fprintf(stderr
, "failed to accept on socket: %s (%d)\n", strerror(errno
),
143 fcntl(client_fd
, F_SETFL
, O_NONBLOCK
);
147 void remote_bitbang_t::read()
149 // Reading from a non-blocking socket still blocks if there is no data
152 size_t count
= recv_buf
.contiguous_empty_size();
153 ssize_t bytes
= ::read(client_fd
, recv_buf
.contiguous_empty(), count
);
155 if (errno
== EAGAIN
) {
156 // We'll try again the next call.
158 fprintf(stderr
, "failed to read on socket: %s (%d)\n", strerror(errno
), errno
);
161 } else if (bytes
== 0) {
162 // The remote disconnected.
167 recv_buf
.data_added(bytes
);
168 D(fprintf(stderr
, "receive buffer: "));
169 for (unsigned i
= 0; i
< recv_buf
.size(); i
++) {
170 D(fprintf(stderr
, "%c", recv_buf
[i
]));
172 D(fprintf(stderr
, "\n"));
176 void remote_bitbang_t::write()
178 if (send_buf
.empty())
181 while (!send_buf
.empty()) {
182 unsigned int count
= send_buf
.contiguous_data_size();
184 ssize_t bytes
= ::write(client_fd
, send_buf
.contiguous_data(), count
);
186 fprintf(stderr
, "failed to write to socket: %s (%d)\n", strerror(errno
), errno
);
188 } else if (bytes
== 0) {
189 // Client can't take any more data right now.
192 D(fprintf(stderr
, "wrote %zd bytes: ", bytes
));
193 for (int i
= 0; i
< bytes
; i
++) {
194 D(fprintf(stderr
, "%c", send_buf
[i
]));
196 D(fprintf(stderr
, "\n"));
197 send_buf
.consume(bytes
);
202 void remote_bitbang_t::tick()
213 void remote_bitbang_t::process_input()
215 for (unsigned i
= 0; i
< recv_buf
.size(); i
++) {
216 uint8_t command
= recv_buf
[i
];
219 case 'B': fprintf(stderr
, "*BLINK*\n"); break;
220 case 'b': fprintf(stderr
, "_______\n"); break;
221 case 'r': tap
.reset(); break;
222 case '0': tap
.set_pins(0, 0, 0); break;
223 case '1': tap
.set_pins(0, 0, 1); break;
224 case '2': tap
.set_pins(0, 1, 0); break;
225 case '3': tap
.set_pins(0, 1, 1); break;
226 case '4': tap
.set_pins(1, 0, 0); break;
227 case '5': tap
.set_pins(1, 0, 1); break;
228 case '6': tap
.set_pins(1, 1, 0); break;
229 case '7': tap
.set_pins(1, 1, 1); break;
230 case 'R': send_buf
.append(tap
.tdo() ? '1' : '0'); break;
232 fprintf(stderr
, "remote_bitbang got unsupported command '%c'\n", command
);