saturnng/keyb.c
2022-03-21 11:05:59 +01:00

341 lines
7.7 KiB
C

/* -------------------------------------------------------------------------
saturn - A poor-man's emulator of some HP calculators
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the documentation of this program; if not, write to
the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
For more information, please contact the author, preferably by email,
at the following address:
Ivan Cibrario Bertolotti
IRITI - National Research Council
c/o IEN "Galileo Ferraris"
Strada delle Cacce, 91
10135 - Torino (ITALY)
email: cibrario@iriti.cnr.it
------------------------------------------------------------------------- */
/* +-+ */
/* .+
.identifier : $Id: keyb.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
.context : SATURN, Saturn CPU / HP48 emulator
.title : $RCSfile: keyb.c,v $
.kind : C source
.author : Ivan Cibrario B.
.site : CSTV-CNR
.creation : 29-Jan-1998
.keywords : *
.description :
This module emulates the keyboard interface of the Yorke chip.
References:
SASM.DOC by HP (HORN disk 4)
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
x48 source code by Eddie C. Dost (ecd@dressler.de)
NOTE: In the current (r1.1) implementation,
the emulation accuracy could be poor.
.include : config.h, machdep.h, cpu.h, modules.h, keyb.h
.notes :
$Log: keyb.c,v $
Revision 4.1 2000/12/11 09:54:19 cibrario
Public release.
Revision 3.13 2000/11/09 11:32:49 cibrario
Revised to add file selection box GUI element, CPU halt/run
requests and emulator's extended functions:
- Implemented KeybReset()
Revision 3.10 2000/10/24 16:14:44 cibrario
Added/Replaced GPL header
Revision 2.1 2000/09/08 15:17:32 cibrario
Deep revision to accommodate the new GUI: all facilities to map a
key code (enum Key) into an IN/OUT pair have been removed,
because the GUI now does this function itself; KeybPress() and
KeybRelease() now directly accept an IN/OUT pair as input.
* Revision 1.1 1998/02/17 11:53:23 cibrario
* Initial revision
*
.- */
#ifndef lint
static char rcs_id[] = "$Id: keyb.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include "config.h"
#include "machdep.h"
#include "cpu.h"
#include "modules.h"
#include "keyb.h"
#include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h>
#define OUT_BITS 12
/* cur_in:
This array contains the current value the CPU IN register will assume
for each bit set in the OUT register.
*/
static InputRegister cur_in[OUT_BITS];
/* .+
.title : KeybRSI
.kind : C function
.creation : 11-Feb-1998
.description :
This function is called by the CPU emulator when the RSI instruction is
executed. It resets the keyboard interrupt system and posts a maskable
interrupt request if any key is pressed.
NOTE: This function currently (r1.1) always posts an IRQ request; perhaps,
if the ON key is down, a NMI request should be posted instead.
.call :
KeybRSI();
.input :
void
.output :
void
.status_codes :
*
.notes :
1.1, 17-Feb-1998, creation
.- */
void KeybRSI(void)
{
/* Post an IRQ if the IN register is not zero */
CpuIntRequest(KeybIN((OutputRegister)0x1FF) != (InputRegister)0 ?
INT_REQUEST_IRQ : INT_REQUEST_NONE);
}
/* .+
.title : KeybIn
.kind : C function
.creation : 11-Feb-1998
.description :
This function is called by the CPU emulator when either a C=IN or a A=IN
instruction is executed. It scans the keyboard and returns the current
value of the IN register for the given value of the OUT reguster.
.call :
in = KeybIN(out);
.input :
OutputRegister out, current value of the OUT register
.output :
InputRegister in, computed value of the IN register
.status_codes :
*
.notes :
1.1, 17-Feb-1998, creation
.- */
InputRegister KeybIN(OutputRegister out)
{
/* Compute the current value of the IN register */
InputRegister in = (InputRegister)0;
int bit;
/* For each bit set in the 'out' register, OR the corresponding IN register
value into 'in'
*/
for(bit=0; bit<OUT_BITS; bit++)
{
if(out & 0x01) in |= cur_in[bit];
out >>= 1;
}
return in;
}
/* .+
.title : KeybPress
.kind : C function
.creation : 11-Feb-1998
.description :
This function tells to the keyboard emulator that key 'key' has been
pressed. It updates the internal keyboard status information and, if
necessary, posts an interrupt request to the CPU.
.call :
KeybPress(key);
.input :
const char *key, identifies the key that has been pressed.
.output :
void
.status_codes :
MOD_W_BAD_KEY
MOD_W_BAD_OUT_BIT
.notes :
1.1, 17-Feb-1998, creation
2.1, 6-Sep-2000,
deeply revised to accomodate the new GUI
.- */
void KeybPress(const char *key)
{
if(strcmp(key, "*") == 0)
{
/* This is the ON key */
int i;
/* Set all 0x8000 lines */
for(i=0; i<OUT_BITS; i++) cur_in[i] |= 0x8000;
/* Post an interrupt request to the CPU */
CpuIntRequest(INT_REQUEST_NMI);
}
else
{
int in_val, out_bit;
if(sscanf(key, "%x/%x", &out_bit, &in_val) != 2)
{
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
ChfSignal();
}
else if(out_bit < 0 || out_bit >= OUT_BITS)
{
ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd;
ChfSignal();
}
else
{
/* Update the cur_in array */
cur_in[out_bit] |= in_val;
/* Post an interrupt request to the CPU */
CpuIntRequest(INT_REQUEST_NMI);
}
}
}
/* .+
.title : KeybRelease
.kind : C function
.creation : 11-Feb-1998
.description :
This function tells to the keyboard emulator that key 'key' has been
released. It updates the internal keyboard status information.
.call :
KeybRelease(key);
.input :
const char *key, identifies the key that has been released.
.output :
void
.status_codes :
MOD_W_BAD_KEY
MOD_W_BAD_OUT_BIT
.notes :
1.1, 17-Feb-1998, creation
2.1, 6-Sep-2000,
deeply revised to accomodate the new GUI
.- */
void KeybRelease(const char *key)
{
if(strcmp(key, "*") == 0)
{
/* This is the ON key */
int i;
/* Reset all 0x8000 lines */
for(i=0; i<OUT_BITS; i++) cur_in[i] &= 0x7FFF;
}
else
{
int in_val, out_bit;
if(sscanf(key, "%x/%x", &out_bit, &in_val) != 2)
{
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
ChfSignal();
}
else if(out_bit < 0 || out_bit >= OUT_BITS)
{
ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd;
ChfSignal();
}
else
{
/* Update the cur_in array */
cur_in[out_bit] &= ~in_val;
}
}
}
/* .+
.title : KeybReset
.kind : C function
.creation : 7-Nov-2000
.description :
This function resets the emulated keyboard; all keys are released.
.call :
KeybReset();
.input :
void
.output :
void
.status_codes :
.notes :
3.13, 7-Nov-2000, creation
.- */
void KeybReset(void)
{
int i;
/* Reset all 0x8000 lines */
for(i=0; i<OUT_BITS; i++) cur_in[i] = 0;
}