LPT and MIDI Tests

Added tests for the parallel and MIDI ports on SuperIO machines
This commit is contained in:
Peter Weingartner 2021-11-02 15:08:27 -04:00
parent 4d2f3e37a0
commit 95856b80dc
16 changed files with 8559 additions and 7954 deletions

Binary file not shown.

View file

@ -6,6 +6,7 @@
#include "sound_cmds.h" #include "sound_cmds.h"
#include "sound_reg.h" #include "sound_reg.h"
#include "snd/psg.h" #include "snd/psg.h"
#include "dev/midi.h"
/* /*
* Play a sound on the PSG * Play a sound on the PSG
@ -124,3 +125,80 @@ short opl3_test(short channel, int argc, char * argv[]) {
return 0; return 0;
} }
/*
* Perform a receive test on the MIDI ports
*/
short midi_rx_test(short channel, int argc, char * argv[]) {
char message[80];
unsigned short scancode = 0;
int i;
midi_init();
sprintf(message, "Press '1' to start, and 'ESC' to exit test.\n");
sys_chan_write(channel, message, strlen(message));
while (sys_kbd_scancode() != 0x02) ;
i = 0;
while (scancode != 0x01) {
unsigned char input = midi_get_poll();
if ((input != 0xf8) && (input != 0xfe)) {
if ((i % 16) == 0) {
sprintf(message, "\n%02X", input);
sys_chan_write(channel, message, strlen(message));
} else {
sprintf(message, " %02X", input);
sys_chan_write(channel, message, strlen(message));
}
i++;
}
scancode = sys_kbd_scancode();
}
sys_chan_write(channel, "\n", 1);
return 0;
}
/*
* Perform a loopback test on the MIDI ports
*/
short midi_loop_test(short channel, int argc, char * argv[]) {
char message[80];
unsigned short scancode = 0;
unsigned char output;
midi_init();
sprintf(message, "Plug a MIDI loopback cable between MIDI IN and MIDI OUT.\nThen press '1' to start.\n");
sys_chan_write(channel, message, strlen(message));
sprintf(message, "Press ESC to exit test.\n");
sys_chan_write(channel, message, strlen(message));
while (sys_kbd_scancode() != 0x02) ;
output = 0xF8;
while (scancode != 0x01) {
sprintf(message, "Sending: ");
sys_chan_write(channel, message, strlen(message));
midi_put(output);
sprintf(message, "%02X --> ", output);
sys_chan_write(channel, message, strlen(message));
unsigned char input = midi_get_poll();
sprintf(message, "%02X\n", input);
sys_chan_write(channel, message, strlen(message));
scancode = sys_kbd_scancode();
}
sys_chan_write(channel, "\n", 1);
return 0;
}

View file

@ -15,4 +15,14 @@ extern short psg_test(short channel, int argc, char * argv[]);
*/ */
extern short opl3_test(short channel, int argc, char * argv[]); extern short opl3_test(short channel, int argc, char * argv[]);
/*
* Perform a receive test on the MIDI ports
*/
extern short midi_rx_test(short channel, int argc, char * argv[]);
/*
* Perform a loopback test on the MIDI ports
*/
extern short midi_loop_test(short channel, int argc, char * argv[]);
#endif #endif

View file

@ -7,9 +7,11 @@
#include "cli.h" #include "cli.h"
#include "cli/test_cmds.h" #include "cli/test_cmds.h"
#include "cli/sound_cmds.h"
#include "dev/block.h" #include "dev/block.h"
#include "dev/channel.h" #include "dev/channel.h"
#include "dev/fsys.h" #include "dev/fsys.h"
#include "dev/lpt.h"
#include "dev/rtc.h" #include "dev/rtc.h"
#include "dev/uart.h" #include "dev/uart.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
@ -20,6 +22,29 @@
#include "sys_general.h" #include "sys_general.h"
#include "uart_reg.h" #include "uart_reg.h"
#define LPT_DATA_PORT ((volatile unsigned char *)0x00C02378)
#define LPT_STAT_PORT ((volatile unsigned char *)0x00C02379)
#define LPT_STAT_BUSY 0x80
#define LPT_STAT_ACK 0x40
#define LPT_STAT_PO 0x20
#define LPT_STAT_SELECT 0x10
#define LPT_STAT_ERROR 0x08
#define LPT_STAT_IRQ 0x04
#define LPT_CTRL_PORT ((volatile unsigned char *)0x00C0237A)
#define LPT_CTRL_STROBE 0x01
#define LPT_CTRL_AL 0x02
#define LPT_CTRL_INIT 0x04
#define LPT_CTRL_SELECT 0x08
#define LPT_CTRL_IRQE 0x10
#define LPT_CTRL_BI 0x20
#define LPT_INIT_ON 0x08 /* Start the printer initialization process */
#define LPT_INIT_OFF 0x0C /* Stop the printer initialization process */
#define LPT_STROBE_ON 0x0F /* Strobe the printer */
#define LPT_STROBE_OFF 0x0E /* Drop the strobe to the printer */
typedef struct s_cli_test_feature { typedef struct s_cli_test_feature {
const char * name; const char * name;
const char * help; const char * help;
@ -201,12 +226,95 @@ short cli_test_create(short screen, int argc, char * argv[]) {
} }
} }
short cli_test_lpt(short screen, int argc, char * argv[]) {
char message[80];
unsigned char scancode;
sprintf(message, "Test parallel port:\nF1: DATA=00 F2: DATA=FF F3: STRB=1 F4: STRB=0\n");
sys_chan_write(screen, message, strlen(message));
sprintf(message, "F5: INIT=1 F6: INIT=0 F7: SEL=1 F8: SEL=0\nESC: Quit");
sys_chan_write(screen, message, strlen(message));
while (1) {
scancode = sys_kbd_scancode();
switch (scancode) {
case 0x3B: /* F1 */
*LPT_DATA_PORT = 0;
break;
case 0x3C: /* F2 */
*LPT_DATA_PORT = 0xff;
break;
case 0x3D: /* F3 */
*LPT_CTRL_PORT = LPT_CTRL_STROBE;
break;
case 0x3E: /* F4 */
*LPT_CTRL_PORT = 0;
break;
case 0x3F: /* F5 */
*LPT_CTRL_PORT = 0;
break;
case 0x40: /* F6 */
*LPT_CTRL_PORT = LPT_CTRL_INIT;
break;
case 0x41: /* F7 */
*LPT_CTRL_PORT = LPT_CTRL_SELECT;
break;
case 0x42: /* F8 */
*LPT_CTRL_PORT = 0;
break;
case 0x1B: /* ESC */
return 0;
default:
break;
}
}
return 0;
}
short cmd_test_print(short screen, int argc, char * argv[]) {
const char * test_pattern = "0123456789ABCDEFGHIJKLMNOPQRTSUVWZXYZ\r\n";
char message[80];
unsigned short scancode = 0;
sprintf(message, "Initializing printer...\n");
sys_chan_write(screen, message, strlen(message));
lpt_initialize();
sprintf(message, "Sending test patterns to printer (ESC to quit)...\n");
sys_chan_write(screen, message, strlen(message));
while (scancode != 0x01) {
scancode = sys_kbd_scancode();
lpt_write(0, test_pattern, strlen(test_pattern));
}
return 0;
}
static t_cli_test_feature cli_test_features[] = { static t_cli_test_feature cli_test_features[] = {
{"CREATE", "CREATE <path>: test creating a file", cli_test_create}, {"CREATE", "CREATE <path>: test creating a file", cli_test_create},
{"IDE", "IDE: test reading the MBR of the IDE drive", cli_test_ide}, {"IDE", "IDE: test reading the MBR of the IDE drive", cli_test_ide},
{"PANIC", "PANIC: test the kernel panic mechanism", cli_test_panic}, {"PANIC", "PANIC: test the kernel panic mechanism", cli_test_panic},
{"RTC", "RTC: test the real time clock periodic interrupt", cli_test_rtc}, {"RTC", "RTC: test the real time clock periodic interrupt", cli_test_rtc},
{"LPT", "LPT: test the parallel port", cli_test_lpt},
{"MEM", "MEM: test reading and writing memory", cli_mem_test}, {"MEM", "MEM: test reading and writing memory", cli_mem_test},
{"MIDILOOP", "MIDILOOP: perform a loopback test on the MIDI ports", midi_loop_test},
{"MIDIRX", "MIDIRX: perform a receive test on the MIDI ports", midi_rx_test},
{"OPL3", "OPL3: test the OPL3 sound chip", opl3_test},
{"PSG", "PSG: test the PSG sound chip", psg_test},
{"PRINT", "PRINT: sent text to the printer", cmd_test_print},
{"UART", "UART: test the serial port", cli_test_uart}, {"UART", "UART: test the serial port", cli_test_uart},
{0, 0} {0, 0}
}; };

View file

@ -21,6 +21,8 @@
#define MAX_ANSI_ARGS 10 #define MAX_ANSI_ARGS 10
#define CON_CTRL_ANSI 0x80 /* Set to enable ANSI escape processing */ #define CON_CTRL_ANSI 0x80 /* Set to enable ANSI escape processing */
#define CON_IOCTRL_ANSI_ON 0x01 /* IOCTRL Command: turn on ANSI terminal codes */
#define CON_IOCTRL_ANSI_OFF 0x02 /* IOCTRL Command: turn off ANSI terminal codes */
typedef void (*ansi_handler)(p_channel, short, short[]); typedef void (*ansi_handler)(p_channel, short, short[]);
@ -39,6 +41,7 @@ typedef struct s_console_data {
unsigned char control; /* Control flags for the console: e.g. process ANSI codes */ unsigned char control; /* Control flags for the console: e.g. process ANSI codes */
unsigned char ansi_buffer_count; /* Number of characters in the ANSI BUFFER */ unsigned char ansi_buffer_count; /* Number of characters in the ANSI BUFFER */
char ansi_buffer[ANSI_BUFFER_SIZE]; /* Used to keep track of characters in the ANSI escape sequences */ char ansi_buffer[ANSI_BUFFER_SIZE]; /* Used to keep track of characters in the ANSI escape sequences */
char key_buffer; /* Used to peek at keyboard input */
} t_console_data, *p_console_data; } t_console_data, *p_console_data;
/* /*
@ -425,6 +428,7 @@ short con_open(p_channel chan, uint8_t * path, short mode) {
for (i = 0; i < ANSI_BUFFER_SIZE; i++) { for (i = 0; i < ANSI_BUFFER_SIZE; i++) {
con_data->ansi_buffer[i] = 0; con_data->ansi_buffer[i] = 0;
} }
con_data->key_buffer = 0;
return 0; return 0;
} }
@ -485,23 +489,34 @@ short con_write_b(p_channel chan, uint8_t b) {
* Attempt to read from the keyboard. * Attempt to read from the keyboard.
*/ */
short con_read_b(p_channel chan) { short con_read_b(p_channel chan) {
p_console_data con_data;
/* Check to see if we need to process ANSI codes */
con_data = &(chan->data);
char c; char c;
do { do {
if (con_data->key_buffer != 0) {
c = con_data->key_buffer;
con_data->key_buffer = 0;
} else {
#if MODEL == MODEL_FOENIX_A2560K #if MODEL == MODEL_FOENIX_A2560K
#ifdef KBD_POLLED #ifdef KBD_POLLED
ps2_mouse_get_packet(); ps2_mouse_get_packet();
c = kbdmo_getc_poll(); c = kbdmo_getc_poll();
#else #else
c = kbdmo_getc(); c = kbdmo_getc();
#endif #endif
#else #else
#ifdef KBD_POLLED #ifdef KBD_POLLED
c = kbd_getc_poll(); c = kbd_getc_poll();
#else #else
c = kbd_getc(); c = kbd_getc();
#endif #endif
#endif #endif
}
} while (c == 0); } while (c == 0);
@ -605,13 +620,58 @@ short con_write(p_channel chan, const uint8_t * buffer, short size) {
return i; return i;
} }
short con_has_input(p_channel chan) {
p_console_data con_data;
char c;
/* Check to see if we need to process ANSI codes */
con_data = &(chan->data);
if (con_data->key_buffer != 0) {
/* If we already peeked and have a character... return true */
return 1;
} else {
/* Otherwise, peek at the keyboard to see if there is a valid key */
#if MODEL == MODEL_FOENIX_A2560K
#ifdef KBD_POLLED
ps2_mouse_get_packet();
c = kbdmo_getc_poll();
#else
c = kbdmo_getc();
#endif
#else
#ifdef KBD_POLLED
c = kbd_getc_poll();
#else
c = kbd_getc();
#endif
#endif
if (c == 0) {
/* No: return false */
return 0;
} else {
/* Yes: save the key we got and return true */
con_data->key_buffer = c;
return 1;
}
}
}
// //
// Return the status of the console // Return the status of the console
// //
short con_status(p_channel chan) { short con_status(p_channel chan) {
// TODO: make CDEV_STAT_READABLE conditional short status = CDEV_STAT_WRITABLE; /* The console is always writable */
if (con_has_input(chan)) {
/* If there is data available, flag that it's readable */
status |= CDEV_STAT_READABLE;
}
return CDEV_STAT_READABLE | CDEV_STAT_WRITABLE; return status;
} }
// //
@ -622,6 +682,25 @@ short con_seek(p_channel chan, long position, short base) {
} }
short con_ioctrl(p_channel chan, short command, uint8_t * buffer, short size) { short con_ioctrl(p_channel chan, short command, uint8_t * buffer, short size) {
p_console_data con_data;
/* Check to see if we need to process ANSI codes */
con_data = &(chan->data);
switch (command) {
case CON_IOCTRL_ANSI_ON:
/* Turn on ANSI interpreting */
con_data->control |= CON_CTRL_ANSI;
return 0;
case CON_IOCTRL_ANSI_OFF:
/* Turn on ANSI interpreting */
con_data->control &= ~CON_CTRL_ANSI;
return 0;
default:
break;
}
return 0; return 0;
} }

View file

@ -32,11 +32,9 @@
short lpt_delay() { short lpt_delay() {
int i; int i;
short x; short x;
for (i = 0, x = 0; i < 65535; i++) { for (i = 0, x = 0; i < 10; i++) {
x++; x++;
} }
DEBUG(".");
return x; return x;
} }

77
src/dev/midi.c Normal file
View file

@ -0,0 +1,77 @@
/*
* Definitions for the MIDI ports
*/
#include "midi_reg.h"
#include "dev/midi.h"
#include "simpleio.h"
/*
* Return true if there is data waiting to be read
*/
short midi_input_not_ready() {
return (*MIDI_STAT & MIDI_STAT_RX_EMPTY);
}
/*
* Return true if there is data waiting to be read
*/
short midi_output_busy() {
return (*MIDI_STAT & MIDI_STAT_RX_EMPTY);
}
/*
* Initilialize the MIDI port
*/
short midi_init() {
unsigned char dummy;
while (midi_output_busy()) ;
*MIDI_CMD = 0xFF; /* Reset the MIDI port */
/* Wait for the ACK */
for (dummy = 0; dummy != 0xFE; ) {
while (midi_input_not_ready()) ;
dummy = *MIDI_DATA;
}
while (midi_output_busy()) ;
*MIDI_CMD = 0x3F; /* Switch the MIDI port into UART mode */
/* Wait for the ACK */
for (dummy = 0; dummy != 0xFE; ) {
while (midi_input_not_ready()) ;
dummy = *MIDI_DATA;
}
return 0;
}
/*
* Send a byte to the MIDI port
*
* Inputs:
* b = the byte to send
*/
short midi_put(unsigned char b) {
while (midi_output_busy()) ;
/* Send the byte */
*MIDI_DATA = b;
return 0;
}
/*
* Get a byte from the MIDI port
*
* Returns:
* b = the byte to send
*/
unsigned char midi_get_poll() {
while (midi_input_not_ready()) ;
return *MIDI_DATA;
}

View file

@ -24,6 +24,6 @@ extern short midi_put(unsigned char b);
* Returns: * Returns:
* b = the byte to send * b = the byte to send
*/ */
extern short midi_get_poll(); extern unsigned char midi_get_poll();
#endif #endif

View file

@ -118,7 +118,7 @@ int text_init() {
/* Initialize everything... only do a screen if it's present */ /* Initialize everything... only do a screen if it's present */
need_hires = ((*VKY3_DIP_REG & VKY3_DIP_HIRES) == VKY3_DIP_HIRES) ? 1 : 0; // need_hires = ((*VKY3_DIP_REG & VKY3_DIP_HIRES) == VKY3_DIP_HIRES) ? 1 : 0;
chan_a->master_control = MasterControlReg_A; chan_a->master_control = MasterControlReg_A;
chan_a->text_cells = ScreenText_A; chan_a->text_cells = ScreenText_A;

View file

@ -1,66 +0,0 @@
/*
* Definitions for the MIDI ports
*/
#include "midi_reg.h"
#include "dev/midi.h"
/*
* Initilialize the MIDI port
*/
short midi_init() {
*MIDI_CMD = 0xff; /* Send the command to reset the MIDI port */
// while ((*MIDI_STAT & MIDI_STAT_RX_EMPTY) == 0) {
// /* While there is data, throw it out */
// unsigned char dummy = *MIDI_DATA;
// }
*MIDI_CMD = 0x3F; /* Switch the MIDI port into UART mode */
// while ((*MIDI_STAT & MIDI_STAT_RX_EMPTY) == 0) {
// /* While there is data, throw it out */
// unsigned char dummy = *MIDI_DATA;
// }
return 0;
}
/*
* Send a byte to the MIDI port
*
* Inputs:
* b = the byte to send
*/
short midi_put(unsigned char b) {
while ((*MIDI_STAT & MIDI_STAT_TX_BUSY) != 0) {
/* Wait until the MIDI transmitter is not busy */
;
}
/* Send the byte */
*MIDI_DATA = b;
while ((*MIDI_STAT & MIDI_STAT_TX_BUSY) != 0) {
/* Wait until the MIDI transmitter is not busy */
;
}
return 0;
}
/*
* Get a byte from the MIDI port
*
* Returns:
* b = the byte to send
*/
short midi_get_poll() {
if (*MIDI_STAT & MIDI_STAT_RX_EMPTY) {
/* There's no data... return 0 */
return 0;
} else {
/* Get and return the byte */
return (short)*MIDI_DATA;
}
}

File diff suppressed because it is too large Load diff

View file

@ -353,6 +353,11 @@ extern short sys_bdev_flush(short dev);
// //
extern short sys_bdev_ioctrl(short dev, short command, unsigned char * buffer, short size); extern short sys_bdev_ioctrl(short dev, short command, unsigned char * buffer, short size);
/*
* Return the next scan code from the keyboard... 0 if nothing pending
*/
extern unsigned short sys_kbd_scancode();
/* /*
* Miscellaneous * Miscellaneous
*/ */

View file

@ -13,6 +13,13 @@
#include "dev/block.h" #include "dev/block.h"
#include "dev/fsys.h" #include "dev/fsys.h"
#include "dev/rtc.h" #include "dev/rtc.h"
#include "sys_general.h"
#if MODEL == MODEL_FOENIX_A2560K
#include "dev/kbd_mo.h"
#else
#include "dev/ps2.h"
#endif
/* /*
* Determine the correct system function implementation and call it. * Determine the correct system function implementation and call it.
@ -188,6 +195,13 @@ unsigned long syscall_dispatch(int32_t function, int32_t param0, int32_t param1,
rtc_get_time((p_time)param0); rtc_get_time((p_time)param0);
return 0; return 0;
case KFN_KBD_SCANCODE:
#if MODEL == MODEL_FOENIX_A2560K
return kbdmo_get_scancode();
#else
return kbd_get_scancode();
#endif
case KFN_ERR_MESSAGE: case KFN_ERR_MESSAGE:
return (unsigned long)err_message((short)param0); return (unsigned long)err_message((short)param0);

11012
src/mapfile

File diff suppressed because it is too large Load diff

View file

@ -314,6 +314,13 @@ short sys_bdev_ioctrl(short dev, short command, unsigned char * buffer, short si
* Miscellaneous * Miscellaneous
*/ */
/*
* Return the next scan code from the keyboard... 0 if nothing pending
*/
unsigned short sys_kbd_scancode() {
return syscall(KFN_KBD_SCANCODE);
}
const char * sys_err_message(short err_number) { const char * sys_err_message(short err_number) {
return (const char *)syscall(KFN_ERR_MESSAGE, (short)err_number); return (const char *)syscall(KFN_ERR_MESSAGE, (short)err_number);
} }