Rev 656 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6 | lvd | 1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
||
60 | chrv | 3 | |
4 | #include <util/delay.h> |
||
5 | |||
6 | lvd | 6 | #include "mytypes.h" |
126 | chrv | 7 | #include "main.h" |
6 | lvd | 8 | #include "ps2.h" |
9 | #include "zx.h" |
||
10 | #include "pins.h" |
||
11 | #include "spi.h" |
||
60 | chrv | 12 | #include "rs232.h" |
299 | chrv | 13 | #include "rtc.h" |
6 | lvd | 14 | |
179 | chrv | 15 | //if want Log than comment next string |
16 | #undef LOGENABLE |
||
17 | |||
60 | chrv | 18 | UBYTE ps2_decode(UBYTE count, UWORD shifter) |
19 | { |
||
20 | UBYTE t,byte; |
||
6 | lvd | 21 | |
60 | chrv | 22 | if( count!=0 ) return 0x00; // have nothing received |
6 | lvd | 23 | |
60 | chrv | 24 | // check packet: |
25 | //shifter.hi - stp.par.7.6.5.4.3.2 |
||
26 | //shifter.lo - 1.0.strt.x.x.x.x.x |
||
6 | lvd | 27 | |
60 | chrv | 28 | if( !( shifter&0x8000 ) ) return 0x00; // stopbit must be 1 |
29 | if( shifter&0x0020 ) return 0x00; // startbit must be 0 |
||
6 | lvd | 30 | |
31 | |||
60 | chrv | 32 | byte = (UBYTE) ( 0x00FF & (shifter>>6) ); |
6 | lvd | 33 | |
60 | chrv | 34 | t = byte ^ (byte>>4); |
35 | t = t ^ (t>>2); |
||
36 | t = t ^ (t>>1); // parity |
||
6 | lvd | 37 | |
60 | chrv | 38 | t = t ^ (UBYTE) ( shifter>>14 ); // compare parities |
6 | lvd | 39 | |
60 | chrv | 40 | if( !(t&1) ) return 0x00; // must be different |
6 | lvd | 41 | |
60 | chrv | 42 | return byte; |
6 | lvd | 43 | } |
44 | |||
60 | chrv | 45 | UWORD ps2_encode(UBYTE byte) |
6 | lvd | 46 | { |
60 | chrv | 47 | UWORD t; |
48 | t = byte ^ (byte>>4); |
||
49 | t = t ^ (t>>2); |
||
50 | t = ~(1 & (t ^ (t>>1))); // parity |
||
6 | lvd | 51 | |
60 | chrv | 52 | t = (((t<<8) + byte)<<1) + 0x0400; |
6 | lvd | 53 | |
60 | chrv | 54 | // prepare to shifter: |
55 | //shifter.hi - x.x.x.x.x.stp.par.7 |
||
56 | //shifter.lo - 6.5.4.3.2.1.0.strt |
||
57 | return t; |
||
58 | } |
||
6 | lvd | 59 | |
860 | lvd | 60 | volatile UBYTE ps2_was_release = 0; |
61 | volatile UBYTE ps2_was_E0 = 0; |
||
62 | volatile UBYTE ps2_last_scancode = 0; |
||
63 | volatile UBYTE ps2_last_scancode_E0 = 1; |
||
64 | volatile UBYTE ps2_skipshit = 0; |
||
65 | |||
60 | chrv | 66 | volatile UWORD ps2keyboard_shifter; |
67 | volatile UBYTE ps2keyboard_count; |
||
68 | volatile UBYTE ps2keyboard_timeout; |
||
149 | chrv | 69 | volatile UBYTE ps2keyboard_cmd_count; |
70 | volatile UBYTE ps2keyboard_cmd; |
||
6 | lvd | 71 | |
520 | chrv | 72 | volatile UBYTE ps2keyboard_log[16]; |
73 | volatile UBYTE ps2keyboard_log_start; |
||
74 | volatile UBYTE ps2keyboard_log_end; |
||
494 | chrv | 75 | |
860 | lvd | 76 | void ps2keyboard_init(void) |
77 | { |
||
78 | ps2keyboard_count = 12; |
||
79 | ps2keyboard_cmd_count = 0; |
||
80 | ps2keyboard_cmd = 0; |
||
81 | |||
82 | ps2_was_release = 0; |
||
83 | ps2_was_E0 = 0; |
||
84 | ps2_last_scancode = 0; |
||
85 | ps2_last_scancode_E0 = 1; |
||
86 | ps2_skipshit = 0; |
||
87 | } |
||
88 | |||
89 | |||
494 | chrv | 90 | void ps2keyboard_to_log(UBYTE data) |
91 | { |
||
520 | chrv | 92 | if( ps2keyboard_log_end != 0xFF ) |
494 | chrv | 93 | { |
520 | chrv | 94 | if( ps2keyboard_log_end == 0xFE ) |
95 | { |
||
96 | //first byte after reset |
||
97 | ps2keyboard_log_end = ps2keyboard_log_start; |
||
98 | } |
||
99 | |||
496 | chrv | 100 | #ifdef LOGENABLE |
101 | { |
||
102 | char log_ps2kb_parse[] = "LG<..:..\r\n"; |
||
520 | chrv | 103 | UBYTE b = ps2keyboard_log_end; |
496 | chrv | 104 | log_ps2kb_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
105 | log_ps2kb_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
106 | b = data; |
||
107 | log_ps2kb_parse[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
108 | log_ps2kb_parse[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
109 | to_log(log_ps2kb_parse); |
||
110 | } |
||
111 | #endif |
||
520 | chrv | 112 | ps2keyboard_log[ps2keyboard_log_end] = data; |
113 | ps2keyboard_log_end++; |
||
114 | if( ps2keyboard_log_end >= sizeof(ps2keyboard_log) ) |
||
115 | { |
||
116 | ps2keyboard_log_end = 0; |
||
117 | } |
||
118 | |||
119 | if( ps2keyboard_log_end == ps2keyboard_log_start ) |
||
120 | { |
||
121 | //overload |
||
122 | ps2keyboard_log_end = 0xFF; |
||
123 | } |
||
494 | chrv | 124 | } |
125 | } |
||
126 | |||
127 | UBYTE ps2keyboard_from_log(void) |
||
128 | { |
||
496 | chrv | 129 | UBYTE ret; |
520 | chrv | 130 | if( ps2keyboard_log_start == 0xFF ) |
494 | chrv | 131 | { |
520 | chrv | 132 | //reset state |
133 | return 0; |
||
134 | } |
||
135 | if( ps2keyboard_log_end<sizeof(ps2keyboard_log) ) |
||
136 | { |
||
137 | if( ps2keyboard_log_end != ps2keyboard_log_start ) |
||
138 | { |
||
139 | ret = ps2keyboard_log[ps2keyboard_log_start]; |
||
496 | chrv | 140 | #ifdef LOGENABLE |
141 | { |
||
142 | char log_ps2kb_parse[] = "LG>..:..\r\n"; |
||
143 | UBYTE b = ret; |
||
144 | log_ps2kb_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
145 | log_ps2kb_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
520 | chrv | 146 | b = ps2keyboard_log_start; |
496 | chrv | 147 | log_ps2kb_parse[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
148 | log_ps2kb_parse[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
149 | to_log(log_ps2kb_parse); |
||
150 | } |
||
151 | #endif |
||
520 | chrv | 152 | ps2keyboard_log_start++; |
153 | if( ps2keyboard_log_start >= sizeof(ps2keyboard_log) ) |
||
494 | chrv | 154 | { |
520 | chrv | 155 | ps2keyboard_log_start = 0; |
494 | chrv | 156 | } |
157 | } |
||
520 | chrv | 158 | else |
159 | { |
||
160 | ret=0; |
||
161 | } |
||
494 | chrv | 162 | } |
496 | chrv | 163 | else |
164 | { |
||
520 | chrv | 165 | ret = ps2keyboard_log_end; |
536 | chrv | 166 | if ( ret==0xFE ) |
167 | { |
||
168 | ret=0; |
||
169 | } |
||
170 | else |
||
171 | { |
||
172 | //after reading overload 'FF' - reset log |
||
173 | ps2keyboard_reset_log(); |
||
174 | } |
||
496 | chrv | 175 | } |
494 | chrv | 176 | //0 - no data, 0xFF - overload |
496 | chrv | 177 | return ret; |
494 | chrv | 178 | } |
179 | |||
180 | void ps2keyboard_reset_log(void) |
||
181 | { |
||
496 | chrv | 182 | #ifdef LOGENABLE |
520 | chrv | 183 | if( ps2keyboard_log_start!=0xFF ) |
496 | chrv | 184 | to_log("LGRESET\r\n"); |
185 | #endif |
||
520 | chrv | 186 | ps2keyboard_log_start = 0xFF; |
494 | chrv | 187 | } |
188 | |||
149 | chrv | 189 | static void ps2keyboard_release_clk(void) |
190 | { |
||
191 | ps2keyboard_count = 12; //counter reinit |
||
192 | if( flags_register & FLAG_PS2KEYBOARD_DIRECTION ) |
||
193 | { |
||
194 | PS2KBDAT_DDR &= ~(1<<PS2KBDAT); //ps2 keyboard data pin to input mode |
||
176 | chrv | 195 | flags_register &= ~(FLAG_PS2KEYBOARD_DIRECTION); //set to receive mode |
149 | chrv | 196 | } |
197 | |||
198 | //release ps2 receiver (disabled by now) |
||
199 | EIFR = (1<<INTF4); // clr any spurious int which can happen when we pulldown clock pin |
||
200 | PS2KBCLK_DDR &= ~(1<<PS2KBCLK); //ps2 keyboard clk pin to input mode |
||
201 | PS2KBCLK_PORT |= (1<<PS2KBCLK); //release clk pin |
||
202 | } |
||
203 | |||
204 | void ps2keyboard_send(UBYTE data) |
||
205 | { |
||
206 | #ifdef LOGENABLE |
||
207 | { |
||
208 | char log_ps2kb_parse[] = "KB>..\r\n"; |
||
209 | UBYTE b = data; |
||
210 | log_ps2kb_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
211 | log_ps2kb_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
212 | to_log(log_ps2kb_parse); |
||
213 | } |
||
214 | #endif |
||
215 | ps2keyboard_shifter = ps2_encode(data); //prepare data |
||
216 | flags_register |= FLAG_PS2KEYBOARD_DIRECTION; //set send mode |
||
217 | PS2KBCLK_PORT &= ~(1<<PS2KBCLK); //bring ps2 keyboard clk pin - |
||
218 | PS2KBCLK_DDR |= (1<<PS2KBCLK); //generate interruption |
||
219 | } |
||
220 | |||
60 | chrv | 221 | void ps2keyboard_task(void) |
222 | { |
||
149 | chrv | 223 | UBYTE b; |
6 | lvd | 224 | |
149 | chrv | 225 | if ( ( ps2keyboard_count == 12 ) && |
226 | ( ps2keyboard_cmd != 0) && |
||
227 | ( ps2keyboard_cmd_count != 0 ) ) |
||
228 | { |
||
229 | //delay need for pause between release and hold clk pin |
||
230 | _delay_us(100); |
||
6 | lvd | 231 | |
149 | chrv | 232 | //if need send command on current stage |
233 | if ( ((ps2keyboard_cmd_count == 4)&&(ps2keyboard_cmd == PS2KEYBOARD_CMD_SETLED)) || |
||
234 | ((ps2keyboard_cmd_count == 3)&&(ps2keyboard_cmd == PS2KEYBOARD_CMD_RESET)) ) |
||
235 | { |
||
236 | ps2keyboard_send(ps2keyboard_cmd); |
||
237 | ps2keyboard_cmd_count--; |
||
238 | } |
||
239 | else |
||
240 | //if need send led data on current stage |
||
241 | if ( ((ps2keyboard_cmd_count == 2)&&(ps2keyboard_cmd == PS2KEYBOARD_CMD_SETLED)) ) |
||
242 | { |
||
505 | chrv | 243 | b = (PS2KEYBOARD_LED_SCROLLOCK|PS2KEYBOARD_LED_NUMLOCK|PS2KEYBOARD_LED_CAPSLOCK)&modes_register; |
149 | chrv | 244 | ps2keyboard_send(b); |
245 | ps2keyboard_cmd_count--; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | if ( ( ps2keyboard_count<12 ) && |
||
250 | ( ps2keyboard_timeout==0 ) ) |
||
60 | chrv | 251 | { |
149 | chrv | 252 | //error due send/receive |
253 | ps2keyboard_release_clk(); |
||
254 | #ifdef LOGENABLE |
||
255 | to_log("KBerr\r\n"); |
||
256 | #endif |
||
257 | //TODO: ���� ������ |
||
656 | chrv | 258 | if ( ps2keyboard_cmd != PS2KEYBOARD_CMD_RESET ) |
259 | { |
||
260 | //set cmd RESET |
||
261 | ps2keyboard_cmd = PS2KEYBOARD_CMD_RESET; |
||
262 | ps2keyboard_cmd_count = 3; |
||
263 | } |
||
264 | else |
||
265 | { |
||
266 | //reset command |
||
267 | ps2keyboard_cmd = 0; |
||
268 | ps2keyboard_cmd_count = 0; |
||
269 | } |
||
151 | chrv | 270 | |
271 | //reset buffer |
||
272 | zx_clr_kb(); |
||
656 | chrv | 273 | |
274 | return; |
||
60 | chrv | 275 | } |
6 | lvd | 276 | |
149 | chrv | 277 | if ( ps2keyboard_count!=0 ) return; // not received anything |
6 | lvd | 278 | |
149 | chrv | 279 | if ( !(flags_register&FLAG_PS2KEYBOARD_DIRECTION) ) |
280 | { |
||
281 | //receive complete |
||
282 | b = ps2_decode(ps2keyboard_count, ps2keyboard_shifter); |
||
283 | #ifdef LOGENABLE |
||
284 | { |
||
285 | char log_ps2kb_parse[] = "KB<..\r\n"; |
||
286 | log_ps2kb_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
287 | log_ps2kb_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
288 | to_log(log_ps2kb_parse); |
||
6 | lvd | 289 | } |
149 | chrv | 290 | #endif |
291 | if ( ps2keyboard_cmd ) |
||
292 | { |
||
293 | //wait for 0xFA on current stage |
||
294 | if ( ((ps2keyboard_cmd == PS2KEYBOARD_CMD_SETLED)&&(ps2keyboard_cmd_count == 3 || ps2keyboard_cmd_count == 1)) || |
||
295 | ((ps2keyboard_cmd == PS2KEYBOARD_CMD_RESET)&&(ps2keyboard_cmd_count == 2)) ) |
||
296 | { |
||
151 | chrv | 297 | if( b != 0xFA ) |
298 | { |
||
299 | ps2keyboard_cmd_count = 0; |
||
300 | //if non FA - may be scan code received |
||
301 | if ( b ) ps2keyboard_parse(b); |
||
302 | } |
||
149 | chrv | 303 | else ps2keyboard_cmd_count--; |
6 | lvd | 304 | |
149 | chrv | 305 | if ( ps2keyboard_cmd_count == 0 ) ps2keyboard_cmd = 0; |
306 | } |
||
307 | else |
||
308 | //wait for 0xAA on current stage |
||
309 | if ( ((ps2keyboard_cmd == PS2KEYBOARD_CMD_RESET)&&(ps2keyboard_cmd_count == 1)) ) |
||
310 | { |
||
151 | chrv | 311 | if ( b != 0xAA ) |
312 | { |
||
313 | //if non AA - may be scan code received |
||
314 | if ( b ) ps2keyboard_parse(b); |
||
315 | } |
||
149 | chrv | 316 | ps2keyboard_cmd_count = 0; |
317 | ps2keyboard_cmd = 0; |
||
318 | } |
||
319 | } |
||
320 | else |
||
321 | if ( b ) // there is no zero byte in scancode tables so we can ignore and use it as 'nothing received' |
||
322 | { |
||
323 | ps2keyboard_parse(b); |
||
324 | } |
||
325 | } |
||
326 | |||
327 | ps2keyboard_release_clk(); |
||
328 | } |
||
329 | |||
330 | void ps2keyboard_send_cmd(UBYTE cmd) |
||
331 | { |
||
332 | if ( ps2keyboard_cmd == 0 ) |
||
333 | { |
||
334 | ps2keyboard_cmd = cmd; |
||
335 | switch ( cmd ) |
||
336 | { |
||
337 | case PS2KEYBOARD_CMD_RESET: |
||
338 | ps2keyboard_cmd_count = 3; |
||
339 | break; |
||
340 | case PS2KEYBOARD_CMD_SETLED: |
||
341 | ps2keyboard_cmd_count = 4; |
||
342 | break; |
||
343 | default: |
||
344 | ps2keyboard_cmd = 0; |
||
345 | } |
||
346 | } |
||
347 | } |
||
348 | |||
60 | chrv | 349 | void ps2keyboard_parse(UBYTE recbyte) |
6 | lvd | 350 | { |
351 | |||
60 | chrv | 352 | #ifdef LOGENABLE |
353 | char log_ps2keyboard_parse[] = "KB..\r\n"; |
||
860 | lvd | 354 | if ( ps2_skipshit ) log_ps2keyboard_parse[1] = ps2_skipshit + '0'; |
60 | chrv | 355 | log_ps2keyboard_parse[2] = ((recbyte >> 4) <= 9 )?'0'+(recbyte >> 4):'A'+(recbyte >> 4)-10; |
356 | log_ps2keyboard_parse[3] = ((recbyte & 0x0F) <= 9 )?'0'+(recbyte & 0x0F):'A'+(recbyte & 0x0F)-10; |
||
357 | to_log(log_ps2keyboard_parse); |
||
358 | #endif |
||
6 | lvd | 359 | |
494 | chrv | 360 | if( recbyte==0xFA ) return; |
361 | if( recbyte==0xFE ) return; |
||
362 | if( recbyte==0xEE ) return; |
||
363 | if( recbyte==0xAA ) return; |
||
6 | lvd | 364 | |
494 | chrv | 365 | //start write to log only for full key data |
860 | lvd | 366 | if( (recbyte!=0xE1) && (ps2_skipshit==0) ) //PAUSE not logged |
494 | chrv | 367 | { |
520 | chrv | 368 | if( ps2keyboard_log_start == 0xFF ) |
497 | chrv | 369 | { |
520 | chrv | 370 | //reseting log |
371 | ps2keyboard_log_end = 0xFE; |
||
372 | ps2keyboard_log_start = 0; |
||
373 | } |
||
860 | lvd | 374 | if( (ps2keyboard_log_end!=0xFE) || ((ps2_was_release==0) && (ps2_was_E0==0)/* && (ps2_skipshit==0)*/) ) |
520 | chrv | 375 | { |
497 | chrv | 376 | ps2keyboard_to_log(recbyte); |
377 | } |
||
494 | chrv | 378 | } |
379 | |||
860 | lvd | 380 | if( ps2_skipshit ) |
6 | lvd | 381 | { |
860 | lvd | 382 | ps2_skipshit--; |
6 | lvd | 383 | return; |
384 | } |
||
385 | |||
386 | if( recbyte==0xE0 ) |
||
387 | { |
||
860 | lvd | 388 | ps2_was_E0 = 1; |
6 | lvd | 389 | return; |
390 | } |
||
391 | |||
392 | |||
393 | if( recbyte==0xF0 ) |
||
394 | { |
||
860 | lvd | 395 | ps2_was_release = 1; |
6 | lvd | 396 | return; |
397 | } |
||
398 | |||
399 | if( recbyte==0xE1 ) // pause pressed |
||
400 | { |
||
860 | lvd | 401 | ps2_skipshit=7; |
6 | lvd | 402 | return; // skip next 7 bytes |
403 | } |
||
404 | |||
860 | lvd | 405 | if( (recbyte==ps2_last_scancode) && (ps2_was_E0==ps2_last_scancode_E0) ) |
6 | lvd | 406 | { |
860 | lvd | 407 | if( ps2_was_release ) |
6 | lvd | 408 | { |
860 | lvd | 409 | ps2_last_scancode = 0x00; |
410 | ps2_last_scancode_E0 = 1; // impossible scancode: E0 00 |
||
6 | lvd | 411 | } |
412 | else // was depress |
||
413 | { |
||
860 | lvd | 414 | ps2_was_E0 = 0; |
6 | lvd | 415 | return; |
416 | } |
||
417 | } |
||
418 | |||
860 | lvd | 419 | if( !ps2_was_release ) |
6 | lvd | 420 | { |
860 | lvd | 421 | ps2_last_scancode = recbyte; |
422 | ps2_last_scancode_E0 = ps2_was_E0; |
||
6 | lvd | 423 | } |
424 | |||
860 | lvd | 425 | if( (recbyte==0x12) && ps2_was_E0 ) // skip E0 12 |
6 | lvd | 426 | { |
860 | lvd | 427 | ps2_was_E0 = 0; |
428 | ps2_was_release = 0; |
||
6 | lvd | 429 | return; |
430 | } |
||
431 | |||
860 | lvd | 432 | to_zx( recbyte, ps2_was_E0, ps2_was_release ); // send valid scancode to zx decoding stage |
536 | chrv | 433 | #ifdef LOGENABLE |
434 | char log_ps2keyboard_parse2[] = "KB(..,.,.)\r\n"; |
||
435 | log_ps2keyboard_parse2[3] = ((recbyte >> 4) <= 9 )?'0'+(recbyte >> 4):'A'+(recbyte >> 4)-10; |
||
436 | log_ps2keyboard_parse2[4] = ((recbyte & 0x0F) <= 9 )?'0'+(recbyte & 0x0F):'A'+(recbyte & 0x0F)-10; |
||
860 | lvd | 437 | log_ps2keyboard_parse2[6] = (ps2_was_E0)?'1':'0'; |
438 | log_ps2keyboard_parse2[8] = (ps2_was_release)?'1':'0'; |
||
536 | chrv | 439 | to_log(log_ps2keyboard_parse2); |
440 | #endif |
||
6 | lvd | 441 | |
860 | lvd | 442 | ps2_was_E0 = 0; |
443 | ps2_was_release = 0; |
||
6 | lvd | 444 | |
445 | return; |
||
446 | } |
||
447 | |||
60 | chrv | 448 | volatile UWORD ps2mouse_shifter; |
449 | volatile UBYTE ps2mouse_count; |
||
450 | volatile UBYTE ps2mouse_timeout; |
||
451 | volatile UBYTE ps2mouse_initstep; |
||
452 | volatile UBYTE ps2mouse_resp_count; |
||
299 | chrv | 453 | volatile UBYTE ps2mouse_cmd; |
60 | chrv | 454 | |
299 | chrv | 455 | const UBYTE ps2mouse_init_sequence[] = |
60 | chrv | 456 | "\xFF" // |
457 | "\xFF" // reset |
||
458 | "\xFF" // |
||
459 | "\xF3\xC8" // set sample rate 200 | switch to |
||
460 | "\xF3\x64" // set sample rate 100 | scroll |
||
461 | "\xF3\x50" // set sample rate 80 | mode |
||
462 | "\xF2" // get device type |
||
656 | chrv | 463 | // "\xE8\x02" // set resolution to 4 count/mm |
60 | chrv | 464 | "\xE6" // set scaling 1:1 |
75 | chrv | 465 | "\xF3\x64" // set sample rate 100 |
60 | chrv | 466 | "\xF4" // enable |
467 | ; |
||
468 | |||
469 | static void ps2mouse_release_clk(void) |
||
470 | { |
||
471 | ps2mouse_count = 12; //counter reinit |
||
126 | chrv | 472 | if( flags_register & FLAG_PS2MOUSE_DIRECTION ) |
60 | chrv | 473 | { |
474 | PS2MSDAT_DDR &= ~(1<<PS2MSDAT); //ps2 mouse data pin to input mode |
||
176 | chrv | 475 | flags_register &= ~(FLAG_PS2MOUSE_DIRECTION); //set to receive mode |
60 | chrv | 476 | } |
477 | |||
478 | //release ps2 receiver (disabled by now) |
||
479 | EIFR = (1<<INTF5); // clr any spurious int which can happen when we pulldown clock pin |
||
480 | PS2MSCLK_DDR &= ~(1<<PS2MSCLK); //ps2 mouse clk pin to input mode |
||
481 | PS2MSCLK_PORT |= (1<<PS2MSCLK); //release clk pin |
||
482 | } |
||
483 | |||
484 | void ps2mouse_send(UBYTE data) |
||
485 | { |
||
299 | chrv | 486 | #ifdef LOGENABLE |
487 | { |
||
488 | UBYTE b=data; |
||
489 | char log_ps2mouse_parse[] = "MS>..\r\n"; |
||
490 | log_ps2mouse_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
491 | log_ps2mouse_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
492 | to_log(log_ps2mouse_parse); |
||
493 | } |
||
494 | #endif |
||
60 | chrv | 495 | ps2mouse_shifter = ps2_encode(data); //prepare data |
126 | chrv | 496 | flags_register |= FLAG_PS2MOUSE_DIRECTION; //set send mode |
60 | chrv | 497 | PS2MSCLK_PORT &= ~(1<<PS2MSCLK); //bring ps2 mouse clk pin - |
498 | PS2MSCLK_DDR |= (1<<PS2MSCLK); //generate interruption |
||
499 | } |
||
500 | |||
501 | void ps2mouse_task(void) |
||
502 | { |
||
149 | chrv | 503 | UBYTE b; |
60 | chrv | 504 | |
299 | chrv | 505 | if ( ps2mouse_count == 12 ) |
60 | chrv | 506 | { |
299 | chrv | 507 | if ( ps2mouse_init_sequence[ps2mouse_initstep] != 0 ) |
508 | { |
||
509 | if ( ps2mouse_resp_count == 0 ) |
||
510 | { |
||
511 | //delay need for pause between release and hold clk pin |
||
512 | _delay_us(200); |
||
75 | chrv | 513 | |
299 | chrv | 514 | //initialization not complete |
515 | //send next command to mouse |
||
516 | ps2mouse_send(ps2mouse_init_sequence[ps2mouse_initstep]); |
||
517 | ps2mouse_resp_count++; |
||
518 | } |
||
519 | } |
||
520 | else if ( ps2mouse_cmd != 0 ) |
||
521 | { |
||
522 | if ( ps2mouse_resp_count == 0 ) |
||
523 | { |
||
524 | //delay need for pause between release and hold clk pin |
||
525 | _delay_us(200); |
||
526 | |||
527 | //start command |
||
528 | flags_ex_register |= FLAG_EX_PS2MOUSE_CMD; |
||
529 | ps2mouse_send(ps2mouse_cmd); |
||
530 | ps2mouse_resp_count++; |
||
531 | } |
||
532 | else if( flags_ex_register & FLAG_EX_PS2MOUSE_CMD ) |
||
533 | { |
||
534 | switch( ps2mouse_cmd ) |
||
535 | { |
||
536 | case PS2MOUSE_CMD_SET_RESOLUTION: |
||
537 | if ( ps2mouse_resp_count == 2 ) |
||
538 | { |
||
539 | //delay need for pause between release and hold clk pin |
||
540 | _delay_us(200); |
||
541 | |||
542 | //send resolution |
||
410 | ddp | 543 | ps2mouse_send(rtc_read(RTC_PS2MOUSE_RES_REG)&0x03); |
299 | chrv | 544 | ps2mouse_resp_count++; |
545 | } |
||
546 | break; |
||
547 | } |
||
548 | } |
||
549 | } |
||
60 | chrv | 550 | } |
551 | |||
552 | if ( ( ps2mouse_count<12 ) && |
||
553 | ( ps2mouse_timeout==0 ) ) |
||
554 | { |
||
555 | #ifdef LOGENABLE |
||
182 | chrv | 556 | char log_ps2mouse_err[] = "MS.err.\r\n"; |
557 | if( flags_register&FLAG_PS2MOUSE_DIRECTION ) log_ps2mouse_err[2]='S'; else log_ps2mouse_err[2]='R'; |
||
558 | if( ps2mouse_count<10 ) log_ps2mouse_err[6]='0'+ps2mouse_count; else log_ps2mouse_err[6]='A'+ps2mouse_count-10; |
||
559 | to_log(log_ps2mouse_err); |
||
60 | chrv | 560 | #endif |
182 | chrv | 561 | //error due exchange data with PS/2 mouse |
75 | chrv | 562 | |
182 | chrv | 563 | //get direction |
564 | b = flags_register&FLAG_PS2MOUSE_DIRECTION; |
||
565 | |||
566 | //reset pins and states |
||
567 | ps2mouse_release_clk(); |
||
568 | |||
569 | //analizing error |
||
570 | if( b && (ps2mouse_initstep==0) ) |
||
571 | { |
||
572 | //error due send first init byte - mouse not connected to PS/2 |
||
573 | |||
574 | //disable mouse |
||
575 | zx_mouse_reset(0); |
||
576 | } |
||
577 | else |
||
578 | { |
||
579 | //error due receive or send non first byte - mouse connected to PS/2 |
||
580 | |||
581 | //re-init mouse |
||
582 | ps2mouse_initstep = 0; |
||
583 | } |
||
60 | chrv | 584 | } |
585 | |||
586 | if ( ps2mouse_count!=0 ) return; // not received anything |
||
587 | |||
126 | chrv | 588 | if ( !(flags_register&FLAG_PS2MOUSE_DIRECTION) ) |
60 | chrv | 589 | { |
590 | //receive complete |
||
149 | chrv | 591 | b = ps2_decode(ps2mouse_count, ps2mouse_shifter); |
60 | chrv | 592 | |
593 | #ifdef LOGENABLE |
||
594 | { |
||
595 | char log_ps2mouse_parse[] = "MS<..\r\n"; |
||
149 | chrv | 596 | log_ps2mouse_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
597 | log_ps2mouse_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
60 | chrv | 598 | to_log(log_ps2mouse_parse); |
599 | } |
||
600 | #endif |
||
601 | |||
299 | chrv | 602 | //if command proceed than command code |
603 | //if initialization proceed than current init code |
||
604 | //else 0 |
||
605 | switch( (flags_ex_register&FLAG_EX_PS2MOUSE_CMD)?ps2mouse_cmd:ps2mouse_init_sequence[ps2mouse_initstep] ) |
||
60 | chrv | 606 | { |
607 | //initialization complete - working mode |
||
608 | case 0: |
||
71 | chrv | 609 | ps2mouse_resp_count++; |
610 | switch( ps2mouse_resp_count ) |
||
611 | { |
||
612 | case 1: |
||
613 | //byte 1: Y overflow | X overflow | Y sign bit | X sign bit | 1 | Middle Btn | Right Btn | Left Btn |
||
149 | chrv | 614 | zx_mouse_button = (zx_mouse_button&0xF0) + ((b^0x07)&0x0F); |
71 | chrv | 615 | break; |
616 | case 2: |
||
617 | //byte 2: X movement |
||
149 | chrv | 618 | zx_mouse_x += b; |
71 | chrv | 619 | break; |
620 | case 3: |
||
621 | //byte 3: Y movement |
||
149 | chrv | 622 | zx_mouse_y += b; |
126 | chrv | 623 | if ( !(flags_register&FLAG_PS2MOUSE_TYPE) ) |
71 | chrv | 624 | { |
625 | //classical mouse |
||
626 | ps2mouse_resp_count = 0; |
||
126 | chrv | 627 | flags_register |= FLAG_PS2MOUSE_ZX_READY; |
71 | chrv | 628 | } |
629 | break; |
||
630 | case 4: |
||
631 | //byte 4: wheel movement |
||
149 | chrv | 632 | zx_mouse_button += ((b<<4)&0xF0); |
126 | chrv | 633 | flags_register |= FLAG_PS2MOUSE_ZX_READY; |
71 | chrv | 634 | ps2mouse_resp_count = 0; |
635 | } |
||
60 | chrv | 636 | break; |
637 | |||
638 | //reset command |
||
299 | chrv | 639 | case PS2MOUSE_CMD_RESET: |
60 | chrv | 640 | if ( ps2mouse_resp_count==1 ) |
641 | { |
||
642 | //must be acknowledge |
||
149 | chrv | 643 | if ( b != 0xFA ) |
60 | chrv | 644 | { |
299 | chrv | 645 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
646 | { |
||
647 | //reset command |
||
648 | ps2mouse_cmd = 0; |
||
649 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
||
650 | } |
||
651 | else |
||
652 | { |
||
653 | //reset initialization |
||
654 | ps2mouse_initstep = 0; |
||
655 | } |
||
60 | chrv | 656 | ps2mouse_resp_count = 0; |
657 | break; |
||
658 | } |
||
659 | } |
||
660 | ps2mouse_resp_count++; |
||
661 | if ( ps2mouse_resp_count >= 4 ) |
||
662 | { |
||
663 | ps2mouse_resp_count = 0; |
||
299 | chrv | 664 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
665 | { |
||
666 | //reset command |
||
667 | ps2mouse_cmd = 0; |
||
668 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
||
669 | } |
||
670 | else |
||
671 | { |
||
672 | //next initialization stage |
||
673 | ps2mouse_initstep++; |
||
674 | } |
||
60 | chrv | 675 | } |
676 | break; |
||
677 | |||
678 | //get device type |
||
299 | chrv | 679 | case PS2MOUSE_CMD_GET_TYPE: |
60 | chrv | 680 | if ( ps2mouse_resp_count==1 ) |
681 | { |
||
682 | ps2mouse_resp_count++; |
||
683 | //must be acknowledge |
||
149 | chrv | 684 | if ( b != 0xFA ) |
60 | chrv | 685 | { |
299 | chrv | 686 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
687 | { |
||
688 | //reset command |
||
689 | ps2mouse_cmd = 0; |
||
690 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
||
691 | } |
||
692 | else |
||
693 | { |
||
694 | //reset initialization |
||
695 | ps2mouse_initstep = 0; |
||
696 | } |
||
60 | chrv | 697 | ps2mouse_resp_count = 0; |
698 | } |
||
699 | break; |
||
700 | } |
||
701 | else |
||
702 | { |
||
703 | ps2mouse_resp_count = 0; |
||
299 | chrv | 704 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
705 | { |
||
706 | //reset command |
||
707 | ps2mouse_cmd = 0; |
||
708 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
||
709 | } |
||
710 | else |
||
711 | { |
||
712 | //next initialization stage |
||
713 | ps2mouse_initstep++; |
||
714 | } |
||
60 | chrv | 715 | |
149 | chrv | 716 | if ( b > 0 ) |
60 | chrv | 717 | { |
126 | chrv | 718 | flags_register |= FLAG_PS2MOUSE_TYPE; |
60 | chrv | 719 | } |
720 | else |
||
721 | { |
||
126 | chrv | 722 | flags_register &= ~(FLAG_PS2MOUSE_TYPE); |
60 | chrv | 723 | } |
724 | } |
||
725 | break; |
||
726 | |||
299 | chrv | 727 | //set resolution |
728 | case PS2MOUSE_CMD_SET_RESOLUTION: |
||
729 | //must be acknowledge |
||
730 | if ( b != 0xFA ) |
||
60 | chrv | 731 | { |
299 | chrv | 732 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
60 | chrv | 733 | { |
299 | chrv | 734 | //reset command |
735 | ps2mouse_cmd = 0; |
||
736 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
||
737 | } |
||
738 | else |
||
739 | { |
||
60 | chrv | 740 | //reset initialization |
741 | ps2mouse_initstep = 0; |
||
299 | chrv | 742 | } |
743 | ps2mouse_resp_count = 0; |
||
744 | } |
||
745 | else |
||
746 | { |
||
747 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
||
748 | { |
||
749 | if( ps2mouse_resp_count >= 3 ) |
||
750 | { |
||
751 | ps2mouse_resp_count = 0; |
||
752 | //reset command |
||
656 | chrv | 753 | //ps2mouse_cmd = 0; |
299 | chrv | 754 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
656 | chrv | 755 | |
756 | //WARNING! some mouses need enable command after changing resolution |
||
757 | ps2mouse_cmd = PS2MOUSE_CMD_ENABLE; |
||
299 | chrv | 758 | } |
759 | else |
||
760 | { |
||
761 | ps2mouse_resp_count ++; |
||
762 | } |
||
763 | } |
||
764 | else |
||
765 | { |
||
766 | //next initialization stage |
||
60 | chrv | 767 | ps2mouse_resp_count = 0; |
299 | chrv | 768 | ps2mouse_initstep++; |
60 | chrv | 769 | } |
770 | } |
||
299 | chrv | 771 | break; |
772 | |||
773 | //other commands |
||
774 | default: |
||
775 | if( flags_ex_register&FLAG_EX_PS2MOUSE_CMD ) |
||
776 | { |
||
777 | //reset command |
||
778 | ps2mouse_cmd = 0; |
||
779 | flags_ex_register &= ~FLAG_EX_PS2MOUSE_CMD; |
||
780 | } |
||
781 | else |
||
782 | { |
||
783 | //next initialization stage |
||
784 | ps2mouse_initstep++; |
||
785 | if ( ps2mouse_resp_count==1 ) |
||
786 | { |
||
787 | //must be acknowledge |
||
788 | if ( b != 0xFA ) |
||
789 | { |
||
790 | //reset initialization |
||
791 | ps2mouse_initstep = 0; |
||
792 | } |
||
793 | } |
||
794 | } |
||
60 | chrv | 795 | ps2mouse_resp_count = 0; |
796 | break; |
||
797 | } |
||
798 | } |
||
182 | chrv | 799 | //#ifdef LOGENABLE |
800 | // else |
||
801 | // { |
||
802 | // //send complete |
||
803 | // char log_ps2mouse_parse[] = "MS>..\r\n"; |
||
804 | // b = ps2mouse_init_sequence[ps2mouse_initstep]; |
||
805 | // log_ps2mouse_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
806 | // log_ps2mouse_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
807 | // to_log(log_ps2mouse_parse); |
||
808 | // } |
||
809 | //#endif |
||
60 | chrv | 810 | |
811 | ps2mouse_release_clk(); |
||
812 | } |
||
299 | chrv | 813 | |
814 | void ps2mouse_set_resolution(UBYTE code) |
||
815 | { |
||
816 | #ifdef LOGENABLE |
||
817 | { |
||
818 | UBYTE b = zx_mouse_button; |
||
819 | char log_ps2mouse_parse[] = "SS:..-..\r\n"; |
||
820 | log_ps2mouse_parse[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
821 | log_ps2mouse_parse[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
822 | b = code; |
||
823 | log_ps2mouse_parse[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10; |
||
824 | log_ps2mouse_parse[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10; |
||
825 | to_log(log_ps2mouse_parse); |
||
826 | } |
||
827 | #endif |
||
828 | |||
829 | //if pressed left and right buttons on mouse |
||
830 | if ( (zx_mouse_button & 0x03) == 0 ) |
||
831 | { |
||
832 | switch( code ) |
||
833 | { |
||
834 | //keypad '*' - set default resolution |
||
835 | case 0x7C: |
||
836 | rtc_write(RTC_PS2MOUSE_RES_REG,0x00); |
||
837 | ps2mouse_cmd = PS2MOUSE_CMD_SET_RESOLUTION; |
||
838 | break; |
||
839 | |||
840 | //keypad '+' - inc resolution |
||
841 | case 0x79: |
||
842 | { |
||
410 | ddp | 843 | UBYTE data = rtc_read(RTC_PS2MOUSE_RES_REG)&0x03; |
299 | chrv | 844 | if( data < 0x03 ) |
845 | { |
||
846 | data++; |
||
847 | } |
||
848 | rtc_write(RTC_PS2MOUSE_RES_REG,data); |
||
849 | ps2mouse_cmd = PS2MOUSE_CMD_SET_RESOLUTION; |
||
850 | break; |
||
851 | } |
||
852 | |||
853 | //keypad '-' - dec resolution |
||
854 | case 0x7B: |
||
855 | { |
||
410 | ddp | 856 | UBYTE data = rtc_read(RTC_PS2MOUSE_RES_REG)&0x03; |
857 | if (data) |
||
299 | chrv | 858 | { |
859 | data--; |
||
860 | } |
||
861 | rtc_write(RTC_PS2MOUSE_RES_REG,data); |
||
862 | ps2mouse_cmd = PS2MOUSE_CMD_SET_RESOLUTION; |
||
863 | break; |
||
864 | } |
||
865 | } |
||
866 | } |
||
867 | } |