ref: d311c8e87038a48dc4162df0e2821c04dc0f6fa3
dir: /src/KBRDEMDV.c/
/* KBRDEMDV.c Copyright (C) 2006 Philip Cummins, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* KeyBoaRD EMulated DeVice Emulation of the keyboard in the Mac Plus. This code adapted from "Keyboard.c" in vMac by Philip Cummins. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #endif #include "KBRDEMDV.h" #ifdef _VIA_Debug #include <stdio.h> #endif /* ReportAbnormalID unused 0x0B03 - 0x0BFF */ IMPORTPROC KYBD_ShiftOutData(ui3b v); IMPORTFUNC ui3b KYBD_ShiftInData(void); enum { kKybdStateIdle, kKybdStateRecievingCommand, kKybdStateRecievedCommand, kKybdStateRecievingEndCommand, kKybdStates }; LOCALVAR int KybdState = kKybdStateIdle; LOCALVAR blnr HaveKeyBoardResult = falseblnr; LOCALVAR ui3b KeyBoardResult; LOCALPROC GotKeyBoardData(ui3b v) { if (KybdState != kKybdStateIdle) { HaveKeyBoardResult = trueblnr; KeyBoardResult = v; } else { KYBD_ShiftOutData(v); VIA1_iCB2 = 1; } } LOCALVAR ui3b InstantCommandData = 0x7B; LOCALFUNC blnr AttemptToFinishInquiry(void) { int i; blnr KeyDown; ui3b Keyboard_Data; if (FindKeyEvent(&i, &KeyDown)) { if (i < 64) { Keyboard_Data = i << 1; if (! KeyDown) { Keyboard_Data += 128; } } else { Keyboard_Data = 121; InstantCommandData = (i - 64) << 1; if (! KeyDown) { InstantCommandData += 128; } } GotKeyBoardData(Keyboard_Data); return trueblnr; } else { return falseblnr; } } #define MaxKeyboardWait 16 /* in 60ths of a second */ /* Code in the mac rom will reset the keyboard if it hasn't been heard from in 32/60th of a second. So time out and send something before that to keep connection. */ LOCALVAR int InquiryCommandTimer = 0; GLOBALPROC DoKybd_ReceiveCommand(void) { if (KybdState != kKybdStateRecievingCommand) { ReportAbnormalID(0x0B01, "KybdState != kKybdStateRecievingCommand"); } else { ui3b in = KYBD_ShiftInData(); KybdState = kKybdStateRecievedCommand; switch (in) { case 0x10 : /* Inquiry Command */ if (! AttemptToFinishInquiry()) { InquiryCommandTimer = MaxKeyboardWait; } break; case 0x14 : /* Instant Command */ GotKeyBoardData(InstantCommandData); InstantCommandData = 0x7B; break; case 0x16 : /* Model Command */ GotKeyBoardData(0x0b /* 0x01 */); /* Test value, means Model 0, no extra devices */ /* Fixed by Hoshi Takanori - it uses the proper keyboard type now */ break; case 0x36 : /* Test Command */ GotKeyBoardData(0x7D); break; case 0x00: GotKeyBoardData(0); break; default : /* Debugger(); */ GotKeyBoardData(0); break; } } } GLOBALPROC DoKybd_ReceiveEndCommand(void) { if (KybdState != kKybdStateRecievingEndCommand) { ReportAbnormalID(0x0B02, "KybdState != kKybdStateRecievingEndCommand"); } else { KybdState = kKybdStateIdle; #ifdef _VIA_Debug fprintf(stderr, "enter DoKybd_ReceiveEndCommand\n"); #endif if (HaveKeyBoardResult) { #ifdef _VIA_Debug fprintf(stderr, "HaveKeyBoardResult: %d\n", KeyBoardResult); #endif HaveKeyBoardResult = falseblnr; KYBD_ShiftOutData(KeyBoardResult); VIA1_iCB2 = 1; } } } GLOBALPROC Kybd_DataLineChngNtfy(void) { switch (KybdState) { case kKybdStateIdle: if (VIA1_iCB2 == 0) { KybdState = kKybdStateRecievingCommand; #ifdef _VIA_Debug fprintf(stderr, "posting kICT_Kybd_ReceiveCommand\n"); #endif ICT_add(kICT_Kybd_ReceiveCommand, 6800UL * kCycleScale / 64 * kMyClockMult); if (InquiryCommandTimer != 0) { InquiryCommandTimer = 0; /* abort Inquiry */ } } break; case kKybdStateRecievedCommand: if (VIA1_iCB2 == 1) { KybdState = kKybdStateRecievingEndCommand; #ifdef _VIA_Debug fprintf(stderr, "posting kICT_Kybd_ReceiveEndCommand\n"); #endif ICT_add(kICT_Kybd_ReceiveEndCommand, 6800UL * kCycleScale / 64 * kMyClockMult); } break; } } GLOBALPROC KeyBoard_Update(void) { if (InquiryCommandTimer != 0) { if (AttemptToFinishInquiry()) { InquiryCommandTimer = 0; } else { --InquiryCommandTimer; if (InquiryCommandTimer == 0) { GotKeyBoardData(0x7B); } } } }