2016-05-28 12:18:59 +00:00
|
|
|
/*
|
|
|
|
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
|
|
|
|
|
|
|
|
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) {
|
|
|
|
ReportAbnormal("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) {
|
|
|
|
ReportAbnormal("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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|