1 // Commander X16 Emulator
2 // Copyright (c) 2019 Michael Steil
3 // All rights reserved. License: 2-clause BSD
4
5 #include <stdio.h>
6 #include <stdbool.h>
7 #include "ps2.h"
8
9 #define HOLD 25 * 8 /* 25 x ~3 cycles at 8 MHz = 75µs */
10
11 #define PS2_BUFFER_SIZE 32
12
13 static struct {
14 bool sending;
15 bool has_byte;
16 uint8_t current_byte;
17 int bit_index;
18 int data_bits;
19 int send_state;
20 struct
21 {
22 uint8_t data[PS2_BUFFER_SIZE];
23 uint8_t read;
24 uint8_t write;
25 } buffer;
26 } state[2];
27
28 ps2_port_t ps2_port[2];
29
30 bool
ps2_buffer_can_fit(int i,int n)31 ps2_buffer_can_fit(int i, int n)
32 {
33 // Math is hard. There's certainly a way to do this without a loop.
34 for (int n2 = 1; n2 < n; n2++) {
35 if ((state[i].buffer.write + n2) % PS2_BUFFER_SIZE == state[i].buffer.read) {
36 return false;
37 }
38 }
39 return true;
40 }
41
42 void
ps2_buffer_add(int i,uint8_t byte)43 ps2_buffer_add(int i, uint8_t byte)
44 {
45 if (!ps2_buffer_can_fit(i, 1)) {
46 return;
47 }
48
49 state[i].buffer.data[state[i].buffer.write] = byte;
50 state[i].buffer.write = (state[i].buffer.write + 1) % PS2_BUFFER_SIZE;
51 }
52
53 int
ps2_buffer_remove(int i)54 ps2_buffer_remove(int i)
55 {
56 if (state[i].buffer.read == state[i].buffer.write) {
57 return -1; // empty
58 } else {
59 uint8_t byte = state[i].buffer.data[state[i].buffer.read];
60 state[i].buffer.read = (state[i].buffer.read + 1) % PS2_BUFFER_SIZE;
61 return byte;
62 }
63 }
64
65 void
ps2_step(int i)66 ps2_step(int i)
67 {
68 if (!ps2_port[i].clk_in && ps2_port[i].data_in) { // communication inhibited
69 ps2_port[i].clk_out = 0;
70 ps2_port[i].data_out = 0;
71 state[i].sending = false;
72 // printf("PS2[%d]: STATE: communication inhibited.\n", i);
73 return;
74 } else if (ps2_port[i].clk_in && ps2_port[i].data_in) { // idle state
75 // printf("PS2[%d]: STATE: idle\n", i);
76 if (!state[i].sending) {
77 // get next byte
78 if (!state[i].has_byte) {
79 int current_byte = ps2_buffer_remove(i);
80 if (current_byte < 0) {
81 // we have nothing to send
82 ps2_port[i].clk_out = 1;
83 ps2_port[i].data_out = 0;
84 // printf("PS2[%d]: nothing to send.\n", i);
85 return;
86 }
87 state[i].current_byte = current_byte;
88 // printf("PS2[%d]: current_byte: %x\n", i, state[i].current_byte);
89 state[i].has_byte = true;
90 }
91
92 state[i].data_bits = state[i].current_byte << 1 | (1 - __builtin_parity(state[i].current_byte)) << 9 | (1 << 10);
93 // printf("PS2[%d]: data_bits: %x\n", i, state[i].data_bits);
94 state[i].bit_index = 0;
95 state[i].send_state = 0;
96 state[i].sending = true;
97 }
98
99 if (state[i].send_state <= HOLD) {
100 ps2_port[i].clk_out = 0; // data ready
101 ps2_port[i].data_out = state[i].data_bits & 1;
102 // printf("PS2[%d]: [%d]sending #%d: %x\n", i, state[i].send_state, state[i].bit_index, state[i].data_bits & 1);
103 if (state[i].send_state == 0 && state[i].bit_index == 10) {
104 // we have sent the last bit, if the host
105 // inhibits now, we'll send the next byte
106 state[i].has_byte = false;
107 }
108 if (state[i].send_state == HOLD) {
109 state[i].data_bits >>= 1;
110 state[i].bit_index++;
111 }
112 state[i].send_state++;
113 } else if (state[i].send_state <= 2 * HOLD) {
114 // printf("PS2[%d]: [%d]not ready\n", i, state[i].send_state);
115 ps2_port[i].clk_out = 1; // not ready
116 ps2_port[i].data_out = 0;
117 if (state[i].send_state == 2 * HOLD) {
118 // printf("XXX bit_index: %d\n", state[i].bit_index);
119 if (state[i].bit_index < 11) {
120 state[i].send_state = 0;
121 } else {
122 state[i].sending = false;
123 }
124 }
125 if (state[i].send_state) {
126 state[i].send_state++;
127 }
128 }
129 } else {
130 // printf("PS2[%d]: Warning: unknown PS/2 bus state: CLK_IN=%d, DATA_IN=%d\n", i, ps2_port[i].clk_in, ps2_port[i].data_in);
131 ps2_port[i].clk_out = 0;
132 ps2_port[i].data_out = 0;
133 }
134 }
135
136 // fake mouse
137
138 static uint8_t buttons;
139 static int16_t mouse_diff_x = 0;
140 static int16_t mouse_diff_y = 0;
141
142 // byte 0, bit 7: Y overflow
143 // byte 0, bit 6: X overflow
144 // byte 0, bit 5: Y sign bit
145 // byte 0, bit 4: X sign bit
146 // byte 0, bit 3: Always 1
147 // byte 0, bit 2: Middle Btn
148 // byte 0, bit 1: Right Btn
149 // byte 0, bit 0: Left Btn
150 // byte 2: X Movement
151 // byte 3: Y Movement
152
153
154 static bool
mouse_send(int x,int y,int b)155 mouse_send(int x, int y, int b)
156 {
157 if (ps2_buffer_can_fit(1, 3)) {
158 uint8_t byte0 =
159 ((y >> 9) & 1) << 5 |
160 ((x >> 9) & 1) << 4 |
161 1 << 3 |
162 b;
163 uint8_t byte1 = x;
164 uint8_t byte2 = y;
165 // printf("%02X %02X %02X\n", byte0, byte1, byte2);
166
167 ps2_buffer_add(1, byte0);
168 ps2_buffer_add(1, byte1);
169 ps2_buffer_add(1, byte2);
170
171 return true;
172 } else {
173 // printf("buffer full, skipping...\n");
174 return false;
175 }
176 }
177
178 void
mouse_send_state()179 mouse_send_state()
180 {
181 if (mouse_diff_x > 255) {
182 mouse_send(255, 0, buttons);
183 mouse_diff_x -= 255;
184 }
185 if (mouse_diff_x < -256) {
186 mouse_send(-256, 0, buttons);
187 mouse_diff_x -= -256;
188 }
189 if (mouse_diff_y > 255) {
190 mouse_send(0, 255, buttons);
191 mouse_diff_y -= 255;
192 }
193 if (mouse_diff_y < -256) {
194 mouse_send(0, -256, buttons);
195 mouse_diff_y -= -256;
196 }
197 if (mouse_send(mouse_diff_x, mouse_diff_y, buttons)) {
198 mouse_diff_x = 0;
199 mouse_diff_y = 0;
200 }
201 }
202
203
204 void
mouse_button_down(int num)205 mouse_button_down(int num)
206 {
207 buttons |= 1 << num;
208 mouse_send_state();
209 }
210
211 void
mouse_button_up(int num)212 mouse_button_up(int num)
213 {
214 buttons &= (1 << num) ^ 0xff;
215 mouse_send_state();
216 }
217
218 void
mouse_move(int x,int y)219 mouse_move(int x, int y)
220 {
221 mouse_diff_x += x;
222 mouse_diff_y += y;
223 mouse_send_state();
224 }
225
226 uint8_t
mouse_read(uint8_t reg)227 mouse_read(uint8_t reg)
228 {
229 return 0xff;
230 }
231
232