mirror of
https://github.com/mist-devel/mist-firmware.git
synced 2026-04-25 03:55:33 +00:00
ACSI and ikbd improvements
This commit is contained in:
2
Makefile
2
Makefile
@@ -8,7 +8,7 @@ DUMP = $(BASE)-objdump
|
||||
TODAY = `date +"%m/%d/%y"`
|
||||
|
||||
PRJ = firmware
|
||||
SRC = Cstartup_SAM7.c fat.c fdd.c firmware.c fpga.c hardware.c hdd.c main.c menu.c mmc.c osd.c syscalls.c user_io.c boot_print.c boot_logo.c rafile.c config.c tos.c
|
||||
SRC = Cstartup_SAM7.c fat.c fdd.c firmware.c fpga.c hardware.c hdd.c main.c menu.c mmc.c osd.c syscalls.c user_io.c boot_print.c boot_logo.c rafile.c config.c tos.c ikbd.c
|
||||
SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/timer.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
|
||||
313
ikbd.c
Normal file
313
ikbd.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
|
||||
https://www.kernel.org/doc/Documentation/input/atarikbd.txt
|
||||
|
||||
ikbd ToDo:
|
||||
|
||||
Feature Example using/needing it impl. tested
|
||||
---------------------------------------------------------------------
|
||||
mouse y at bottom Bolo X X
|
||||
mouse button key events Goldrunner/A_008 X X
|
||||
joystick interrogation mode Xevious/A_004 X X
|
||||
Absolute mouse mode Backlash/A_008, A-Ball/A50
|
||||
disable mouse ? X
|
||||
disable joystick ? X
|
||||
Joysticks also generate Goldrunner X X
|
||||
mouse button events!
|
||||
Pause (cmd 0x13) Wings of Death/A_427
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "user_io.h"
|
||||
#include "hardware.h"
|
||||
#include "ikbd.h"
|
||||
|
||||
// atari ikbd stuff
|
||||
#define IKBD_STATE_JOYSTICK_EVENT_REPORTING 0x01
|
||||
#define IKBD_STATE_MOUSE_Y_BOTTOM 0x02
|
||||
#define IKBD_STATE_MOUSE_BUTTON_AS_KEY 0x04 // mouse buttons act like keys
|
||||
#define IKBD_STATE_MOUSE_DISABLED 0x08
|
||||
#define IKBD_STATE_MOUSE_ABSOLUTE 0x10
|
||||
|
||||
#define IKBD_DEFAULT IKBD_STATE_JOYSTICK_EVENT_REPORTING
|
||||
|
||||
#define QUEUE_LEN 16 // power of 2!
|
||||
static unsigned char tx_queue[QUEUE_LEN];
|
||||
static unsigned char wptr = 0, rptr = 0;
|
||||
|
||||
// structure to keep track of ikbd state
|
||||
static struct {
|
||||
unsigned char cmd;
|
||||
unsigned char state;
|
||||
unsigned char expect;
|
||||
|
||||
// joystick state
|
||||
unsigned char joystick[2];
|
||||
|
||||
// mouse state
|
||||
unsigned short mouse_pos_x, mouse_pos_y;
|
||||
unsigned char mouse_buttons;
|
||||
} ikbd;
|
||||
|
||||
// #define IKBD_DEBUG
|
||||
|
||||
void ikbd_init() {
|
||||
// reset ikbd state
|
||||
memset(&ikbd, 0, sizeof(ikbd));
|
||||
ikbd.state = IKBD_DEFAULT;
|
||||
}
|
||||
|
||||
static void enqueue(unsigned char b) {
|
||||
if(((wptr + 1)&(QUEUE_LEN-1)) == rptr) {
|
||||
iprintf("IKBD: !!!!!!! tx queue overflow !!!!!!!!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tx_queue[wptr] = b;
|
||||
wptr = (wptr+1)&(QUEUE_LEN-1);
|
||||
}
|
||||
|
||||
// convert internal joystick format into atari ikbd format
|
||||
static unsigned char joystick_map2ikbd(unsigned in) {
|
||||
unsigned char out = 0;
|
||||
|
||||
if(in & JOY_UP) out |= 0x01;
|
||||
if(in & JOY_DOWN) out |= 0x02;
|
||||
if(in & JOY_LEFT) out |= 0x04;
|
||||
if(in & JOY_RIGHT) out |= 0x08;
|
||||
if(in & JOY_BTN1) out |= 0x80;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// process inout from atari core into ikbd
|
||||
void ikbd_handle_input(unsigned char cmd) {
|
||||
// expecting a second byte for command
|
||||
if(ikbd.expect) {
|
||||
ikbd.expect--;
|
||||
|
||||
// last byte of command received
|
||||
if(!ikbd.expect) {
|
||||
switch(ikbd.cmd) {
|
||||
case 0x07: // set mouse button action
|
||||
iprintf("IKBD: mouse button action = %x\n", cmd);
|
||||
|
||||
// bit 2: Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75)
|
||||
if(cmd & 0x04) ikbd.state |= IKBD_STATE_MOUSE_BUTTON_AS_KEY;
|
||||
else ikbd.state &= ~IKBD_STATE_MOUSE_BUTTON_AS_KEY;
|
||||
|
||||
break;
|
||||
|
||||
case 0x80: // ibkd reset
|
||||
// reply "everything is ok"
|
||||
enqueue(0xf0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ikbd.cmd = cmd;
|
||||
|
||||
switch(cmd) {
|
||||
case 0x07:
|
||||
puts("IKBD: Set mouse button action");
|
||||
ikbd.expect = 1;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
puts("IKBD: Set relative mouse positioning");
|
||||
ikbd.state &= ~IKBD_STATE_MOUSE_DISABLED;
|
||||
ikbd.state &= ~IKBD_STATE_MOUSE_ABSOLUTE;
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
puts("IKBD: Set absolute mouse positioning");
|
||||
ikbd.state &= ~IKBD_STATE_MOUSE_DISABLED;
|
||||
ikbd.state |= IKBD_STATE_MOUSE_ABSOLUTE;
|
||||
ikbd.expect = 4;
|
||||
break;
|
||||
|
||||
case 0x0b:
|
||||
puts("IKBD: Set Mouse threshold");
|
||||
ikbd.expect = 2;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
puts("IKBD: Set Y at bottom");
|
||||
ikbd.state |= IKBD_STATE_MOUSE_Y_BOTTOM;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
puts("IKBD: Set Y at top");
|
||||
ikbd.state &= ~IKBD_STATE_MOUSE_Y_BOTTOM;
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
puts("IKBD: Disable mouse");
|
||||
ikbd.state |= IKBD_STATE_MOUSE_DISABLED;
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
puts("IKBD: Set Joystick event reporting");
|
||||
ikbd.state |= IKBD_STATE_JOYSTICK_EVENT_REPORTING;
|
||||
break;
|
||||
|
||||
case 0x15:
|
||||
puts("IKBD: Set Joystick interrogation mode");
|
||||
ikbd.state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
|
||||
break;
|
||||
|
||||
case 0x16: // interrogate joystick
|
||||
// send reply
|
||||
enqueue(0xfd);
|
||||
enqueue(joystick_map2ikbd(ikbd.joystick[0]));
|
||||
enqueue(joystick_map2ikbd(ikbd.joystick[1]));
|
||||
break;
|
||||
|
||||
case 0x1a:
|
||||
puts("IKBD: Disable joysticks");
|
||||
ikbd.state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
|
||||
break;
|
||||
|
||||
case 0x1c:
|
||||
puts("IKBD: Interrogate time of day");
|
||||
|
||||
enqueue(0xfc);
|
||||
enqueue(0x13); // year bcd
|
||||
enqueue(0x03); // month bcd
|
||||
enqueue(0x07); // day bcd
|
||||
enqueue(0x20); // hour bcd
|
||||
enqueue(0x58); // minute bcd
|
||||
enqueue(0x00); // second bcd
|
||||
break;
|
||||
|
||||
|
||||
case 0x80:
|
||||
puts("IKBD: Reset");
|
||||
ikbd.expect = 1;
|
||||
ikbd.state = IKBD_DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
iprintf("IKBD: unknown command: %x\n", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ikbd_poll(void) {
|
||||
static mtimer = 0;
|
||||
if(CheckTimer(mtimer)) {
|
||||
mtimer = GetTimer(10);
|
||||
|
||||
// check for incoming ikbd data
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_IN);
|
||||
|
||||
while(SPI(0))
|
||||
ikbd_handle_input(SPI(0));
|
||||
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
// send data from queue if present
|
||||
if(rptr == wptr) return;
|
||||
|
||||
// transmit data from queue
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_OUT);
|
||||
SPI(tx_queue[rptr]);
|
||||
DisableIO();
|
||||
|
||||
rptr = (rptr+1)&(QUEUE_LEN-1);
|
||||
}
|
||||
|
||||
void ikbd_joystick(unsigned char joystick, unsigned char map) {
|
||||
// todo: suppress events for joystick 0 as long as mouse
|
||||
// is enabled?
|
||||
|
||||
if(ikbd.state & IKBD_STATE_JOYSTICK_EVENT_REPORTING) {
|
||||
#ifdef IKBD_DEBUG
|
||||
iprintf("IKBD: joy %d %x\n", joystick, map);
|
||||
#endif
|
||||
|
||||
// only report joystick data for joystick 0 if the mouse is disabled
|
||||
if((ikbd.state & IKBD_STATE_MOUSE_DISABLED) || (joystick == 1)) {
|
||||
enqueue(0xfe + joystick);
|
||||
enqueue(joystick_map2ikbd(map));
|
||||
}
|
||||
|
||||
if(!(ikbd.state & IKBD_STATE_MOUSE_DISABLED)) {
|
||||
// the fire button also generates a mouse event if
|
||||
// mouse reporting is enabled
|
||||
if((map & JOY_BTN1) != (ikbd.joystick[joystick] & JOY_BTN1)) {
|
||||
// generate mouse event (ikbd_joystick_buttons is evaluated inside
|
||||
// user_io_mouse)
|
||||
ikbd.joystick[joystick] = map;
|
||||
ikbd_mouse(0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef IKBD_DEBUG
|
||||
else
|
||||
iprintf("IKBD: no monitor, drop joy %d %x\n", joystick, map);
|
||||
#endif
|
||||
|
||||
// save state of joystick for interrogation mode
|
||||
ikbd.joystick[joystick] = map;
|
||||
}
|
||||
|
||||
void ikbd_keyboard(unsigned char code) {
|
||||
#ifdef IKBD_DEBUG
|
||||
iprintf("IKBD: send keycode %x%s\n", code&0x7f, (code&0x80)?" BREAK":"");
|
||||
#endif
|
||||
enqueue(code);
|
||||
}
|
||||
|
||||
void ikbd_mouse(unsigned char b, char x, char y) {
|
||||
if(ikbd.state & IKBD_STATE_MOUSE_DISABLED)
|
||||
return;
|
||||
|
||||
// joystick and mouse buttons are wired together in
|
||||
// atari st
|
||||
b |= (ikbd.joystick[0] & JOY_BTN1)?1:0;
|
||||
b |= (ikbd.joystick[1] & JOY_BTN1)?2:0;
|
||||
|
||||
static unsigned char b_old = 0;
|
||||
// monitor state of two mouse buttons
|
||||
if(b != b_old) {
|
||||
// check if mouse buttons are supposed to be treated like keys
|
||||
if(ikbd.state & IKBD_STATE_MOUSE_BUTTON_AS_KEY) {
|
||||
// Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75)
|
||||
|
||||
// handle left mouse button
|
||||
if((b ^ b_old) & 1) ikbd_keyboard(0x74 | ((b&1)?0x00:0x80));
|
||||
// handle right mouse button
|
||||
if((b ^ b_old) & 2) ikbd_keyboard(0x75 | ((b&2)?0x00:0x80));
|
||||
}
|
||||
b_old = b;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(ikbd.state & IKBD_STATE_MOUSE_BUTTON_AS_KEY) {
|
||||
b = 0;
|
||||
// if mouse position is 0/0 quit here
|
||||
if(!x && !y) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ikbd.state & IKBD_STATE_MOUSE_ABSOLUTE) {
|
||||
} else {
|
||||
// atari has mouse button bits swapped
|
||||
enqueue(0xf8|((b&1)?2:0)|((b&2)?1:0));
|
||||
enqueue(x);
|
||||
enqueue((ikbd.state & IKBD_STATE_MOUSE_Y_BOTTOM)?-y:y);
|
||||
}
|
||||
}
|
||||
10
ikbd.h
Normal file
10
ikbd.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef IKBD_H
|
||||
#define IKBD_H
|
||||
|
||||
void ikbd_init(void);
|
||||
void ikbd_poll(void);
|
||||
void ikbd_joystick(unsigned char joy, unsigned char map);
|
||||
void ikbd_mouse(unsigned char buttons, char x, char y);
|
||||
void ikbd_keyboard(unsigned char code);
|
||||
|
||||
#endif // IKBD_H
|
||||
138
tos.c
138
tos.c
@@ -42,26 +42,6 @@ static const char *acsi_cmd_name(int cmd) {
|
||||
return cmdname[cmd];
|
||||
}
|
||||
|
||||
static void acsi_read_cmd() {
|
||||
static int cnt = 0;
|
||||
|
||||
EnableFpga();
|
||||
SPI(MIST_READ_ACSI);
|
||||
unsigned char status = SPI(0);
|
||||
while(status & 1) {
|
||||
unsigned char data = SPI(0);
|
||||
|
||||
if(!(status & 0x02))
|
||||
iprintf("ACSI: cmd \"%s\", target %d\n",
|
||||
acsi_cmd_name(data & 0x1f), data>>5);
|
||||
else
|
||||
iprintf("ACSI: cont. data %x\n", data);
|
||||
|
||||
status = SPI(0);
|
||||
}
|
||||
DisableFpga();
|
||||
}
|
||||
|
||||
static void mist_memory_set_address(unsigned long a) {
|
||||
a >>= 1; // make word address
|
||||
|
||||
@@ -75,9 +55,11 @@ static void mist_memory_set_address(unsigned long a) {
|
||||
}
|
||||
|
||||
|
||||
static void mist_set_control(unsigned short ctrl) {
|
||||
static void mist_set_control(unsigned long ctrl) {
|
||||
EnableFpga();
|
||||
SPI(MIST_SET_CONTROL);
|
||||
SPI((ctrl >> 24) & 0xff);
|
||||
SPI((ctrl >> 16) & 0xff);
|
||||
SPI((ctrl >> 8) & 0xff);
|
||||
SPI((ctrl >> 0) & 0xff);
|
||||
DisableFpga();
|
||||
@@ -154,67 +136,67 @@ static void handle_acsi(unsigned char *buffer) {
|
||||
if(length == 0) length = 256;
|
||||
|
||||
iprintf("ACSI: target %d, \"%s\"\n", target, acsi_cmd_name(cmd));
|
||||
|
||||
// iprintf("ACSI: %02x %02x %02x %02x %02x\n", buffer[10], buffer[11],
|
||||
// buffer[12], buffer[13], buffer[14]);
|
||||
|
||||
iprintf("ACSI: lba %lu, length %u\n", lba, length);
|
||||
|
||||
iprintf("DMA: scnt %u, addr %p\n", scnt, dma_address);
|
||||
|
||||
mist_memory_set_address(dma_address);
|
||||
// only a harddisk on ACSI 0 is supported
|
||||
// ACSI 0 is only supported if a image is loaded
|
||||
if((target == 0) && (hdd_image.size != 0)) {
|
||||
mist_memory_set_address(dma_address);
|
||||
|
||||
switch(cmd) {
|
||||
case 0x08: // read sector
|
||||
DISKLED_ON;
|
||||
while(length) {
|
||||
FileSeek(&hdd_image, lba++, SEEK_SET);
|
||||
FileRead(&hdd_image, dma_buffer);
|
||||
mist_memory_write(dma_buffer, 256);
|
||||
length--;
|
||||
}
|
||||
DISKLED_OFF;
|
||||
break;
|
||||
|
||||
case 0x0a: // write sector
|
||||
DISKLED_ON;
|
||||
while(length) {
|
||||
mist_memory_read(dma_buffer, 256);
|
||||
FileSeek(&hdd_image, lba++, SEEK_SET);
|
||||
FileWrite(&hdd_image, dma_buffer);
|
||||
length--;
|
||||
}
|
||||
DISKLED_OFF;
|
||||
break;
|
||||
|
||||
case 0x12: // inquiry
|
||||
memset(dma_buffer, 0, 512);
|
||||
dma_buffer[2] = 1; // ANSI version
|
||||
dma_buffer[4] = length-8; // len
|
||||
memcpy(dma_buffer+8, "MIST ", 8); // Vendor
|
||||
memcpy(dma_buffer+16, " ", 16); // Clear device entry
|
||||
memcpy(dma_buffer+16, hdd_image.name, 11); // Device
|
||||
mist_memory_write(dma_buffer, length/2);
|
||||
break;
|
||||
|
||||
case 0x1a: // mode sense
|
||||
{ unsigned int blocks = hdd_image.size / 512;
|
||||
iprintf("ACSI: mode sense, blocks = %u\n", blocks);
|
||||
switch(cmd) {
|
||||
case 0x08: // read sector
|
||||
DISKLED_ON;
|
||||
while(length) {
|
||||
FileSeek(&hdd_image, lba++, SEEK_SET);
|
||||
FileRead(&hdd_image, dma_buffer);
|
||||
mist_memory_write(dma_buffer, 256);
|
||||
length--;
|
||||
}
|
||||
DISKLED_OFF;
|
||||
break;
|
||||
|
||||
case 0x0a: // write sector
|
||||
DISKLED_ON;
|
||||
while(length) {
|
||||
mist_memory_read(dma_buffer, 256);
|
||||
FileSeek(&hdd_image, lba++, SEEK_SET);
|
||||
FileWrite(&hdd_image, dma_buffer);
|
||||
length--;
|
||||
}
|
||||
DISKLED_OFF;
|
||||
break;
|
||||
|
||||
case 0x12: // inquiry
|
||||
memset(dma_buffer, 0, 512);
|
||||
dma_buffer[3] = 8; // size of extent descriptor list
|
||||
dma_buffer[5] = blocks >> 16;
|
||||
dma_buffer[6] = blocks >> 8;
|
||||
dma_buffer[7] = blocks;
|
||||
dma_buffer[10] = 2; // byte 1 of block size in bytes (512)
|
||||
dma_buffer[2] = 1; // ANSI version
|
||||
dma_buffer[4] = length-8; // len
|
||||
memcpy(dma_buffer+8, "MIST ", 8); // Vendor
|
||||
memcpy(dma_buffer+16, " ", 16); // Clear device entry
|
||||
memcpy(dma_buffer+16, hdd_image.name, 11); // Device
|
||||
mist_memory_write(dma_buffer, length/2);
|
||||
break;
|
||||
|
||||
case 0x1a: // mode sense
|
||||
{ unsigned int blocks = hdd_image.size / 512;
|
||||
iprintf("ACSI: mode sense, blocks = %u\n", blocks);
|
||||
memset(dma_buffer, 0, 512);
|
||||
dma_buffer[3] = 8; // size of extent descriptor list
|
||||
dma_buffer[5] = blocks >> 16;
|
||||
dma_buffer[6] = blocks >> 8;
|
||||
dma_buffer[7] = blocks;
|
||||
dma_buffer[10] = 2; // byte 1 of block size in bytes (512)
|
||||
mist_memory_write(dma_buffer, length/2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
iprintf("ACSI: Unsupported command\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} else
|
||||
iprintf("ACSI: Request for unsupported target\n");
|
||||
|
||||
default:
|
||||
iprintf("ACSI: Unsupported command\n");
|
||||
break;
|
||||
}
|
||||
|
||||
EnableFpga();
|
||||
SPI(MIST_ACK_DMA);
|
||||
DisableFpga();
|
||||
@@ -283,8 +265,6 @@ static void mist_get_dmastate() {
|
||||
static unsigned char buffer[16];
|
||||
int i;
|
||||
|
||||
// acsi_read_cmd();
|
||||
|
||||
EnableFpga();
|
||||
SPI(MIST_GET_DMASTATE);
|
||||
for(i=0;i<16;i++)
|
||||
@@ -550,8 +530,10 @@ void tos_upload() {
|
||||
|
||||
// try to open harddisk image
|
||||
hdd_image.size = 0;
|
||||
if(FileOpen(&hdd_image, "HARDDISKHD "))
|
||||
tos_write("Found harddisk image ");
|
||||
if(FileOpen(&hdd_image, "HARDDISKHD ")) {
|
||||
tos_write("Found hard disk image ");
|
||||
tos_system_ctrl |= TOS_ACSI0_ENABLE;
|
||||
}
|
||||
|
||||
tos_write("Booting ... ");
|
||||
|
||||
|
||||
23
tos.h
23
tos.h
@@ -13,7 +13,6 @@
|
||||
#define MIST_SET_CONTROL 0x04
|
||||
#define MIST_GET_DMASTATE 0x05 // reads state of dma and floppy controller
|
||||
#define MIST_ACK_DMA 0x06 // acknowledges a dma command
|
||||
#define MIST_READ_ACSI 0x07
|
||||
|
||||
// tos sysconfig bits:
|
||||
// 0 - RESET
|
||||
@@ -21,6 +20,8 @@
|
||||
// 4-5 - CPU configuration
|
||||
// 6-7 - Floppy A+B write protection
|
||||
// 8 - Color/Monochrome mode
|
||||
// 9 - PAL mode in 56 or 50 Hz
|
||||
// 10-17 - ACSI device enable
|
||||
|
||||
// memory configurations (0x02/0x04/0x08)
|
||||
// (currently 4MB are fixed and cannot be changed)
|
||||
@@ -40,11 +41,21 @@
|
||||
#define TOS_CPUCONFIG_68020 (3<<4)
|
||||
|
||||
// control bits (all control bits have unknown state after core startup)
|
||||
#define TOS_CONTROL_CPU_RESET 0x0001
|
||||
#define TOS_CONTROL_FDC_WR_PROT_A 0x0040
|
||||
#define TOS_CONTROL_FDC_WR_PROT_B 0x0080
|
||||
#define TOS_CONTROL_VIDEO_COLOR 0x0100 // input to mfp
|
||||
#define TOS_CONTROL_PAL50HZ 0x0200 // display pal at 50hz (56 hz otherwise)
|
||||
#define TOS_CONTROL_CPU_RESET 0x00000001
|
||||
#define TOS_CONTROL_FDC_WR_PROT_A 0x00000040
|
||||
#define TOS_CONTROL_FDC_WR_PROT_B 0x00000080
|
||||
#define TOS_CONTROL_VIDEO_COLOR 0x00000100 // input to mfp
|
||||
#define TOS_CONTROL_PAL50HZ 0x00000200 // display pal at 50hz (56 hz otherwise)
|
||||
|
||||
// up to eight acsi devices can be enabled
|
||||
#define TOS_ACSI0_ENABLE 0x00000400
|
||||
#define TOS_ACSI1_ENABLE 0x00000800
|
||||
#define TOS_ACSI2_ENABLE 0x00001000
|
||||
#define TOS_ACSI3_ENABLE 0x00002000
|
||||
#define TOS_ACSI4_ENABLE 0x00004000
|
||||
#define TOS_ACSI5_ENABLE 0x00008000
|
||||
#define TOS_ACSI6_ENABLE 0x00010000
|
||||
#define TOS_ACSI7_ENABLE 0x00020000
|
||||
|
||||
extern unsigned long tos_system_ctrl;
|
||||
|
||||
|
||||
304
user_io.c
304
user_io.c
@@ -1,31 +1,13 @@
|
||||
/*
|
||||
|
||||
https://www.kernel.org/doc/Documentation/input/atarikbd.txt
|
||||
|
||||
ikbd ToDo:
|
||||
|
||||
Feature Example using/needing it impl. tested
|
||||
---------------------------------------------------------------------
|
||||
mouse y at bottom Bolo X X
|
||||
mouse button key events Goldrunner/A_008 X X
|
||||
joystick interrogation mode Xevious/A_004
|
||||
Absolute mouse mode Backlash/A_008
|
||||
disable mouse ? X
|
||||
disable joystick ? X
|
||||
Joysticks also generate Goldrunner X X
|
||||
mouse button events!
|
||||
Pause (cmd 0x13) Wings of Death/A_427
|
||||
|
||||
*/
|
||||
|
||||
#include "AT91SAM7S256.h"
|
||||
#include "stdio.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "hardware.h"
|
||||
|
||||
#include "user_io.h"
|
||||
#include "usb.h"
|
||||
|
||||
#include "keycodes.h"
|
||||
#include "ikbd.h"
|
||||
|
||||
typedef enum { EMU_NONE, EMU_MOUSE, EMU_JOY0, EMU_JOY1 } emu_mode_t;
|
||||
static emu_mode_t emu_mode = EMU_NONE;
|
||||
@@ -40,155 +22,6 @@ AT91PS_PMC a_pPMC = AT91C_BASE_PMC;
|
||||
|
||||
static char caps_lock_toggle = 0;
|
||||
|
||||
// atari ikbd stuff
|
||||
#define IKBD_STATE_JOYSTICK_EVENT_REPORTING 0x01
|
||||
#define IKBD_STATE_MOUSE_Y_BOTTOM 0x02
|
||||
#define IKBD_STATE_MOUSE_BUTTON_AS_KEY 0x04 // mouse buttons act like keys
|
||||
#define IKBD_STATE_MOUSE_DISABLED 0x08
|
||||
|
||||
#define IKBD_DEFAULT IKBD_STATE_JOYSTICK_EVENT_REPORTING
|
||||
|
||||
static unsigned char ikbd_cmd = 0;
|
||||
static unsigned char ikbd_state = IKBD_DEFAULT;
|
||||
static unsigned char ikbd_expect = 0;
|
||||
static unsigned char ikbd_joystick_buttons = 0;
|
||||
|
||||
// #define IKBD_DEBUG
|
||||
|
||||
void ikbd_ok() {
|
||||
// this only happens while we are reading
|
||||
// from the spi. so stop reading
|
||||
DisableIO();
|
||||
|
||||
// send reply
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_OUT);
|
||||
SPI(0xf0);
|
||||
DisableIO();
|
||||
|
||||
// continue reading
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_IN);
|
||||
}
|
||||
|
||||
// process inout from atari core into ikbd
|
||||
void ikbd_handle_input(unsigned char cmd) {
|
||||
// expecting a second byte for command
|
||||
if(ikbd_expect) {
|
||||
ikbd_expect--;
|
||||
|
||||
// last byte of command received
|
||||
if(!ikbd_expect) {
|
||||
switch(ikbd_cmd) {
|
||||
case 0x07: // set mouse button action
|
||||
iprintf("IKBD: mouse button action = %x\n", cmd);
|
||||
|
||||
// bit 2: Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75)
|
||||
if(cmd & 0x04) ikbd_state |= IKBD_STATE_MOUSE_BUTTON_AS_KEY;
|
||||
else ikbd_state &= ~IKBD_STATE_MOUSE_BUTTON_AS_KEY;
|
||||
|
||||
break;
|
||||
|
||||
case 0x80: // ibkd reset
|
||||
// reply "everything is ok"
|
||||
ikbd_ok();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ikbd_cmd = cmd;
|
||||
|
||||
switch(cmd) {
|
||||
case 0x07:
|
||||
puts("IKBD: Set mouse button action");
|
||||
ikbd_expect = 1;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
puts("IKBD: Set relative mouse positioning");
|
||||
ikbd_state &= ~IKBD_STATE_MOUSE_DISABLED;
|
||||
break;
|
||||
|
||||
case 0x0b:
|
||||
puts("IKBD: Set Mouse threshold");
|
||||
ikbd_expect = 2;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
puts("IKBD: Set Y at bottom");
|
||||
ikbd_state |= IKBD_STATE_MOUSE_Y_BOTTOM;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
puts("IKBD: Set Y at top");
|
||||
ikbd_state &= ~IKBD_STATE_MOUSE_Y_BOTTOM;
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
puts("IKBD: Disable mouse");
|
||||
ikbd_state |= IKBD_STATE_MOUSE_DISABLED;
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
puts("IKBD: Set Joystick event reporting");
|
||||
ikbd_state |= IKBD_STATE_JOYSTICK_EVENT_REPORTING;
|
||||
break;
|
||||
|
||||
case 0x15:
|
||||
puts("IKBD: Set Joystick interrogation mode");
|
||||
ikbd_state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
|
||||
break;
|
||||
|
||||
case 0x1a:
|
||||
puts("IKBD: Disable joysticks");
|
||||
ikbd_state &= ~IKBD_STATE_JOYSTICK_EVENT_REPORTING;
|
||||
break;
|
||||
|
||||
case 0x1c:
|
||||
puts("IKBD: Interrogate time of day");
|
||||
|
||||
// send some date
|
||||
|
||||
// stop reading from ikbd queue
|
||||
DisableIO();
|
||||
|
||||
// send reply (the date this routine was written)
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_OUT);
|
||||
SPI(0xfc);
|
||||
SPI(0x13); // year bcd
|
||||
SPI(0x03); // month bcd
|
||||
SPI(0x07); // day bcd
|
||||
SPI(0x20); // hour bcd
|
||||
SPI(0x58); // minute bcd
|
||||
SPI(0x00); // second bcd
|
||||
DisableIO();
|
||||
|
||||
// continue reading
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_IN);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 0x80:
|
||||
puts("IKBD: Reset");
|
||||
ikbd_expect = 1;
|
||||
ikbd_state = IKBD_DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
iprintf("IKBD: unknown command: %x\n", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void InitADC(void) {
|
||||
|
||||
// Enable clock for interface
|
||||
@@ -229,6 +62,7 @@ static unsigned int GetAdc(unsigned char channel) {
|
||||
void user_io_init() {
|
||||
InitADC();
|
||||
|
||||
ikbd_init();
|
||||
}
|
||||
|
||||
unsigned char user_io_core_type() {
|
||||
@@ -269,19 +103,6 @@ void user_io_detect_core_type() {
|
||||
}
|
||||
}
|
||||
|
||||
// convert internal joystick format into atari ikbd format
|
||||
unsigned char joystick_map2ikbd(unsigned in) {
|
||||
unsigned char out = 0;
|
||||
|
||||
if(in & JOY_UP) out |= 0x01;
|
||||
if(in & JOY_DOWN) out |= 0x02;
|
||||
if(in & JOY_LEFT) out |= 0x04;
|
||||
if(in & JOY_RIGHT) out |= 0x08;
|
||||
if(in & JOY_BTN1) out |= 0x80;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void user_io_joystick(unsigned char joystick, unsigned char map) {
|
||||
if(core_type == CORE_TYPE_MINIMIG || core_type == CORE_TYPE_PACE) {
|
||||
EnableIO();
|
||||
@@ -290,39 +111,8 @@ void user_io_joystick(unsigned char joystick, unsigned char map) {
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
if(core_type == CORE_TYPE_MIST) {
|
||||
// todo: suppress events for joystick 0 as long as mouse
|
||||
// is enabled?
|
||||
|
||||
if(ikbd_state & IKBD_STATE_JOYSTICK_EVENT_REPORTING) {
|
||||
#ifdef IKBD_DEBUG
|
||||
iprintf("IKBD: joy %d %x\n", joystick, map);
|
||||
#endif
|
||||
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_OUT);
|
||||
SPI(0xfe + joystick);
|
||||
SPI(joystick_map2ikbd(map));
|
||||
DisableIO();
|
||||
|
||||
// the fire button also generates a mouse event if
|
||||
// mouse reporting is enabled
|
||||
|
||||
unsigned char button1 = (map & JOY_BTN1)?(1<<joystick):0;
|
||||
if(button1 != (ikbd_joystick_buttons & (1<<joystick))) {
|
||||
// update saved state of joystick buttons
|
||||
ikbd_joystick_buttons = (ikbd_joystick_buttons & ~(1<<joystick)) | button1;
|
||||
|
||||
// generate mouse event (ikbd_joystick_buttons is evaluated inside
|
||||
// user_io_mouse)
|
||||
user_io_mouse(0, 0, 0);
|
||||
}
|
||||
}
|
||||
#ifdef IKBD_DEBUG
|
||||
else
|
||||
iprintf("IKBD: no monitor, drop joy %d %x\n", joystick, map);
|
||||
#endif
|
||||
}
|
||||
if(core_type == CORE_TYPE_MIST)
|
||||
ikbd_joystick(joystick, map);
|
||||
}
|
||||
|
||||
void user_io_poll() {
|
||||
@@ -333,28 +123,16 @@ void user_io_poll() {
|
||||
}
|
||||
|
||||
if(core_type == CORE_TYPE_MIST) {
|
||||
static mtimer = 0;
|
||||
if(CheckTimer(mtimer)) {
|
||||
mtimer = GetTimer(100);
|
||||
ikbd_poll();
|
||||
|
||||
// check for incoming ikbd data
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_IN);
|
||||
|
||||
while(SPI(0))
|
||||
ikbd_handle_input(SPI(0));
|
||||
|
||||
DisableIO();
|
||||
|
||||
// check for incoming serial data
|
||||
EnableIO();
|
||||
SPI(UIO_SERIAL_IN);
|
||||
|
||||
while(SPI(0))
|
||||
putchar(SPI(0));
|
||||
|
||||
DisableIO();
|
||||
}
|
||||
// check for incoming serial data
|
||||
EnableIO();
|
||||
SPI(UIO_SERIAL_IN);
|
||||
|
||||
while(SPI(0))
|
||||
putchar(SPI(0));
|
||||
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
// poll db9 joysticks
|
||||
@@ -445,15 +223,8 @@ static void send_keycode(unsigned short code) {
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
if(core_type == CORE_TYPE_MIST) {
|
||||
#ifdef IKBD_DEBUG
|
||||
iprintf("IKBD: send keycode %x%s\n", code&0x7f, (code&0x80)?" BREAK":"");
|
||||
#endif
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_OUT);
|
||||
SPI(code & 0xff);
|
||||
DisableIO();
|
||||
}
|
||||
if(core_type == CORE_TYPE_MIST)
|
||||
ikbd_keyboard(code);
|
||||
}
|
||||
|
||||
void user_io_mouse(unsigned char b, char x, char y) {
|
||||
@@ -469,45 +240,8 @@ void user_io_mouse(unsigned char b, char x, char y) {
|
||||
}
|
||||
|
||||
// send mouse data as mist expects it
|
||||
if(core_type == CORE_TYPE_MIST) {
|
||||
if(ikbd_state & IKBD_STATE_MOUSE_DISABLED)
|
||||
return;
|
||||
|
||||
// joystick and mouse buttons are wired together in
|
||||
// atari st
|
||||
b |= ikbd_joystick_buttons;
|
||||
|
||||
static unsigned char b_old = 0;
|
||||
// monitor state of two mouse buttons
|
||||
if(b != b_old) {
|
||||
// check if mouse buttons are supposed to be treated like keys
|
||||
if(ikbd_state & IKBD_STATE_MOUSE_BUTTON_AS_KEY) {
|
||||
// Mouse buttons act like keys (LEFT=0x74 & RIGHT=0x75)
|
||||
|
||||
// handle left mouse button
|
||||
if((b ^ b_old) & 1) send_keycode(0x74 | ((b&1)?0x00:0x80));
|
||||
// handle right mouse button
|
||||
if((b ^ b_old) & 2) send_keycode(0x75 | ((b&2)?0x00:0x80));
|
||||
}
|
||||
b_old = b;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(ikbd_state & IKBD_STATE_MOUSE_BUTTON_AS_KEY) {
|
||||
b = 0;
|
||||
// if mouse position is 0/0 quit here
|
||||
if(!x && !y) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
EnableIO();
|
||||
SPI(UIO_IKBD_OUT);
|
||||
// atari has mouse button bits swapped
|
||||
SPI(0xf8|((b&1)?2:0)|((b&2)?1:0));
|
||||
SPI(x);
|
||||
SPI((ikbd_state & IKBD_STATE_MOUSE_Y_BOTTOM)?-y:y);
|
||||
DisableIO();
|
||||
}
|
||||
if(core_type == CORE_TYPE_MIST)
|
||||
ikbd_mouse(b, x, y);
|
||||
}
|
||||
|
||||
// check if this is a key that's supposed to be suppressed
|
||||
|
||||
Reference in New Issue
Block a user