minivmac4ios/Mini vMac/mnvm_core/KBRDEMDV.c
2019-05-03 21:21:30 +02:00

215 lines
4.5 KiB
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);
}
}
}
}