1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-02-14 11:55:20 +00:00

KA10: Updated IMX device.

This commit is contained in:
Richard Cornwell
2020-02-24 20:56:23 -05:00
4 changed files with 263 additions and 21 deletions

View File

@@ -1,6 +1,6 @@
/* ka10_imx.c: Input multplexor for A/D.
Copyright (c) 2018, Lars Brinkhoff
Copyright (c) 2018,2020, Lars Brinkhoff
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
#include <time.h>
#include "kx10_defs.h"
#include "sim_video.h"
#ifndef NUM_DEVS_IMX
#define NUM_DEVS_IMX 0
@@ -47,33 +48,78 @@
#define IMX_CHANNEL 0000177
t_stat imx_devio(uint32 dev, uint64 *data);
const char *imx_description (DEVICE *dptr);
#define JOY_MAX_UNITS 4
#define JOY_MAX_AXES 4
#define JOY_NO_CHAN (IMX_CHANNEL + 1)
t_stat imx_devio(uint32 dev, uint64 *data);
t_stat imx_svc (UNIT *uptr);
t_stat imx_reset (DEVICE *dptr);
const char *imx_description (DEVICE *dptr);
#if MPX_DEV
t_stat imx_set_mpx (UNIT *uptr, int32 val, CONST char *cptr, void *desc) ;
t_stat imx_show_mpx (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
#endif
t_stat imx_show_channel (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
t_stat imx_set_channel (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
static uint64 status = IMX_ASSIGNED;
static uint64 imx_data;
static uint64 imx_samples;
static int initial_channel = 0;
static int current_channel = 0;
static int imx_mpx_lvl;
static int imx_inputs[0200];
static int imx_map[JOY_MAX_UNITS][JOY_MAX_AXES];
UNIT imx_unit[] = {
{UDATA(NULL, UNIT_DISABLE, 0)}, /* 0 */
{ UDATA (&imx_svc, UNIT_IDLE, 0) }
};
DIB imx_dib = {IMX_DEVNUM, 1, &imx_devio, NULL};
MTAB imx_mod[] = {
#if MPX_DEV
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "MPX", "MPX",
&imx_set_mpx, &imx_show_mpx, NULL},
#endif
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "CHANNEL", "CHANNEL",
&imx_set_channel, &imx_show_channel, NULL},
{ 0 }
};
DEVICE imx_dev = {
"IMX", imx_unit, NULL, imx_mod,
1, 8, 0, 1, 8, 36,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, imx_reset, NULL, NULL, NULL,
&imx_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, NULL,
NULL, NULL, NULL, NULL, NULL, &imx_description
};
static void imx_joy_motion(int which, int axis, int value)
{
int chan;
if (which < JOY_MAX_UNITS && axis < JOY_MAX_AXES) {
chan = imx_map[which][axis];
if (chan == JOY_NO_CHAN)
return;
value += 32768;
if (chan < 0) {
chan = -chan;
value = 65535 - value;
}
imx_inputs[chan] = value >> 5;
sim_debug(DEBUG_DETAIL, &imx_dev, "Channel %d value %o\n",
chan, imx_inputs[chan]);
}
}
static int imx_sample (void)
{
int sample = 2048;
int sample = imx_inputs[current_channel];
if (status & IMX_SEQUENCE)
current_channel = (current_channel + 1) & IMX_CHANNEL;
else
@@ -81,36 +127,217 @@ static int imx_sample (void)
return sample;
}
static void imx_activate (void)
{
int micros;
if (status & IMX_DONE) {
sim_cancel (imx_unit);
sim_debug(DEBUG_IRQ, &imx_dev, "Cancel\n");
return;
}
micros = (status >> 16) & 0377;
if (micros < 10)
micros = 10;
sim_activate_after (imx_unit, micros);
sim_debug(DEBUG_IRQ, &imx_dev, "Activate\n");
}
t_stat imx_reset (DEVICE *dptr)
{
static int init = 1;
int i, j;
if (dptr->flags & DEV_DIS) {
imx_samples = 0;
imx_data = 0;
for (i = 0; i <= IMX_CHANNEL; i++)
imx_inputs[i] = 1000;
for (i = 0; i < JOY_MAX_UNITS; i++) {
for (j = 0; j < JOY_MAX_UNITS; j++)
imx_map[i][j] = JOY_NO_CHAN;
}
} else {
if (init) {
vid_register_gamepad_motion_callback (imx_joy_motion);
init = 0;
}
}
return SCPE_OK;
}
t_stat imx_devio(uint32 dev, uint64 *data)
{
DEVICE *dptr = &imx_dev;
switch(dev & 07) {
case CONO|4:
status &= ~IMX_CONO;
sim_debug(DEBUG_CONO, &imx_dev, "%06llo\n", *data);
status &= ~(IMX_CONO|IMX_DONE);
status |= *data & IMX_CONO;
imx_data = 0;
imx_samples = 0;
current_channel = initial_channel;
clr_interrupt (IMX_DEVNUM);
imx_activate ();
break;
case CONI|4:
status |= IMX_DONE;
*data = status & IMX_CONI;
sim_debug(DEBUG_CONI, &imx_dev, "%012llo\n", *data);
break;
case DATAO|4:
sim_debug(DEBUG_DATAIO, &imx_dev, "DATAO %012llo\n", *data);
initial_channel = *data & IMX_CHANNEL;
break;
case DATAI|4:
*data = imx_sample();
if (status & IMX_PACK) {
*data <<= 24;
*data |= imx_sample() << 12;
*data |= imx_sample();
}
*data = imx_data;
sim_debug(DEBUG_DATAIO, &imx_dev, "DATAI %012llo\n", *data);
imx_data = 0;
imx_samples = 0;
status &= ~IMX_DONE;
clr_interrupt (IMX_DEVNUM);
sim_debug(DEBUG_IRQ, &imx_dev, "Clear interrupt\n");
imx_activate ();
break;
}
return SCPE_OK;
}
t_stat imx_svc (UNIT *uptr)
{
int max_samples;
if (status & IMX_PACK) {
max_samples = 3;
} else {
max_samples = 1;
}
if (imx_samples < max_samples) {
imx_data <<= 12;
imx_data |= imx_sample();
imx_samples++;
}
if (imx_samples == max_samples) {
status |= IMX_DONE;
if (status & 7) {
set_interrupt_mpx (IMX_DEVNUM, status & 7, imx_mpx_lvl);
sim_debug(DEBUG_IRQ, &imx_dev, "Raise interrupt\n");
}
}
imx_activate ();
return SCPE_OK;
}
#if MPX_DEV
/* set MPX level number */
t_stat imx_set_mpx (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int32 mpx;
t_stat r;
if (cptr == NULL)
return SCPE_ARG;
mpx = (int32) get_uint (cptr, 8, 8, &r);
if (r != SCPE_OK)
return r;
imx_mpx_lvl = mpx;
return SCPE_OK;
}
t_stat imx_show_mpx (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (uptr == NULL)
return SCPE_IERR;
fprintf (st, "MPX=%o", imx_mpx_lvl);
return SCPE_OK;
}
#endif
t_stat imx_set_channel (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int chan, unit, axis, negate = 0;
char gbuf[CBUFSIZE];
CONST char *tptr;
t_stat r;
if (cptr == NULL || *cptr == 0)
return SCPE_ARG;
tptr = get_glyph (cptr, gbuf, ';');
if (tptr == NULL)
return SCPE_ARG;
chan = (int) get_uint (gbuf, 8, IMX_CHANNEL, &r);
if (r != SCPE_OK)
return r;
tptr = get_glyph (tptr, gbuf, ';');
if (tptr == NULL || strncasecmp (gbuf, "unit", 4) != 0)
return SCPE_ARG;
unit = (int) get_uint (gbuf + 4, 10, JOY_MAX_UNITS - 1, &r);
if (r != SCPE_OK)
return r;
tptr = get_glyph (tptr, gbuf, ';');
if (strncasecmp (gbuf, "axis", 4) != 0)
return SCPE_ARG;
axis = (int) get_uint (gbuf + 4, 10, JOY_MAX_AXES - 1, &r);
if (r != SCPE_OK)
return r;
if (*tptr != 0) {
if (strcasecmp (tptr, "negate") != 0)
return SCPE_ARG;
negate = 1;
}
if (negate)
chan = -chan;
imx_map[unit][axis] = chan;
return SCPE_OK;
}
t_stat imx_show_channel (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
int nothing = 1;
const char *negate, *comma = "";
int chan, i, j;
if (uptr == NULL)
return SCPE_IERR;
for (i = 0; i < JOY_MAX_UNITS; i++) {
for (j = 0; j < JOY_MAX_AXES; j++) {
chan = imx_map[i][j];
if (chan != JOY_NO_CHAN) {
if (chan < 0) {
chan = -chan;
negate = ";NEGATE";
} else
negate = "";
fprintf (st, "%sCHANNEL=%d;JOY%d;AXIS%d%s", comma, chan, i, j, negate);
comma = ", ";
nothing = 0;
}
}
}
if (nothing)
fprintf (st, "CHANNEL=(NO MAPPINGS)");
return SCPE_OK;
}
const char *imx_description (DEVICE *dptr)
{
return "A/D input multiplexor";

View File

@@ -306,6 +306,7 @@ static int joy_buttons[JOY_MAX_UNITS * JOY_MAX_BUTTONS];
static void dpy_joy_motion(int which, int axis, int value)
{
int result = FALSE;
if (which < JOY_MAX_UNITS && axis < JOY_MAX_AXES) {
joy_axes[which * JOY_MAX_AXES + axis] = value;
}
@@ -313,6 +314,7 @@ static void dpy_joy_motion(int which, int axis, int value)
static void dpy_joy_button(int which, int button, int state)
{
int result = FALSE;
if (which < JOY_MAX_UNITS && button < JOY_MAX_BUTTONS) {
joy_buttons[which * JOY_MAX_UNITS + button] = state;
}

View File

@@ -369,6 +369,7 @@ static long queue_interval;
#define Y(P) (((P) - points) / xpixels)
static int initialized = 0;
static void *device = NULL; /* Current display device. */
/*
* global set by O/S display level to indicate "light pen tip switch activated"
@@ -979,6 +980,7 @@ display_init(enum display_type type, int sf, void *dptr)
initialized = 1;
init_failed = 0; /* hey, we made it! */
device = dptr;
return 1;
failed:
@@ -992,10 +994,14 @@ display_close(void *dptr)
if (!initialized)
return;
if (device != dptr)
return;
free (points);
ws_shutdown();
initialized = 0;
device = NULL;
}
void

View File

@@ -564,19 +564,24 @@ static t_stat vid_init_controllers (void)
vid_gamepad_ok = (ver.major > 2 ||
(ver.major == 2 && (ver.minor > 0 || ver.patch >= 4)));
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
if (vid_gamepad_ok)
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
else
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
if (SDL_JoystickEventState (SDL_ENABLE) < 0) {
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
if (vid_gamepad_ok)
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
else
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return SCPE_IOERR;
}
if (vid_gamepad_ok && SDL_GameControllerEventState (SDL_ENABLE) < 0) {
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
if (vid_gamepad_ok)
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
else
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return SCPE_IOERR;
}
@@ -661,8 +666,10 @@ if (vid_active) {
vid_gamepad_inited = 0;
memset (motion_callback, 0, sizeof motion_callback);
memset (button_callback, 0, sizeof button_callback);
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
if (vid_gamepad_ok)
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
else
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
vid_active = FALSE;
if (vid_ready) {