Syscalls, Timeouts, Documentation

Added syscalls, modified SDC and PATA drivers to use RTC interrupt for timeouts. Added more documentation. Starting OPL2 and OPM sound tests.
This commit is contained in:
Peter Weingartner 2021-11-04 20:09:53 -04:00
parent 95856b80dc
commit 8a9878d03d
29 changed files with 10027 additions and 31022 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
docs/OS Layout.odg Normal file

Binary file not shown.

View file

@ -150,7 +150,7 @@ short cmd_cd(short screen, int argc, char * argv[]) {
TRACE("cmd_cd");
if (argc > 1) {
short result = fsys_setcwd(argv[1]);
short result = fsys_set_cwd(argv[1]);
if (result < 0) {
err_print(screen, "Unable to change directory", result);
return result;
@ -175,7 +175,7 @@ short cmd_pwd(short screen, int argc, char * argv[]) {
TRACE("cmd_pwd");
short result = fsys_getcwd(buffer, 128);
short result = fsys_get_cwd(buffer, 128);
if (result < 0) {
err_print(screen, "Unable to get current directory", result);
return result;

View file

@ -17,6 +17,7 @@
#include "rtc_reg.h"
#include "dev/rtc.h"
#include "dev/text_screen_iii.h"
#include "snd/codec.h"
#include "vicky_general.h"
#define MAX_SETTING_NAME 64
@ -445,6 +446,23 @@ short cli_font_get(short channel, char * value) {
return 0;
}
/*
* Volume setter -- SET VOLUME <value>
*/
short cli_volume_set(short channel, char * value) {
unsigned char volume = (unsigned char)cli_eval_number(value);
codec_set_volume(volume);
return 0;
}
/*
* Volume getter -- GET VOLUME
*/
short cli_volume_get(short channel, char * value) {
sprintf(value, "%d", codec_get_volume());
return 0;
}
/*
* Initialize the settings tables
*/
@ -457,4 +475,5 @@ void cli_set_init() {
cli_set_register("SOF", "SOF 1|0 -- Enable or disable the Start of Frame interrupt", cli_sof_set, cli_sof_get);
cli_set_register("TIME", "TIME HH:MM:SS -- set the time in the realtime clock", cli_time_set, cli_time_get);
cli_set_register("FONT", "FONT <path> -- set a font for the display", cli_font_set, cli_font_get);
cli_set_register("VOLUME", "VOLUME <0 - 255> -- set the master volume", cli_volume_set, cli_volume_get);
}

View file

@ -6,6 +6,7 @@
#include "sound_cmds.h"
#include "sound_reg.h"
#include "snd/psg.h"
#include "snd/opl2.h"
#include "dev/midi.h"
/*
@ -18,20 +19,20 @@ short psg_test(short channel, int argc, char * argv[]) {
psg_tone(0, 34923);
psg_attenuation(0, 0);
target_time = timers_jiffies() + 20;
while (target_time > timers_jiffies()) ;
target_time = rtc_get_ticks() + 300;
while (target_time > rtc_get_ticks()) ;
psg_tone(1, 44000);
psg_attenuation(1, 0);
target_time = timers_jiffies() + 20;
while (target_time > timers_jiffies()) ;
target_time = rtc_get_ticks() + 300;
while (target_time > rtc_get_ticks()) ;
psg_tone(2, 52325);
psg_attenuation(2, 0);
target_time = timers_jiffies() + 60;
while (target_time > timers_jiffies()) ;
target_time = rtc_get_ticks() + 1000;
while (target_time > rtc_get_ticks()) ;
psg_attenuation(0, 15);
psg_tone(0, 0);
@ -109,8 +110,8 @@ short opl3_test(short channel, int argc, char * argv[]) {
}
}
target_time = timers_jiffies() + 60;
while (target_time > timers_jiffies()) ;
target_time = rtc_get_ticks() + 1000;
while (target_time > rtc_get_ticks()) ;
i = 0;
while (1) {
@ -126,6 +127,32 @@ short opl3_test(short channel, int argc, char * argv[]) {
return 0;
}
/*
* Perform a transmit test on the MIDI ports
*/
short midi_tx_test(short channel, int argc, char * argv[]) {
const char note_on[] = { 0x90, 0x3c, 0xff };
const char note_off[] = { 0x80, 0x3c, 0x00 };
char message[80];
unsigned short scancode = 0;
int i;
midi_init();
for (i = 0; i < 3; i++) {
midi_put(note_on[i]);
}
for (i = 0; i < 65535 * 20; i++) ;
for (i = 0; i < 3; i++) {
midi_put(note_off[i]);
}
return 0;
}
/*
* Perform a receive test on the MIDI ports
*/
@ -183,7 +210,7 @@ short midi_loop_test(short channel, int argc, char * argv[]) {
while (sys_kbd_scancode() != 0x02) ;
output = 0xF8;
output = 1;
while (scancode != 0x01) {
sprintf(message, "Sending: ");
sys_chan_write(channel, message, strlen(message));
@ -196,9 +223,278 @@ short midi_loop_test(short channel, int argc, char * argv[]) {
sys_chan_write(channel, message, strlen(message));
scancode = sys_kbd_scancode();
output++;
if (output > 0xfe) {
output = 1;
}
}
sys_chan_write(channel, "\n", 1);
return 0;
}
/*
* Test the OPL2
*/
short opl2_test(short channel, int argc, char * argv[]) {
unsigned char i;
OPN2_INT_BASE[OPN2_22_LFO] = 0; /* LFO off */
OPN2_INT_BASE[OPN2_27_CHANEL_3_MODE] = 0; /* chanel 3 in normal mode */
/* switch off all chanal */
for (i = 0; i < 7; i++) {
OPN2_INT_BASE[OPN2_28_KEY_ON_OFF] = i;
}
/* ADC off */
OPN2_INT_BASE[OPN2_2B_ADC_EN] = 0;
/* DT1/MUL */
OPN2_INT_BASE[OPN2_30_ADSR__DT1_MUL__CH1_OP1] = 0x71;
OPN2_INT_BASE[OPN2_31_ADSR__DT1_MUL__CH2_OP1] = 0x71;
OPN2_INT_BASE[OPN2_32_ADSR__DT1_MUL__CH3_OP1] = 0x71;
OPN2_INT_BASE[OPN2_30_ADSR__DT1_MUL__CH1_OP5] = 0x71;
OPN2_INT_BASE[OPN2_31_ADSR__DT1_MUL__CH2_OP5] = 0x71;
OPN2_INT_BASE[OPN2_32_ADSR__DT1_MUL__CH3_OP5] = 0x71;
OPN2_INT_BASE[OPN2_34_ADSR__DT1_MUL__CH1_OP2] = 0x0D;
OPN2_INT_BASE[OPN2_35_ADSR__DT1_MUL__CH2_OP2] = 0x0D;
OPN2_INT_BASE[OPN2_36_ADSR__DT1_MUL__CH3_OP2] = 0x0D;
OPN2_INT_BASE[OPN2_34_ADSR__DT1_MUL__CH1_OP6] = 0x0D;
OPN2_INT_BASE[OPN2_35_ADSR__DT1_MUL__CH2_OP6] = 0x0D;
OPN2_INT_BASE[OPN2_36_ADSR__DT1_MUL__CH3_OP6] = 0x0D;
OPN2_INT_BASE[OPN2_38_ADSR__DT1_MUL__CH1_OP3] = 0x33;
OPN2_INT_BASE[OPN2_39_ADSR__DT1_MUL__CH2_OP3] = 0x33;
OPN2_INT_BASE[OPN2_3A_ADSR__DT1_MUL__CH3_OP3] = 0x33;
OPN2_INT_BASE[OPN2_38_ADSR__DT1_MUL__CH1_OP7] = 0x33;
OPN2_INT_BASE[OPN2_39_ADSR__DT1_MUL__CH2_OP7] = 0x33;
OPN2_INT_BASE[OPN2_3A_ADSR__DT1_MUL__CH3_OP7] = 0x33;
OPN2_INT_BASE[OPN2_3C_ADSR__DT1_MUL__CH1_OP4] = 0x01;
OPN2_INT_BASE[OPN2_3D_ADSR__DT1_MUL__CH2_OP4] = 0x01;
OPN2_INT_BASE[OPN2_3E_ADSR__DT1_MUL__CH3_OP4] = 0x01;
OPN2_INT_BASE[OPN2_3C_ADSR__DT1_MUL__CH1_OP8] = 0x01;
OPN2_INT_BASE[OPN2_3D_ADSR__DT1_MUL__CH2_OP8] = 0x01;
OPN2_INT_BASE[OPN2_3E_ADSR__DT1_MUL__CH3_OP8] = 0x01;
/* Total Level */
OPN2_INT_BASE[OPN2_40_ADSR__LT__CH1_OP1] = 0x23;
OPN2_INT_BASE[OPN2_41_ADSR__LT__CH2_OP1] = 0x23;
OPN2_INT_BASE[OPN2_42_ADSR__LT__CH3_OP1] = 0x23;
OPN2_INT_BASE[OPN2_40_ADSR__LT__CH1_OP5] = 0x23;
OPN2_INT_BASE[OPN2_41_ADSR__LT__CH2_OP5] = 0x23;
OPN2_INT_BASE[OPN2_42_ADSR__LT__CH3_OP5] = 0x23;
OPN2_INT_BASE[OPN2_44_ADSR__LT__CH1_OP2] = 0x2D;
OPN2_INT_BASE[OPN2_45_ADSR__LT__CH2_OP2] = 0x2D;
OPN2_INT_BASE[OPN2_46_ADSR__LT__CH3_OP2] = 0x2D;
OPN2_INT_BASE[OPN2_44_ADSR__LT__CH1_OP6] = 0x2D;
OPN2_INT_BASE[OPN2_45_ADSR__LT__CH2_OP6] = 0x2D;
OPN2_INT_BASE[OPN2_46_ADSR__LT__CH3_OP6] = 0x2D;
OPN2_INT_BASE[OPN2_48_ADSR__LT__CH1_OP3] = 0x26;
OPN2_INT_BASE[OPN2_49_ADSR__LT__CH2_OP3] = 0x26;
OPN2_INT_BASE[OPN2_4A_ADSR__LT__CH3_OP3] = 0x26;
OPN2_INT_BASE[OPN2_48_ADSR__LT__CH1_OP7] = 0x26;
OPN2_INT_BASE[OPN2_49_ADSR__LT__CH2_OP7] = 0x26;
OPN2_INT_BASE[OPN2_4A_ADSR__LT__CH3_OP7] = 0x26;
OPN2_INT_BASE[OPN2_4C_ADSR__LT__CH1_OP4] = 0x00;
OPN2_INT_BASE[OPN2_4D_ADSR__LT__CH2_OP4] = 0x00;
OPN2_INT_BASE[OPN2_4E_ADSR__LT__CH3_OP4] = 0x00;
OPN2_INT_BASE[OPN2_4C_ADSR__LT__CH1_OP8] = 0x00;
OPN2_INT_BASE[OPN2_4D_ADSR__LT__CH2_OP8] = 0x00;
OPN2_INT_BASE[OPN2_4E_ADSR__LT__CH3_OP8] = 0x00;
/* RS/AR */
OPN2_INT_BASE[OPN2_50_ADSR__SR_AR__CH1_OP1] = 0x5F;
OPN2_INT_BASE[OPN2_51_ADSR__SR_AR__CH2_OP1] = 0x5F;
OPN2_INT_BASE[OPN2_52_ADSR__SR_AR__CH3_OP1] = 0x5F;
OPN2_INT_BASE[OPN2_50_ADSR__SR_AR__CH1_OP5] = 0x5F;
OPN2_INT_BASE[OPN2_51_ADSR__SR_AR__CH2_OP5] = 0x5F;
OPN2_INT_BASE[OPN2_52_ADSR__SR_AR__CH3_OP5] = 0x5F;
OPN2_INT_BASE[OPN2_54_ADSR__SR_AR__CH1_OP2] = 0x99;
OPN2_INT_BASE[OPN2_55_ADSR__SR_AR__CH2_OP2] = 0x99;
OPN2_INT_BASE[OPN2_56_ADSR__SR_AR__CH3_OP2] = 0x99;
OPN2_INT_BASE[OPN2_54_ADSR__SR_AR__CH1_OP6] = 0x99;
OPN2_INT_BASE[OPN2_55_ADSR__SR_AR__CH2_OP6] = 0x99;
OPN2_INT_BASE[OPN2_56_ADSR__SR_AR__CH3_OP6] = 0x99;
OPN2_INT_BASE[OPN2_58_ADSR__SR_AR__CH1_OP3] = 0x5F;
OPN2_INT_BASE[OPN2_59_ADSR__SR_AR__CH2_OP3] = 0x5F;
OPN2_INT_BASE[OPN2_5A_ADSR__SR_AR__CH3_OP3] = 0x5F;
OPN2_INT_BASE[OPN2_58_ADSR__SR_AR__CH1_OP7] = 0x5F;
OPN2_INT_BASE[OPN2_59_ADSR__SR_AR__CH2_OP7] = 0x5F;
OPN2_INT_BASE[OPN2_5A_ADSR__SR_AR__CH3_OP7] = 0x5F;
OPN2_INT_BASE[OPN2_5C_ADSR__SR_AR__CH1_OP4] = 0x94;
OPN2_INT_BASE[OPN2_5D_ADSR__SR_AR__CH2_OP4] = 0x94;
OPN2_INT_BASE[OPN2_5E_ADSR__SR_AR__CH3_OP4] = 0x94;
OPN2_INT_BASE[OPN2_5C_ADSR__SR_AR__CH1_OP8] = 0x94;
OPN2_INT_BASE[OPN2_5D_ADSR__SR_AR__CH2_OP8] = 0x94;
OPN2_INT_BASE[OPN2_5E_ADSR__SR_AR__CH3_OP8] = 0x94;
/* AM/D1R */
OPN2_INT_BASE[OPN2_60_ADSR__AM_D1R__CH1_OP1] = 0x07;
OPN2_INT_BASE[OPN2_61_ADSR__AM_D1R__CH2_OP1] = 0x07;
OPN2_INT_BASE[OPN2_62_ADSR__AM_D1R__CH3_OP1] = 0x07;
OPN2_INT_BASE[OPN2_60_ADSR__AM_D1R__CH1_OP5] = 0x07;
OPN2_INT_BASE[OPN2_61_ADSR__AM_D1R__CH2_OP5] = 0x07;
OPN2_INT_BASE[OPN2_62_ADSR__AM_D1R__CH3_OP5] = 0x07;
OPN2_INT_BASE[OPN2_64_ADSR__AM_D1R__CH1_OP2] = 0x07;
OPN2_INT_BASE[OPN2_65_ADSR__AM_D1R__CH2_OP2] = 0x07;
OPN2_INT_BASE[OPN2_66_ADSR__AM_D1R__CH3_OP2] = 0x07;
OPN2_INT_BASE[OPN2_64_ADSR__AM_D1R__CH1_OP6] = 0x07;
OPN2_INT_BASE[OPN2_65_ADSR__AM_D1R__CH2_OP6] = 0x07;
OPN2_INT_BASE[OPN2_66_ADSR__AM_D1R__CH3_OP6] = 0x07;
OPN2_INT_BASE[OPN2_68_ADSR__AM_D1R__CH1_OP3] = 0x05;
OPN2_INT_BASE[OPN2_69_ADSR__AM_D1R__CH2_OP3] = 0x05;
OPN2_INT_BASE[OPN2_6A_ADSR__AM_D1R__CH3_OP3] = 0x05;
OPN2_INT_BASE[OPN2_68_ADSR__AM_D1R__CH1_OP7] = 0x05;
OPN2_INT_BASE[OPN2_69_ADSR__AM_D1R__CH2_OP7] = 0x05;
OPN2_INT_BASE[OPN2_6A_ADSR__AM_D1R__CH3_OP7] = 0x05;
OPN2_INT_BASE[OPN2_6C_ADSR__AM_D1R__CH1_OP4] = 0x07;
OPN2_INT_BASE[OPN2_6D_ADSR__AM_D1R__CH2_OP4] = 0x07;
OPN2_INT_BASE[OPN2_6E_ADSR__AM_D1R__CH3_OP4] = 0x07;
OPN2_INT_BASE[OPN2_6C_ADSR__AM_D1R__CH1_OP8] = 0x07;
OPN2_INT_BASE[OPN2_6D_ADSR__AM_D1R__CH2_OP8] = 0x07;
OPN2_INT_BASE[OPN2_6E_ADSR__AM_D1R__CH3_OP8] = 0x07;
/* D2R */
OPN2_INT_BASE[OPN2_70_ADSR__D2R__CH1_OP1] = 0x02;
OPN2_INT_BASE[OPN2_71_ADSR__D2R__CH2_OP1] = 0x02;
OPN2_INT_BASE[OPN2_72_ADSR__D2R__CH3_OP1] = 0x02;
OPN2_INT_BASE[OPN2_70_ADSR__D2R__CH1_OP5] = 0x02;
OPN2_INT_BASE[OPN2_71_ADSR__D2R__CH2_OP5] = 0x02;
OPN2_INT_BASE[OPN2_72_ADSR__D2R__CH3_OP5] = 0x02;
OPN2_INT_BASE[OPN2_74_ADSR__D2R__CH1_OP2] = 0x02;
OPN2_INT_BASE[OPN2_75_ADSR__D2R__CH2_OP2] = 0x02;
OPN2_INT_BASE[OPN2_76_ADSR__D2R__CH3_OP2] = 0x02;
OPN2_INT_BASE[OPN2_74_ADSR__D2R__CH1_OP6] = 0x02;
OPN2_INT_BASE[OPN2_75_ADSR__D2R__CH2_OP6] = 0x02;
OPN2_INT_BASE[OPN2_76_ADSR__D2R__CH3_OP6] = 0x02;
OPN2_INT_BASE[OPN2_78_ADSR__D2R__CH1_OP3] = 0x02;
OPN2_INT_BASE[OPN2_79_ADSR__D2R__CH2_OP3] = 0x02;
OPN2_INT_BASE[OPN2_7A_ADSR__D2R__CH3_OP3] = 0x02;
OPN2_INT_BASE[OPN2_78_ADSR__D2R__CH1_OP7] = 0x02;
OPN2_INT_BASE[OPN2_79_ADSR__D2R__CH2_OP7] = 0x02;
OPN2_INT_BASE[OPN2_7A_ADSR__D2R__CH3_OP7] = 0x02;
OPN2_INT_BASE[OPN2_7C_ADSR__D2R__CH1_OP4] = 0x02;
OPN2_INT_BASE[OPN2_7D_ADSR__D2R__CH2_OP4] = 0x02;
OPN2_INT_BASE[OPN2_7E_ADSR__D2R__CH3_OP4] = 0x02;
OPN2_INT_BASE[OPN2_7C_ADSR__D2R__CH1_OP8] = 0x02;
OPN2_INT_BASE[OPN2_7D_ADSR__D2R__CH2_OP8] = 0x02;
OPN2_INT_BASE[OPN2_7E_ADSR__D2R__CH3_OP8] = 0x02;
/* D1L/RR */
OPN2_INT_BASE[OPN2_80_ADSR__D1L_RR__CH1_OP1] = 0x11;
OPN2_INT_BASE[OPN2_81_ADSR__D1L_RR__CH2_OP1] = 0x11;
OPN2_INT_BASE[OPN2_82_ADSR__D1L_RR__CH3_OP1] = 0x11;
OPN2_INT_BASE[OPN2_80_ADSR__D1L_RR__CH1_OP5] = 0x11;
OPN2_INT_BASE[OPN2_81_ADSR__D1L_RR__CH2_OP5] = 0x11;
OPN2_INT_BASE[OPN2_82_ADSR__D1L_RR__CH3_OP5] = 0x11;
OPN2_INT_BASE[OPN2_84_ADSR__D1L_RR__CH1_OP2] = 0x11;
OPN2_INT_BASE[OPN2_85_ADSR__D1L_RR__CH2_OP2] = 0x11;
OPN2_INT_BASE[OPN2_86_ADSR__D1L_RR__CH3_OP2] = 0x11;
OPN2_INT_BASE[OPN2_84_ADSR__D1L_RR__CH1_OP6] = 0x11;
OPN2_INT_BASE[OPN2_85_ADSR__D1L_RR__CH2_OP6] = 0x11;
OPN2_INT_BASE[OPN2_86_ADSR__D1L_RR__CH3_OP6] = 0x11;
OPN2_INT_BASE[OPN2_88_ADSR__D1L_RR__CH1_OP3] = 0x11;
OPN2_INT_BASE[OPN2_89_ADSR__D1L_RR__CH2_OP3] = 0x11;
OPN2_INT_BASE[OPN2_8A_ADSR__D1L_RR__CH3_OP3] = 0x11;
OPN2_INT_BASE[OPN2_88_ADSR__D1L_RR__CH1_OP7] = 0x11;
OPN2_INT_BASE[OPN2_89_ADSR__D1L_RR__CH2_OP7] = 0x11;
OPN2_INT_BASE[OPN2_8A_ADSR__D1L_RR__CH3_OP7] = 0x11;
OPN2_INT_BASE[OPN2_8C_ADSR__D1L_RR__CH1_OP4] = 0xA6;
OPN2_INT_BASE[OPN2_8D_ADSR__D1L_RR__CH2_OP4] = 0xA6;
OPN2_INT_BASE[OPN2_8E_ADSR__D1L_RR__CH3_OP4] = 0xA6;
OPN2_INT_BASE[OPN2_8C_ADSR__D1L_RR__CH1_OP8] = 0xA6;
OPN2_INT_BASE[OPN2_8D_ADSR__D1L_RR__CH2_OP8] = 0xA6;
OPN2_INT_BASE[OPN2_8E_ADSR__D1L_RR__CH3_OP8] = 0xA6;
/* Proprietary */
OPN2_INT_BASE[OPN2_90_ADSR__D1L_RR__CH1_OP1] = 0x00;
OPN2_INT_BASE[OPN2_91_ADSR__D1L_RR__CH2_OP1] = 0x00;
OPN2_INT_BASE[OPN2_92_ADSR__D1L_RR__CH3_OP1] = 0x00;
OPN2_INT_BASE[OPN2_90_ADSR__D1L_RR__CH4_OP1] = 0x00;
OPN2_INT_BASE[OPN2_91_ADSR__D1L_RR__CH5_OP1] = 0x00;
OPN2_INT_BASE[OPN2_92_ADSR__D1L_RR__CH6_OP1] = 0x00;
OPN2_INT_BASE[OPN2_94_ADSR__D1L_RR__CH1_OP2] = 0x00;
OPN2_INT_BASE[OPN2_95_ADSR__D1L_RR__CH2_OP2] = 0x00;
OPN2_INT_BASE[OPN2_96_ADSR__D1L_RR__CH3_OP2] = 0x00;
OPN2_INT_BASE[OPN2_94_ADSR__D1L_RR__CH4_OP2] = 0x00;
OPN2_INT_BASE[OPN2_95_ADSR__D1L_RR__CH5_OP2] = 0x00;
OPN2_INT_BASE[OPN2_96_ADSR__D1L_RR__CH6_OP2] = 0x00;
OPN2_INT_BASE[OPN2_98_ADSR__D1L_RR__CH1_OP3] = 0x00;
OPN2_INT_BASE[OPN2_99_ADSR__D1L_RR__CH2_OP3] = 0x00;
OPN2_INT_BASE[OPN2_9A_ADSR__D1L_RR__CH3_OP3] = 0x00;
OPN2_INT_BASE[OPN2_98_ADSR__D1L_RR__CH4_OP3] = 0x00;
OPN2_INT_BASE[OPN2_99_ADSR__D1L_RR__CH5_OP3] = 0x00;
OPN2_INT_BASE[OPN2_9A_ADSR__D1L_RR__CH6_OP3] = 0x00;
OPN2_INT_BASE[OPN2_9C_ADSR__D1L_RR__CH1_OP4] = 0x00;
OPN2_INT_BASE[OPN2_9D_ADSR__D1L_RR__CH2_OP4] = 0x00;
OPN2_INT_BASE[OPN2_9E_ADSR__D1L_RR__CH3_OP4] = 0x00;
OPN2_INT_BASE[OPN2_9C_ADSR__D1L_RR__CH4_OP4] = 0x00;
OPN2_INT_BASE[OPN2_9D_ADSR__D1L_RR__CH5_OP4] = 0x00;
OPN2_INT_BASE[OPN2_9E_ADSR__D1L_RR__CH6_OP4] = 0x00;
/* Feedback/algorithm */
OPN2_INT_BASE[OPN2_B0_CH1_FEEDBACK_ALGO] = 0x32;
OPN2_INT_BASE[OPN2_B1_CH2_FEEDBACK_ALGO] = 0x32;
OPN2_INT_BASE[OPN2_B2_CH3_FEEDBACK_ALGO] = 0x32;
/* Both speakers on */
OPN2_INT_BASE[OPN2_B4_CH1_L_R_AMS_FMS] = 0xC0;
OPN2_INT_BASE[OPN2_B5_CH2_L_R_AMS_FMS] = 0xC0;
OPN2_INT_BASE[OPN2_B6_CH3_L_R_AMS_FMS] = 0xC0;
/* Set frequency */
OPN2_INT_BASE[OPN2_A4_CH1_OCTAVE_FRECANCY_H] = 0x23;
OPN2_INT_BASE[OPN2_A5_CH2_OCTAVE_FRECANCY_H] = 0x22;
OPN2_INT_BASE[OPN2_A6_CH3_OCTAVE_FRECANCY_H] = 0x22;
OPN2_INT_BASE[OPN2_A0_CH1_FRECANCY_L] = 0x96;
OPN2_INT_BASE[OPN2_A1_CH2_FRECANCY_L] = 0x96;
OPN2_INT_BASE[OPN2_A2_CH3_FRECANCY_L] = 0x24;
/* Key off */
OPN2_INT_BASE[OPN2_28_KEY_ON_OFF] = 0x00;
for (i = 0xF0; i < 0xF7; i++) {
OPN2_INT_BASE[OPN2_28_KEY_ON_OFF] = i;
}
long target_ticks = rtc_get_ticks();
while (target_ticks > rtc_get_ticks() + 300) ;
for (i = 0x00; i < 0x07; i++) {
OPN2_INT_BASE[OPN2_28_KEY_ON_OFF] = i;
}
return 0;
}

View file

@ -15,6 +15,16 @@ extern short psg_test(short channel, int argc, char * argv[]);
*/
extern short opl3_test(short channel, int argc, char * argv[]);
/*
* Test the OPL2
*/
extern short opl2_test(short channel, int argc, char * argv[]);
/*
* Perform a transmit test on the MIDI ports
*/
extern short midi_tx_test(short channel, int argc, char * argv[]);
/*
* Perform a receive test on the MIDI ports
*/

View file

@ -312,6 +312,8 @@ static t_cli_test_feature cli_test_features[] = {
{"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},
{"MIDITX", "MIDITX: send a note to a MIDI keyboard", midi_tx_test},
{"OPL2", "OPL2: test the OPL2 sound chip", opl2_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},

View file

@ -177,7 +177,7 @@ short fsys_opendir(const char * path) {
/* Try to open the directory */
if (path[0] == 0) {
char cwd[128];
fsys_getcwd(cwd, 128);
fsys_get_cwd(cwd, 128);
fres = f_opendir(&g_directory[dir], cwd);
} else {
fres = f_opendir(&g_directory[dir], path);
@ -422,14 +422,14 @@ short fsys_rename(const char * old_path, const char * new_path) {
* Returns:
* 0 on success, negative number on failure.
*/
short fsys_setcwd(const char * path) {
short fsys_set_cwd(const char * path) {
FRESULT result;
result = f_chdir(path);
if (result == FR_OK) {
return 0;
} else {
log_num(LOG_ERROR, "fsys_setcwd error: ", result);
log_num(LOG_ERROR, "fsys_set_cwd error: ", result);
return fatfs_to_foenix(result);
}
}
@ -444,7 +444,7 @@ short fsys_setcwd(const char * path) {
* Returns:
* 0 on success, negative number on failure.
*/
short fsys_getcwd(char * path, short size) {
short fsys_get_cwd(char * path, short size) {
FRESULT result;
f_chdrive("");
@ -452,7 +452,7 @@ short fsys_getcwd(char * path, short size) {
if (result == FR_OK) {
return 0;
} else {
log_num(LOG_ERROR, "fsys_getcwd error: ", result);
log_num(LOG_ERROR, "fsys_get_cwd error: ", result);
return fatfs_to_foenix(result);
}
}

View file

@ -195,7 +195,7 @@ extern short fsys_rename(const char * old_path, const char * new_path);
* Returns:
* 0 on success, negative number on failure.
*/
extern short fsys_setcwd(const char * path);
extern short fsys_set_cwd(const char * path);
/**
* Get the current working drive and directory
@ -207,7 +207,7 @@ extern short fsys_setcwd(const char * path);
* Returns:
* 0 on success, negative number on failure.
*/
extern short fsys_getcwd(char * path, short size);
extern short fsys_get_cwd(char * path, short size);
/*
* Load a file into memory at the designated destination address.

View file

@ -10,8 +10,16 @@
#include "dev/block.h"
#include "dev/pata.h"
#include "dev/text_screen_iii.h"
#include "dev/rtc.h"
#include "pata_reg.h"
//
// Constants
//
#define PATA_TIMEOUT_MS 300
#define PATA_WAIT_MS 100
//
// Variables
//
@ -30,16 +38,22 @@ short g_pata_status = PATA_STAT_NOINIT; // Status of the PATA interface
// 0 on success (PATA drive is no longer busy), DEV_TIMEOUT on timeout
//
short pata_wait_not_busy() {
short count = MAX_TRIES_BUSY;
long target_ticks;
long ticks;
char status;
TRACE("pata_wait_not_busy");
target_ticks = rtc_get_ticks() + PATA_TIMEOUT_MS;
do {
status = *PATA_CMD_STAT;
} while ((status & PATA_STAT_BSY) && (count-- > 0));
ticks = rtc_get_ticks();
} while ((status & PATA_STAT_BSY) && (target_ticks > ticks));
if (count == 0) {
if (target_ticks <= ticks) {
log(LOG_ERROR, "pata_wait_not_busy: timeout");
log_num(LOG_ERROR, "target_ticks: ", (int)target_ticks);
log_num(LOG_ERROR, "ticks: ", (int)ticks);
return DEV_TIMEOUT;
} else {
return 0;
@ -53,16 +67,20 @@ short pata_wait_not_busy() {
// 0 on success (PATA drive is ready), DEV_TIMEOUT on timeout
//
short pata_wait_ready() {
short count = MAX_TRIES_BUSY;
long target_ticks;
long ticks;
char status;
TRACE("pata_wait_ready");
target_ticks = rtc_get_ticks() + PATA_TIMEOUT_MS;
do {
status = *PATA_CMD_STAT;
} while (((status & PATA_STAT_DRDY) == 0) && (count-- > 0));
ticks = rtc_get_ticks();
} while (((status & PATA_STAT_DRDY) == 0) && (target_ticks > ticks));
if (count == 0) {
if (target_ticks <= ticks) {
log(LOG_ERROR, "pata_wait_ready: timeout");
return DEV_TIMEOUT;
} else {
return 0;
@ -76,7 +94,8 @@ short pata_wait_ready() {
// 0 on success (PATA drive is ready and not busy), DEV_TIMEOUT on timeout
//
short pata_wait_ready_not_busy() {
short count = MAX_TRIES_BUSY;
long target_ticks;
long ticks;
char status;
TRACE("pata_wait_ready_not_busy");
@ -85,11 +104,17 @@ short pata_wait_ready_not_busy() {
// status = *PATA_CMD_STAT;
// } while (((status & (PATA_STAT_DRDY | PATA_STAT_BSY)) != PATA_STAT_DRDY) && (count-- > 0));
target_ticks = rtc_get_ticks() + PATA_TIMEOUT_MS;
do {
while ((*PATA_CMD_STAT & PATA_STAT_DRDY) != PATA_STAT_DRDY);
} while ((*PATA_CMD_STAT & PATA_STAT_BSY) == PATA_STAT_BSY);
while (((*PATA_CMD_STAT & PATA_STAT_DRDY) != PATA_STAT_DRDY) && (target_ticks > ticks)) {
ticks = rtc_get_ticks();
}
} while (((*PATA_CMD_STAT & PATA_STAT_BSY) == PATA_STAT_BSY) && (target_ticks > ticks));
if (count == 0) {
if (target_ticks <= ticks) {
log(LOG_ERROR, "pata_wait_ready_not_busy: timeout");
log_num(LOG_ERROR, "target_ticks: ", (int)target_ticks);
log_num(LOG_ERROR, "ticks: ", (int)ticks);
return DEV_TIMEOUT;
} else {
return 0;
@ -103,16 +128,20 @@ short pata_wait_ready_not_busy() {
// 0 on success (PATA drive is ready to transfer data), DEV_TIMEOUT on timeout
//
short pata_wait_data_request() {
short count = MAX_TRIES_BUSY;
long target_ticks;
long ticks;
char status;
TRACE("pata_wait_data_request");
target_ticks = rtc_get_ticks() + PATA_TIMEOUT_MS;
do {
status = *PATA_CMD_STAT;
} while (((status & PATA_STAT_DRQ) != PATA_STAT_DRQ) && (count-- > 0));
ticks = rtc_get_ticks();
} while (((status & PATA_STAT_DRQ) != PATA_STAT_DRQ) && (target_ticks > ticks));
if (count == 0) {
if (target_ticks <= ticks) {
log(LOG_ERROR, "pata_wait_data_request: timeout");
return DEV_TIMEOUT;
} else {
return 0;
@ -289,6 +318,7 @@ short pata_read(long lba, unsigned char * buffer, short size) {
}
short pata_flush_cache() {
long target_ticks;
short i;
unsigned short *wptr;
unsigned char status;
@ -314,8 +344,9 @@ short pata_flush_cache() {
*PATA_CMD_STAT = 0xE7; // PATA_CMD_FLUSH_CACHE;
// Give the controller some time...
for (i = 0; i < 32000; i++) ;
// Give the controller some time (100ms?)...
target_ticks = rtc_get_ticks() + PATA_WAIT_MS;
while (target_ticks > rtc_get_ticks()) ;
if (pata_wait_ready_not_busy()) {
return DEV_TIMEOUT;
@ -347,6 +378,7 @@ short pata_flush_cache() {
// number of chars written, any negative number is an error code
//
short pata_write(long lba, const unsigned char * buffer, short size) {
long target_ticks;
short i;
unsigned short *wptr;
unsigned char status;
@ -378,8 +410,9 @@ short pata_write(long lba, const unsigned char * buffer, short size) {
*PATA_CMD_STAT = PATA_CMD_WRITE_SECTOR; // Issue the WRITE command
// Give the controller some time...
for (i = 0; i < 32000; i++) ;
// Give the controller some time (100ms?)...
target_ticks = rtc_get_ticks() + PATA_WAIT_MS;
while (target_ticks > rtc_get_ticks()) ;
if (pata_wait_ready_not_busy()) {
/* Turn off the HDD LED */

View file

@ -8,10 +8,11 @@
#include "interrupt.h"
#include "vicky_general.h"
#include "dev/ps2.h"
#include "dev/rtc.h"
#include "dev/text_screen_iii.h"
#include "rsrc/bitmaps/mouse_pointer.h"
#define PS2_RETRY_MAX 20000 /* For timeout purposes when sending a command */
#define PS2_TIMEOUT_MS 400
#define PS2_RESEND_MAX 50 /* Number of times we'll repeat a command on receiving a 0xFE reply */
/*
@ -252,10 +253,13 @@ char g_us_sc_ctrl_shift[] = {
* 0 if successful, -1 if there was no response after PS2_RETRY_MAX tries
*/
short ps2_wait_out() {
short count = 0;
long target_ticks;
log(LOG_TRACE, "ps2_wait_out");
target_ticks = rtc_get_ticks() + PS2_TIMEOUT_MS;
while ((*PS2_STATUS & PS2_STAT_OBF) == 0) {
if (count++ > PS2_RETRY_MAX) {
if (rtc_get_ticks() > target_ticks) {
return -1;
}
}
@ -270,10 +274,13 @@ short ps2_wait_out() {
* 0 if successful, -1 if there was no response after PS2_RETRY_MAX tries
*/
short ps2_wait_in() {
short count = 0;
long target_ticks;
log(LOG_TRACE, "ps2_wait_in");
target_ticks = rtc_get_ticks() + PS2_TIMEOUT_MS;
while ((*PS2_STATUS & PS2_STAT_IBF) != 0) {
if (count++ > PS2_RETRY_MAX) {
if (rtc_get_ticks() > target_ticks) {
return -1;
}
}

View file

@ -9,7 +9,6 @@
#include "rtc_reg.h"
static long rtc_ticks;
static long sof_ticks;
/*
* Interrupt handler for the real time clock
@ -18,10 +17,8 @@ void rtc_handle_int() {
unsigned char flags;
flags = *RTC_FLAGS;
//if (flags | RTC_PF) {
/* Peridic interrupt: increment the ticks counter */
rtc_ticks++;
//}
int_clear(INT_RTC);
}
@ -34,22 +31,32 @@ void rtc_init() {
unsigned char rates;
unsigned char enables;
log(LOG_TRACE, "rtc_init");
int_disable(INT_RTC);
/* Wait to actually enable PIE until later */
*RTC_ENABLES = 0;
/* Set the periodic interrupt to 250 ms */
*RTC_RATES = 0x0E;
/* Set the periodic interrupt to 976 microsecs */
*RTC_RATES = RTC_RATE_976us;
/* Make sure the RTC is on */
*RTC_CTRL = RTC_STOP;
int_register(INT_RTC, rtc_handle_int);
/* Enable the periodic interrupt */
flags = *RTC_FLAGS;
*RTC_ENABLES = RTC_PIE;
// int_enable(INT_RTC);
int_enable(INT_RTC);
}
/*
* Make sure the RTC tick counter is enabled
*/
void rtc_enable_ticks() {
unsigned char flags = *RTC_FLAGS;
*RTC_ENABLES = RTC_PIE;
int_enable(INT_RTC);
}
/*
@ -205,14 +212,6 @@ void rtc_get_time(p_time time) {
time->second = bcd_to_i(second_bcd);
}
/*
* Get the number of jiffies since the system last reset.
* A "jiffy" should be considered to be 1/60 second.
*/
long rtc_get_jiffies() {
return sof_ticks;
}
/*
* Get the number of ticks since the system last booted.
*

View file

@ -21,6 +21,11 @@ typedef struct s_time {
*/
extern void rtc_init();
/*
* Make sure the RTC tick counter is enabled
*/
extern void rtc_enable_ticks();
/*
* Set the time on the RTC
*
@ -50,10 +55,4 @@ extern void rtc_get_time(p_time time);
*/
extern long rtc_get_ticks();
/*
* Get the number of jiffies since the system last reset.
* A "jiffy" should be considered to be 1/60 second.
*/
extern long rtc_get_jiffies();
#endif

View file

@ -9,9 +9,16 @@
#include "indicators.h"
#include "dev/block.h"
#include "sdc_reg.h"
#include "dev/rtc.h"
#include "dev/sdc.h"
#include "dev/text_screen_iii.h"
//
// Constants
//
#define SDC_TIMEOUT_MS 300
unsigned char g_sdc_status = SDC_STAT_NOINIT;
unsigned char g_sdc_error = 0;
@ -66,11 +73,13 @@ void sdc_set_led(short is_on) {
// 0 on success, DEV_TIMEOUT on timeout
//
short sdc_wait_busy() {
long timer_ticks;
int retry_count = MAX_TRIES_BUSY;
unsigned char status;
timer_ticks = rtc_get_ticks() + SDC_TIMEOUT_MS;
do {
if (retry_count-- == 0) {
if (rtc_get_ticks() > timer_ticks) {
// If we have run out of tries, return a TIMEOUT error
return DEV_TIMEOUT;
}

File diff suppressed because it is too large Load diff

View file

@ -56,7 +56,7 @@ const char* VolumeStr[FF_VOLUMES] = { "sd", "fd", "hd" };
*GP20_REG = 0x00;
*GP24_REG = 0x01;
*GP25_REG = 0x05;
*GP24_REG = 0x84;
*GP26_REG = 0x84;
*GP30_REG = 0x01;
*GP31_REG = 0x01;
@ -168,8 +168,8 @@ void initialize() {
/* Initialize the interrupt system */
int_init();
/* Initialize the timers */
timers_init();
/* Initialize the real time clock */
rtc_init();
#if MODEL == MODEL_FOENIX_A2560K
/* Initialize the SuperIO chip */
@ -203,8 +203,11 @@ void initialize() {
log(LOG_INFO, "Console installed.");
}
/* Initialize the real time clock */
rtc_init();
/* Enable all interrupts */
int_enable_all();
/* Make sure the RTC tick counter is going */
rtc_enable_ticks();
if (res = pata_install()) {
log_num(LOG_ERROR, "FAILED: PATA driver installation", res);
@ -245,9 +248,6 @@ void initialize() {
} else {
log(LOG_INFO, "File system initialized.");
}
/* Enable all interrupts */
int_enable_all();
}
int main(int argc, char * argv[]) {

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,10 @@
#define PSG_PORT ((volatile unsigned char *)0x00C20100) /* Control register for the SN76489 */
#define OPL3_PORT ((volatile unsigned char *)0x00C20200) /* Access port for the OPL3 */
#define OPM_EXT_BASE ((volatile unsigned char *)0x00C20600) /* External OPM base address */
#define OPN2_EXT_BASE ((volatile unsigned char *)0x00C20400) /* External OPN2 base address */
#define OPM_INT_BASE ((volatile unsigned char *)0x00C20C00) /* Internal OPM base address */
#define OPN2_INT_BASE ((volatile unsigned char *)0x00C20A00) /* Internal OPN2 base address */
#define CODEC ((volatile unsigned short *)0x00C20E00) /* Control register for the CODEC */
/*

View file

@ -68,8 +68,11 @@
#define KFN_RENAME 0x38 /* Rename a file */
#define KFN_MKDIR 0x39 /* Create a directory */
#define KFN_LOAD 0x3A /* Load a file into memory */
#define KFN_SAVE 0x3B /* Save a block of memory to a file */
#define KFN_LOAD_REGISTER 0x3C /* Register a file type handler for executable binaries */
#define KFN_GET_LABEL 0x3B /* Read the label of a volume */
#define KFN_SET_LABEL 0x3C /* Set the label of a volume */
#define KFN_SET_CWD 0x3D /* Set the current working directory */
#define KFN_GET_CWD 0x3E /* Get the current working directory */
#define KFN_LOAD_REGISTER 0x3F /* Register a file type handler for executable binaries */
/* Process and memory calls */
@ -353,15 +356,261 @@ extern short sys_bdev_flush(short dev);
//
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
* File System Calls
*/
extern unsigned short sys_kbd_scancode();
/**
* Attempt to open a file given the path to the file and the mode.
*
* Inputs:
* path = the ASCIIZ string containing the path to the file.
* mode = the mode (e.g. r/w/create)
*
* Returns:
* the channel ID for the open file (negative if error)
*/
extern short sys_fsys_open(const char * path, short mode);
/**
* Close access to a previously open file.
*
* Inputs:
* fd = the channel ID for the file
*
* Returns:
* 0 on success, negative number on failure
*/
extern short sys_fsys_close(short fd);
/**
* Attempt to open a directory for scanning
*
* Inputs:
* path = the path to the directory to open
*
* Returns:
* the handle to the directory if >= 0. An error if < 0
*/
extern short sys_fsys_opendir(const char * path);
/**
* Close access to a previously open file.
*
* Inputs:
* fd = the channel ID for the file
*
* Returns:
* 0 on success, negative number on failure
*/
extern short sys_fsys_close(short fd);
/**
* Attempt to open a directory for scanning
*
* Inputs:
* path = the path to the directory to open
*
* Returns:
* the handle to the directory if >= 0. An error if < 0
*/
extern short sys_fsys_opendir(const char * path);
/**
* Close a previously open directory
*
* Inputs:
* dir = the directory handle to close
*
* Returns:
* 0 on success, negative number on error
*/
extern short sys_fsys_closedir(short dir);
/**
* Attempt to read an entry from an open directory
*
* Inputs:
* dir = the handle of the open directory
* file = pointer to the t_file_info structure to fill out.
*
* Returns:
* 0 on success, negative number on failure
*/
extern short sys_fsys_readdir(short dir, p_file_info file);
/**
* Open a directory given the path and search for the first file matching the pattern.
*
* Inputs:
* path = the path to the directory to search
* pattern = the file name pattern to search for
* file = pointer to the t_file_info structure to fill out
*
* Returns:
* the directory handle to use for subsequent calls if >= 0, error if negative
*/
extern short sys_fsys_findfirst(const char * path, const char * pattern, p_file_info file);
/**
* Open a directory given the path and search for the first file matching the pattern.
*
* Inputs:
* dir = the handle to the directory (returned by fsys_findfirst) to search
* file = pointer to the t_file_info structure to fill out
*
* Returns:
* 0 on success, error if negative
*/
extern short sys_fsys_findnext(short dir, p_file_info file);
/*
* Get the label for the drive holding the path
*
* Inputs:
* path = path to the drive
* label = buffer that will hold the label... should be at least 35 bytes
*/
extern short sys_fsys_get_label(const char * path, char * label);
/*
* Set the label for the drive holding the path
*
* Inputs:
* drive = drive number
* label = buffer that holds the label
*/
extern short sys_fsys_set_label(short drive, const char * label);
/**
* Create a directory
*
* Inputs:
* path = the path of the directory to create.
*
* Returns:
* 0 on success, negative number on failure.
*/
extern short sys_fsys_mkdir(const char * path);
/**
* Delete a file or directory
*
* Inputs:
* path = the path of the file or directory to delete.
*
* Returns:
* 0 on success, negative number on failure.
*/
extern short sys_fsys_delete(const char * path);
/**
* Rename a file or directory
*
* Inputs:
* old_path = the current path to the file
* new_path = the new path for the file
*
* Returns:
* 0 on success, negative number on failure.
*/
extern short sys_fsys_rename(const char * old_path, const char * new_path);
/**
* Change the current working directory (and drive)
*
* Inputs:
* path = the path that should be the new current
*
* Returns:
* 0 on success, negative number on failure.
*/
extern short sys_fsys_setcwd(const char * path);
/**
* Get the current working drive and directory
*
* Inputs:
* path = the buffer in which to store the directory
* size = the size of the buffer in bytes
*
* Returns:
* 0 on success, negative number on failure.
*/
extern short sys_fsys_getcwd(char * path, short size);
/*
* Load a file into memory at the designated destination address.
*
* If destination = 0, the file must be in a recognized binary format
* that specifies its own loading address.
*
* Inputs:
* path = the path to the file to load
* destination = the destination address (0 for use file's address)
* start = pointer to the long variable to fill with the starting address
* (0 if not an executable, any other number if file is executable
* with a known starting address)
*
* Returns:
* 0 on success, negative number on error
*/
extern short sys_fsys_load(const char * path, long destination, long * start);
/*
* Register a file loading routine
*
* A file loader, takes a channel number to load from and returns a
* short that is the status of the load.
*
* Inputs:
* extension = the file extension to map to
* loader = pointer to the file load routine to add
*
* Returns:
* 0 on success, negative number on error
*/
extern short sys_fsys_register_loader(const char * extension, p_file_loader loader);
/*
* Miscellaneous
*/
/*
* Get the number of ticks since the system last booted.
*
* NOTE: a tick is almost, but not quite, 1ms. The RTC periodic interrupt
* period does not line up with a 1ms timer, but it comes close.
* Therefore, a tick will be 976.5625 microseconds... a little faster
* than 1ms.
*
* Returns:
* the number of ticks since the last reset
*/
extern long sys_rtc_get_ticks();
/*
* Set the time on the RTC
*
* Inputs:
* time = pointer to a t_time record containing the correct time
*/
extern void sys_rtc_set_time(p_time time);
/*
* Get the time on the RTC
*
* Inputs:
* time = pointer to a t_time record in which to put the current time
*/
extern void sys_rtc_get_time(p_time time);
/*
* Return the next scan code from the keyboard... 0 if nothing pending
*/
extern unsigned short sys_kbd_scancode();
extern const char * sys_err_message(short err_number);
#endif

View file

@ -79,6 +79,20 @@
#define LSR_ERR_OVERRUN 0x02 /* Overrun error */
#define LSR_DATA_AVAIL 0x01 /* Data is ready in the receive buffer */
#if MODEL == MODEL_FOENIX_A2560U || MODEL == MODEL_FOENIX_A2560U_PLUS
#define UART_300 536 /* Code for 300 bps */
#define UART_1200 134 /* Code for 1200 bps */
#define UART_2400 67 /* Code for 2400 bps */
#define UART_4800 34 /* Code for 4800 bps */
#define UART_9600 17 /* Code for 9600 bps */
#define UART_19200 8 /* Code for 19200 bps */
#define UART_38400 4 /* Code for 28400 bps */
#define UART_57600 3 /* Code for 57600 bps */
#define UART_115200 1 /* Code for 115200 bps */
#else
#define UART_300 384 /* Code for 300 bps */
#define UART_1200 96 /* Code for 1200 bps */
#define UART_2400 48 /* Code for 2400 bps */
@ -90,3 +104,7 @@
#define UART_115200 1 /* Code for 115200 bps */
#endif
#endif

View file

@ -162,8 +162,17 @@ unsigned long syscall_dispatch(int32_t function, int32_t param0, int32_t param1,
case KFN_LOAD:
return fsys_load((char *)param0, (long)param1, (long *)param2);
case KFN_SAVE:
return -1;
case KFN_GET_LABEL:
return fsys_getlabel((char *)param0, (char *)param1);
case KFN_SET_LABEL:
return fsys_setlabel((short)param0, (char *)param1);
case KFN_GET_CWD:
return fsys_get_cwd((char *)param0);
case KFN_SET_CWD:
return fsys_set_cwd((char *)param0);
case KFN_LOAD_REGISTER:
return fsys_register_loader((char *)param0, (p_file_loader)param1);
@ -185,7 +194,7 @@ unsigned long syscall_dispatch(int32_t function, int32_t param0, int32_t param1,
/* Misc functions */
switch (function) {
case KFN_TIME_TICKS:
return rtc_get_jiffies();
return rtc_get_ticks();
case KFN_TIME_SETRTC:
rtc_set_time((p_time)param0);

11355
src/mapfile

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,8 @@
#include "snd/codec.h"
static unsigned byte volume = 0xff;
/*
* Wait for the CODEC to be ready to receive more data.
*/
@ -26,4 +28,28 @@ void init_codec() {
codec_wait();
*CODEC = 0x1845; // R12
codec_wait();
codec_set_volume(0xff);
}
/*
* Set the master digital volume
*
* Inputs:
* vol = level of attenuation (0xff = full volume, 0x00 = mute)
*/
void codec_set_volume(unsigned char vol) {
volume = vol;
*CODEC = 0x0A00 | (0xFF - (vol & 0xFF));
*CODEC = 0x0400 | ((vol >> 1) & 0xff);
codec_wait();
}
/*
* Return the current volume
*/
unsigned char codec_get_volume() {
return volume;
}

View file

@ -12,4 +12,17 @@
*/
extern void init_codec();
/*
* Set the master digital volume
*
* Inputs:
* vol = level of attenuation (0xff = full volume, 0x00 = mute)
*/
void codec_set_volume(unsigned char vol);
/*
* Return the current volume
*/
extern unsigned char codec_get_volume();
#endif

313
src/snd/opl2.h Normal file
View file

@ -0,0 +1,313 @@
/*
* Definitions for the OPL2
*/
#ifndef __OPL2_H
#define __OPL2_H
#define OPN2_OFFSET_PART_II 0x100
#define OPN2_22_LFO 0x22 // LFO enable | LFO frequency
#define OPN2_23_TIMER_A_H 0x24 // Timer A MSBs
#define OPN2_24_TIMER_A_L 0x25 // Timer A LSBs
#define OPN2_25_TIMER_B 0x26 // Timer B
#define OPN2_27_CHANEL_3_MODE 0x27 // Ch3 mode Reset B Reset A Enable B Enable A Load B Load A
#define OPN2_27_TIMER_CONF 0x27 // Ch3 mode Reset B Reset A Enable B Enable A Load B Load A
#define OPN2_28_KEY_ON_OFF 0x28 // Operator Channel
//#define OPN2_29 0x29 // not used
#define OPN2_2A_ADC 0x2A // DAC
#define OPN2_2B_ADC_EN 0x2B // DAC en
//--------------------------------------------------------------------------------------
//------------------- DT1 (detune) and MUL (multiple) ----------------------------------
//--------------------------------------------------------------------------------------
//
// MUL ranges from 0 to 15 (decimal), and multiplies the overall frequency, with the
// exception that 0 results in multiplication by 1/2. That is, MUL=0 to 15 gives ×1/2,
// ×1, ×2, ... ×15.
//
// DT1 gives small variations from the overall frequency × MUL. The MSB of DT1 is a
// primitive sign bit, and the two LSBs are magnitude bits. See the next page for a
// diagram.
//
//--------------------------------------------------------------------------------------
#define OPN2_30_ADSR__DT1_MUL__CH1_OP1 0x30 // DT1 MUL
#define OPN2_31_ADSR__DT1_MUL__CH2_OP1 0x31 // DT1 MUL
#define OPN2_32_ADSR__DT1_MUL__CH3_OP1 0x32 // DT1 MUL
#define OPN2_34_ADSR__DT1_MUL__CH1_OP2 0x34 // DT1 MUL
#define OPN2_35_ADSR__DT1_MUL__CH2_OP2 0x35 // DT1 MUL
#define OPN2_36_ADSR__DT1_MUL__CH3_OP2 0x36 // DT1 MUL
#define OPN2_38_ADSR__DT1_MUL__CH1_OP3 0x38 // DT1 MUL
#define OPN2_39_ADSR__DT1_MUL__CH2_OP3 0x39 // DT1 MUL
#define OPN2_3A_ADSR__DT1_MUL__CH3_OP3 0x3A // DT1 MUL
#define OPN2_3C_ADSR__DT1_MUL__CH1_OP4 0x3C // DT1 MUL
#define OPN2_3D_ADSR__DT1_MUL__CH2_OP4 0x3D // DT1 MUL
#define OPN2_3E_ADSR__DT1_MUL__CH3_OP4 0x3E // DT1 MUL
#define OPN2_30_ADSR__DT1_MUL__CH1_OP5 OPN2_OFFSET_PART_II + 0x30 // DT1 MUL
#define OPN2_31_ADSR__DT1_MUL__CH2_OP5 OPN2_OFFSET_PART_II + 0x31 // DT1 MUL
#define OPN2_32_ADSR__DT1_MUL__CH3_OP5 OPN2_OFFSET_PART_II + 0x32 // DT1 MUL
#define OPN2_34_ADSR__DT1_MUL__CH1_OP6 OPN2_OFFSET_PART_II + 0x34 // DT1 MUL
#define OPN2_35_ADSR__DT1_MUL__CH2_OP6 OPN2_OFFSET_PART_II + 0x35 // DT1 MUL
#define OPN2_36_ADSR__DT1_MUL__CH3_OP6 OPN2_OFFSET_PART_II + 0x36 // DT1 MUL
#define OPN2_38_ADSR__DT1_MUL__CH1_OP7 OPN2_OFFSET_PART_II + 0x38 // DT1 MUL
#define OPN2_39_ADSR__DT1_MUL__CH2_OP7 OPN2_OFFSET_PART_II + 0x39 // DT1 MUL
#define OPN2_3A_ADSR__DT1_MUL__CH3_OP7 OPN2_OFFSET_PART_II + 0x3A // DT1 MUL
#define OPN2_3C_ADSR__DT1_MUL__CH1_OP8 OPN2_OFFSET_PART_II + 0x3C // DT1 MUL
#define OPN2_3D_ADSR__DT1_MUL__CH2_OP8 OPN2_OFFSET_PART_II + 0x3D // DT1 MUL
#define OPN2_3E_ADSR__DT1_MUL__CH3_OP8 OPN2_OFFSET_PART_II + 0x3E // DT1 MUL
//--------------------------------------------------------------------------------------
//---------------------------------- TL (total level) ----------------------------------
//--------------------------------------------------------------------------------------
//
// TL (total level) represents the envelopes highest amplitude, with 0 being the largest
// and 127 (decimal) the smallest. A change of one unit is about 0.75 dB.
//
// To make a note softer, only change the TL of the slots (the output operators).
// Changing the other operators will affect the flavor of the note.
//
//--------------------------------------------------------------------------------------
#define OPN2_40_ADSR__LT__CH1_OP1 0x40 // LT
#define OPN2_41_ADSR__LT__CH2_OP1 0x41 // LT
#define OPN2_42_ADSR__LT__CH3_OP1 0x42 // LT
#define OPN2_44_ADSR__LT__CH1_OP2 0x44 // LT
#define OPN2_45_ADSR__LT__CH2_OP2 0x45 // LT
#define OPN2_46_ADSR__LT__CH3_OP2 0x46 // LT
#define OPN2_48_ADSR__LT__CH1_OP3 0x48 // LT
#define OPN2_49_ADSR__LT__CH2_OP3 0x49 // LT
#define OPN2_4A_ADSR__LT__CH3_OP3 0x4A // LT
#define OPN2_4C_ADSR__LT__CH1_OP4 0x4C // LT
#define OPN2_4D_ADSR__LT__CH2_OP4 0x4D // LT
#define OPN2_4E_ADSR__LT__CH3_OP4 0x4E // LT
#define OPN2_40_ADSR__LT__CH1_OP5 OPN2_OFFSET_PART_II + 0x40 // LT
#define OPN2_41_ADSR__LT__CH2_OP5 OPN2_OFFSET_PART_II + 0x41 // LT
#define OPN2_42_ADSR__LT__CH3_OP5 OPN2_OFFSET_PART_II + 0x42 // LT
#define OPN2_44_ADSR__LT__CH1_OP6 OPN2_OFFSET_PART_II + 0x44 // LT
#define OPN2_45_ADSR__LT__CH2_OP6 OPN2_OFFSET_PART_II + 0x45 // LT
#define OPN2_46_ADSR__LT__CH3_OP6 OPN2_OFFSET_PART_II + 0x46 // LT
#define OPN2_48_ADSR__LT__CH1_OP7 OPN2_OFFSET_PART_II + 0x48 // LT
#define OPN2_49_ADSR__LT__CH2_OP7 OPN2_OFFSET_PART_II + 0x49 // LT
#define OPN2_4A_ADSR__LT__CH3_OP7 OPN2_OFFSET_PART_II + 0x4A // LT
#define OPN2_4C_ADSR__LT__CH1_OP8 OPN2_OFFSET_PART_II + 0x4C // LT
#define OPN2_4D_ADSR__LT__CH2_OP8 OPN2_OFFSET_PART_II + 0x4D // LT
#define OPN2_4E_ADSR__LT__CH3_OP8 OPN2_OFFSET_PART_II + 0x4E // LT
//--------------------------------------------------------------------------------------
//------------------- RS (rate scaling) and AR (attack rate) ---------------------------
//--------------------------------------------------------------------------------------
//
// AR is the steepness of the initial amplitude rise, shown on page 5.
//
// RS affects AR, D1R, D2R and RR in the same way. RS is the degree to which the envelope
// becomes narrower as the frequency becomes higher.
//
//--------------------------------------------------------------------------------------
#define OPN2_50_ADSR__SR_AR__CH1_OP1 0x50 // SR AR
#define OPN2_51_ADSR__SR_AR__CH2_OP1 0x51 // SR AR
#define OPN2_52_ADSR__SR_AR__CH3_OP1 0x52 // SR AR
#define OPN2_54_ADSR__SR_AR__CH1_OP2 0x54 // SR AR
#define OPN2_55_ADSR__SR_AR__CH2_OP2 0x55 // SR AR
#define OPN2_56_ADSR__SR_AR__CH3_OP2 0x56 // SR AR
#define OPN2_58_ADSR__SR_AR__CH1_OP3 0x58 // SR AR
#define OPN2_59_ADSR__SR_AR__CH2_OP3 0x59 // SR AR
#define OPN2_5A_ADSR__SR_AR__CH3_OP3 0x5A // SR AR
#define OPN2_5C_ADSR__SR_AR__CH1_OP4 0x5C // SR AR
#define OPN2_5D_ADSR__SR_AR__CH2_OP4 0x5D // SR AR
#define OPN2_5E_ADSR__SR_AR__CH3_OP4 0x5E // SR AR
#define OPN2_50_ADSR__SR_AR__CH1_OP5 OPN2_OFFSET_PART_II + 0x50 // SR AR
#define OPN2_51_ADSR__SR_AR__CH2_OP5 OPN2_OFFSET_PART_II + 0x51 // SR AR
#define OPN2_52_ADSR__SR_AR__CH3_OP5 OPN2_OFFSET_PART_II + 0x52 // SR AR
#define OPN2_54_ADSR__SR_AR__CH1_OP6 OPN2_OFFSET_PART_II + 0x54 // SR AR
#define OPN2_55_ADSR__SR_AR__CH2_OP6 OPN2_OFFSET_PART_II + 0x55 // SR AR
#define OPN2_56_ADSR__SR_AR__CH3_OP6 OPN2_OFFSET_PART_II + 0x56 // SR AR
#define OPN2_58_ADSR__SR_AR__CH1_OP7 OPN2_OFFSET_PART_II + 0x58 // SR AR
#define OPN2_59_ADSR__SR_AR__CH2_OP7 OPN2_OFFSET_PART_II + 0x59 // SR AR
#define OPN2_5A_ADSR__SR_AR__CH3_OP7 OPN2_OFFSET_PART_II + 0x5A // SR AR
#define OPN2_5C_ADSR__SR_AR__CH1_OP8 OPN2_OFFSET_PART_II + 0x5C // SR AR
#define OPN2_5D_ADSR__SR_AR__CH2_OP8 OPN2_OFFSET_PART_II + 0x5D // SR AR
#define OPN2_5E_ADSR__SR_AR__CH3_OP8 OPN2_OFFSET_PART_II + 0x5E // SR AR
//--------------------------------------------------------------------------------------
//-------------- AM modulation enable amd D1R (first decay rate) -----------------------
//--------------------------------------------------------------------------------------
//
// D1R (first decay rate) is the initial steep amplitude decay rate (see page 4). It is,
// like all rates, 0-31 in value and affected by RS.
//
// AM is the amplitude modulation enable, whether of not this operator will be subject to
// amplitude modulation by the LFO. This bit is not relevant unless both the LFO is
// enabled and register B4s AMS (amplitude modulation sensitivity) is non-zero.
//
//--------------------------------------------------------------------------------------
#define OPN2_60_ADSR__AM_D1R__CH1_OP1 0x60 // AM D1R
#define OPN2_61_ADSR__AM_D1R__CH2_OP1 0x61 // AM D1R
#define OPN2_62_ADSR__AM_D1R__CH3_OP1 0x62 // AM D1R
#define OPN2_64_ADSR__AM_D1R__CH1_OP2 0x64 // AM D1R
#define OPN2_65_ADSR__AM_D1R__CH2_OP2 0x65 // AM D1R
#define OPN2_66_ADSR__AM_D1R__CH3_OP2 0x66 // AM D1R
#define OPN2_68_ADSR__AM_D1R__CH1_OP3 0x68 // AM D1R
#define OPN2_69_ADSR__AM_D1R__CH2_OP3 0x69 // AM D1R
#define OPN2_6A_ADSR__AM_D1R__CH3_OP3 0x6A // AM D1R
#define OPN2_6C_ADSR__AM_D1R__CH1_OP4 0x6C // AM D1R
#define OPN2_6D_ADSR__AM_D1R__CH2_OP4 0x6D // AM D1R
#define OPN2_6E_ADSR__AM_D1R__CH3_OP4 0x6E // AM D1R
#define OPN2_60_ADSR__AM_D1R__CH1_OP5 OPN2_OFFSET_PART_II + 0x60 // AM D1R
#define OPN2_61_ADSR__AM_D1R__CH2_OP5 OPN2_OFFSET_PART_II + 0x61 // AM D1R
#define OPN2_62_ADSR__AM_D1R__CH3_OP5 OPN2_OFFSET_PART_II + 0x62 // AM D1R
#define OPN2_64_ADSR__AM_D1R__CH1_OP6 OPN2_OFFSET_PART_II + 0x64 // AM D1R
#define OPN2_65_ADSR__AM_D1R__CH2_OP6 OPN2_OFFSET_PART_II + 0x65 // AM D1R
#define OPN2_66_ADSR__AM_D1R__CH3_OP6 OPN2_OFFSET_PART_II + 0x66 // AM D1R
#define OPN2_68_ADSR__AM_D1R__CH1_OP7 OPN2_OFFSET_PART_II + 0x68 // AM D1R
#define OPN2_69_ADSR__AM_D1R__CH2_OP7 OPN2_OFFSET_PART_II + 0x69 // AM D1R
#define OPN2_6A_ADSR__AM_D1R__CH3_OP7 OPN2_OFFSET_PART_II + 0x6A // AM D1R
#define OPN2_6C_ADSR__AM_D1R__CH1_OP8 OPN2_OFFSET_PART_II + 0x6C // AM D1R
#define OPN2_6D_ADSR__AM_D1R__CH2_OP8 OPN2_OFFSET_PART_II + 0x6D // AM D1R
#define OPN2_6E_ADSR__AM_D1R__CH3_OP8 OPN2_OFFSET_PART_II + 0x6E // AM D1R
//--------------------------------------------------------------------------------------
//-------------------------- D2R (secondary decay rate) --------------------------------
//--------------------------------------------------------------------------------------
//
// D2R (secondary decay rate) is the long tail off of the sound that continues as long
// as the key is depressed.
//
//--------------------------------------------------------------------------------------
#define OPN2_70_ADSR__D2R__CH1_OP1 0x70 // D2R
#define OPN2_71_ADSR__D2R__CH2_OP1 0x71 // D2R
#define OPN2_72_ADSR__D2R__CH3_OP1 0x72 // D2R
#define OPN2_74_ADSR__D2R__CH1_OP2 0x74 // D2R
#define OPN2_75_ADSR__D2R__CH2_OP2 0x75 // D2R
#define OPN2_76_ADSR__D2R__CH3_OP2 0x76 // D2R
#define OPN2_78_ADSR__D2R__CH1_OP3 0x78 // D2R
#define OPN2_79_ADSR__D2R__CH2_OP3 0x79 // D2R
#define OPN2_7A_ADSR__D2R__CH3_OP3 0x7A // D2R
#define OPN2_7C_ADSR__D2R__CH1_OP4 0x7C // D2R
#define OPN2_7D_ADSR__D2R__CH2_OP4 0x7D // D2R
#define OPN2_7E_ADSR__D2R__CH3_OP4 0x7E // D2R
#define OPN2_70_ADSR__D2R__CH1_OP5 OPN2_OFFSET_PART_II + 0x70 // D2R
#define OPN2_71_ADSR__D2R__CH2_OP5 OPN2_OFFSET_PART_II + 0x71 // D2R
#define OPN2_72_ADSR__D2R__CH3_OP5 OPN2_OFFSET_PART_II + 0x72 // D2R
#define OPN2_74_ADSR__D2R__CH1_OP6 OPN2_OFFSET_PART_II + 0x74 // D2R
#define OPN2_75_ADSR__D2R__CH2_OP6 OPN2_OFFSET_PART_II + 0x75 // D2R
#define OPN2_76_ADSR__D2R__CH3_OP6 OPN2_OFFSET_PART_II + 0x76 // D2R
#define OPN2_78_ADSR__D2R__CH1_OP7 OPN2_OFFSET_PART_II + 0x78 // D2R
#define OPN2_79_ADSR__D2R__CH2_OP7 OPN2_OFFSET_PART_II + 0x79 // D2R
#define OPN2_7A_ADSR__D2R__CH3_OP7 OPN2_OFFSET_PART_II + 0x7A // D2R
#define OPN2_7C_ADSR__D2R__CH1_OP8 OPN2_OFFSET_PART_II + 0x7C // D2R
#define OPN2_7D_ADSR__D2R__CH2_OP8 OPN2_OFFSET_PART_II + 0x7D // D2R
#define OPN2_7E_ADSR__D2R__CH3_OP8 OPN2_OFFSET_PART_II + 0x7E // D2R
//--------------------------------------------------------------------------------------
//-------------------------- D2R (secondary decay rate) --------------------------------
//--------------------------------------------------------------------------------------
//
// D2R (secondary decay rate) is the long tail off of the sound that continues as long
// as the key is depressed.
//
//--------------------------------------------------------------------------------------
#define OPN2_80_ADSR__D1L_RR__CH1_OP1 0x80 // D1L RR
#define OPN2_81_ADSR__D1L_RR__CH2_OP1 0x81 // D1L RR
#define OPN2_82_ADSR__D1L_RR__CH3_OP1 0x82 // D1L RR
#define OPN2_84_ADSR__D1L_RR__CH1_OP2 0x84 // D1L RR
#define OPN2_85_ADSR__D1L_RR__CH2_OP2 0x85 // D1L RR
#define OPN2_86_ADSR__D1L_RR__CH3_OP2 0x86 // D1L RR
#define OPN2_88_ADSR__D1L_RR__CH1_OP3 0x88 // D1L RR
#define OPN2_89_ADSR__D1L_RR__CH2_OP3 0x89 // D1L RR
#define OPN2_8A_ADSR__D1L_RR__CH3_OP3 0x8A // D1L RR
#define OPN2_8C_ADSR__D1L_RR__CH1_OP4 0x8C // D1L RR
#define OPN2_8D_ADSR__D1L_RR__CH2_OP4 0x8D // D1L RR
#define OPN2_8E_ADSR__D1L_RR__CH3_OP4 0x8E // D1L RR
#define OPN2_80_ADSR__D1L_RR__CH1_OP5 OPN2_OFFSET_PART_II + 0x80 // D1L RR
#define OPN2_81_ADSR__D1L_RR__CH2_OP5 OPN2_OFFSET_PART_II + 0x81 // D1L RR
#define OPN2_82_ADSR__D1L_RR__CH3_OP5 OPN2_OFFSET_PART_II + 0x82 // D1L RR
#define OPN2_84_ADSR__D1L_RR__CH1_OP6 OPN2_OFFSET_PART_II + 0x84 // D1L RR
#define OPN2_85_ADSR__D1L_RR__CH2_OP6 OPN2_OFFSET_PART_II + 0x85 // D1L RR
#define OPN2_86_ADSR__D1L_RR__CH3_OP6 OPN2_OFFSET_PART_II + 0x86 // D1L RR
#define OPN2_88_ADSR__D1L_RR__CH1_OP7 OPN2_OFFSET_PART_II + 0x88 // D1L RR
#define OPN2_89_ADSR__D1L_RR__CH2_OP7 OPN2_OFFSET_PART_II + 0x89 // D1L RR
#define OPN2_8A_ADSR__D1L_RR__CH3_OP7 OPN2_OFFSET_PART_II + 0x8A // D1L RR
#define OPN2_8C_ADSR__D1L_RR__CH1_OP8 OPN2_OFFSET_PART_II + 0x8C // D1L RR
#define OPN2_8D_ADSR__D1L_RR__CH2_OP8 OPN2_OFFSET_PART_II + 0x8D // D1L RR
#define OPN2_8E_ADSR__D1L_RR__CH3_OP8 OPN2_OFFSET_PART_II + 0x8E // D1L RR
//--------------------------------------------------------------------------------------
//------------------------------------ SSG-EG ------------------------------------------
//--------------------------------------------------------------------------------------
//
// This register is proprietary and should be set to zero.
//
//--------------------------------------------------------------------------------------
#define OPN2_90_ADSR__D1L_RR__CH1_OP1 0x90 // D1L RR
#define OPN2_91_ADSR__D1L_RR__CH2_OP1 0x91 // D1L RR
#define OPN2_92_ADSR__D1L_RR__CH3_OP1 0x92 // D1L RR
#define OPN2_94_ADSR__D1L_RR__CH1_OP2 0x94 // D1L RR
#define OPN2_95_ADSR__D1L_RR__CH2_OP2 0x95 // D1L RR
#define OPN2_96_ADSR__D1L_RR__CH3_OP2 0x96 // D1L RR
#define OPN2_98_ADSR__D1L_RR__CH1_OP3 0x98 // D1L RR
#define OPN2_99_ADSR__D1L_RR__CH2_OP3 0x99 // D1L RR
#define OPN2_9A_ADSR__D1L_RR__CH3_OP3 0x9A // D1L RR
#define OPN2_9C_ADSR__D1L_RR__CH1_OP4 0x9C // D1L RR
#define OPN2_9D_ADSR__D1L_RR__CH2_OP4 0x9D // D1L RR
#define OPN2_9E_ADSR__D1L_RR__CH3_OP4 0x9E // D1L RR
#define OPN2_90_ADSR__D1L_RR__CH4_OP1 OPN2_OFFSET_PART_II + 0x90 // D1L RR
#define OPN2_91_ADSR__D1L_RR__CH5_OP1 OPN2_OFFSET_PART_II + 0x91 // D1L RR
#define OPN2_92_ADSR__D1L_RR__CH6_OP1 OPN2_OFFSET_PART_II + 0x92 // D1L RR
#define OPN2_94_ADSR__D1L_RR__CH4_OP2 OPN2_OFFSET_PART_II + 0x94 // D1L RR
#define OPN2_95_ADSR__D1L_RR__CH5_OP2 OPN2_OFFSET_PART_II + 0x95 // D1L RR
#define OPN2_96_ADSR__D1L_RR__CH6_OP2 OPN2_OFFSET_PART_II + 0x96 // D1L RR
#define OPN2_98_ADSR__D1L_RR__CH4_OP3 OPN2_OFFSET_PART_II + 0x98 // D1L RR
#define OPN2_99_ADSR__D1L_RR__CH5_OP3 OPN2_OFFSET_PART_II + 0x99 // D1L RR
#define OPN2_9A_ADSR__D1L_RR__CH6_OP3 OPN2_OFFSET_PART_II + 0x9A // D1L RR
#define OPN2_9C_ADSR__D1L_RR__CH4_OP4 OPN2_OFFSET_PART_II + 0x9C // D1L RR
#define OPN2_9D_ADSR__D1L_RR__CH5_OP4 OPN2_OFFSET_PART_II + 0x9D // D1L RR
#define OPN2_9E_ADSR__D1L_RR__CH6_OP4 OPN2_OFFSET_PART_II + 0x9E // D1L RR
#define OPN2_A0_CH1_FRECANCY_L 0xA0 // Frequency number LSB
#define OPN2_A1_CH2_FRECANCY_L 0xA1 // Frequency number LSB
#define OPN2_A2_CH3_FRECANCY_L 0xA2 // Frequency number LSB
#define OPN2_A2_CH3_FRECANCY_OP1_L 0xA2 // Frequency number LSB Chanel 3 Operator 1 if special mode
#define OPN2_A8_CH3_FRECANCY_OP2_L 0xA8 // Frequency number LSB Chanel 3 Operator 2 if special mode
#define OPN2_A9_CH3_FRECANCY_OP3_L 0xA9 // Frequency number LSB Chanel 3 Operator 3 if special mode
#define OPN2_AA_CH3_FRECANCY_OP4_L 0xAA // Frequency number LSB Chanel 3 Operator 4 if special mode
#define OPN2_A0_CH4_FRECANCY_L OPN2_OFFSET_PART_II + 0xA0 // Frequency number LSB
#define OPN2_A1_CH5_FRECANCY_L OPN2_OFFSET_PART_II + 0xA1 // Frequency number LSB
#define OPN2_A2_CH6_FRECANCY_L OPN2_OFFSET_PART_II + 0xA2 // Frequency number LSB
#define OPN2_A4_CH1_OCTAVE_FRECANCY_H 0xA4 // OCTAVE and Frequency number MSB
#define OPN2_A5_CH2_OCTAVE_FRECANCY_H 0xA5 // OCTAVE and Frequency number MSB
#define OPN2_A6_CH3_OCTAVE_FRECANCY_H 0xA6 // OCTAVE and Frequency number MSB
#define OPN2_A6_CH3_OCTAVE_FRECANCY_OP1_H 0xA6 // OCTAVE and Frequency number MSB Chanel 3 Operator 1 if special mode
#define OPN2_AC_CH3_OCTAVE_FRECANCY_OP2_H 0xAC // OCTAVE and Frequency number MSB Chanel 3 Operator 2 if special mode
#define OPN2_AD_CH3_OCTAVE_FRECANCY_OP3_H 0xAD // OCTAVE and Frequency number MSB Chanel 3 Operator 3 if special mode
#define OPN2_AE_CH3_OCTAVE_FRECANCY_OP4_H 0xAE // OCTAVE and Frequency number MSB Chanel 3 Operator 4 if special mode
#define OPN2_A4_CH4_OCTAVE_FRECANCY_H OPN2_OFFSET_PART_II + 0xA4 // OCTAVE and Frequency number MSB
#define OPN2_A5_CH5_OCTAVE_FRECANCY_H OPN2_OFFSET_PART_II + 0xA5 // OCTAVE and Frequency number MSB
#define OPN2_A6_CH6_OCTAVE_FRECANCY_H OPN2_OFFSET_PART_II + 0xA6 // OCTAVE and Frequency number MSB
// Feedback is the degree to which operator 1 feeds back into itself.
// The algorithm is the type of inter-operator connection used
#define OPN2_B0_CH1_FEEDBACK_ALGO 0xB0 //
#define OPN2_B1_CH2_FEEDBACK_ALGO 0xB1 //
#define OPN2_B2_CH3_FEEDBACK_ALGO 0xB2 //
#define OPN2_B0_CH4_FEEDBACK_ALGO OPN2_OFFSET_PART_II + 0xB0 //
#define OPN2_B1_CH5_FEEDBACK_ALGO OPN2_OFFSET_PART_II + 0xB1 //
#define OPN2_B2_CH6_FEEDBACK_ALGO OPN2_OFFSET_PART_II + 0xB2 //
// Register B4H contains stereo output control and LFO sensitivity control.
#define OPN2_B4_CH1_L_R_AMS_FMS 0xB4 //
#define OPN2_B5_CH2_L_R_AMS_FMS 0xB5 //
#define OPN2_B6_CH3_L_R_AMS_FMS 0xB6 //
#define OPN2_B4_CH4_L_R_AMS_FMS OPN2_OFFSET_PART_II + 0xB4 //
#define OPN2_B5_CH5_L_R_AMS_FMS OPN2_OFFSET_PART_II + 0xB5 //
#define OPN2_B6_CH6_L_R_AMS_FMS OPN2_OFFSET_PART_II + 0xB6 //
#endif

251
src/snd/opm.h Normal file
View file

@ -0,0 +1,251 @@
/*
* Definitions for the OPM
*/
#ifndef __OPM_H
#define __OPM_H
#define OPM_01_TEST 0x01
#define OPM_08_KEY_ON_OFF 0x08
#define OPM_0F_NE_NFREQ 0x0F
#define OPM_10_CLK_A1 0x10
#define OPM_11_CLK_A2 0x11
#define OPM_12_CLK_B 0x12
#define OPM_14_CMS_FLAG_RESET_IRQEN_LOAD 0x14
#define OPM_18_LFRQ 0x18
#define OPM_19_PMD_AMD 0x19
#define OPM_1B_CT_W 0x1B
#define OPM_20_A_RL_FR_CONNECT 0x20
#define OPM_21_B_RL_FR_CONNECT 0x21
#define OPM_22_C_RL_FR_CONNECT 0x22
#define OPM_23_D_RL_FR_CONNECT 0x23
#define OPM_24_E_RL_FR_CONNECT 0x24
#define OPM_25_F_RL_FR_CONNECT 0x25
#define OPM_26_G_RL_FR_CONNECT 0x26
#define OPM_27_H_RL_FR_CONNECT 0x27
#define OPM_28_A_KC 0x28
#define OPM_29_B_KC 0x29
#define OPM_2A_C_KC 0x2A
#define OPM_2B_D_KC 0x2B
#define OPM_2C_E_KC 0x2C
#define OPM_2D_F_KC 0x2D
#define OPM_2E_G_KC 0x2E
#define OPM_2F_H_KC 0x2F
#define OPM_30_A_KF 0x30
#define OPM_31_B_KF 0x31
#define OPM_32_C_KF 0x32
#define OPM_33_D_KF 0x33
#define OPM_34_E_KF 0x34
#define OPM_35_F_KF 0x35
#define OPM_36_G_KF 0x36
#define OPM_37_H_KF 0x37
#define OPM_38_A_PMS_AMS 0x38
#define OPM_39_B_PMS_AMS 0x39
#define OPM_3A_C_PMS_AMS 0x3A
#define OPM_3B_D_PMS_AMS 0x3B
#define OPM_3C_E_PMS_AMS 0x3C
#define OPM_3D_F_PMS_AMS 0x3D
#define OPM_3E_G_PMS_AMS 0x3E
#define OPM_3F_H_PMS_AMS 0x3F
#define OPM_40_A_M1_DT1_MUL 0x40
#define OPM_41_B_M1_DT1_MUL 0x41
#define OPM_42_C_M1_DT1_MUL 0x42
#define OPM_43_D_M1_DT1_MUL 0x43
#define OPM_44_E_M1_DT1_MUL 0x44
#define OPM_45_F_M1_DT1_MUL 0x45
#define OPM_46_G_M1_DT1_MUL 0x46
#define OPM_47_H_M1_DT1_MUL 0x47
#define OPM_48_A_M2_DT1_MUL 0x48
#define OPM_49_B_M2_DT1_MUL 0x49
#define OPM_4A_C_M2_DT1_MUL 0x4A
#define OPM_4B_D_M2_DT1_MUL 0x4B
#define OPM_4C_E_M2_DT1_MUL 0x4C
#define OPM_4D_F_M2_DT1_MUL 0x4D
#define OPM_4E_G_M2_DT1_MUL 0x4E
#define OPM_4F_H_M2_DT1_MUL 0x4F
#define OPM_50_A_C1_DT1_MUL 0x50
#define OPM_51_B_C1_DT1_MUL 0x51
#define OPM_52_C_C1_DT1_MUL 0x52
#define OPM_53_D_C1_DT1_MUL 0x53
#define OPM_54_E_C1_DT1_MUL 0x54
#define OPM_55_F_C1_DT1_MUL 0x55
#define OPM_56_G_C1_DT1_MUL 0x56
#define OPM_57_H_C1_DT1_MUL 0x57
#define OPM_58_A_C2_DT1_MUL 0x58
#define OPM_59_B_C2_DT1_MUL 0x59
#define OPM_5A_C_C2_DT1_MUL 0x5A
#define OPM_5B_D_C2_DT1_MUL 0x5B
#define OPM_5C_E_C2_DT1_MUL 0x5C
#define OPM_5D_F_C2_DT1_MUL 0x5D
#define OPM_5E_G_C2_DT1_MUL 0x5E
#define OPM_5F_H_C2_DT1_MUL 0x5F
#define OPM_60_A_M1_TL 0x60
#define OPM_61_B_M1_TL 0x61
#define OPM_62_C_M1_TL 0x62
#define OPM_63_D_M1_TL 0x63
#define OPM_64_E_M1_TL 0x64
#define OPM_65_F_M1_TL 0x65
#define OPM_66_G_M1_TL 0x66
#define OPM_67_H_M1_TL 0x67
#define OPM_68_A_M2_TL 0x68
#define OPM_69_B_M2_TL 0x69
#define OPM_6A_C_M2_TL 0x6A
#define OPM_6B_D_M2_TL 0x6B
#define OPM_6C_E_M2_TL 0x6C
#define OPM_6D_F_M2_TL 0x6D
#define OPM_6E_G_M2_TL 0x6E
#define OPM_6F_H_M2_TL 0x6F
#define OPM_70_A_C1_TL 0x70
#define OPM_71_B_C1_TL 0x71
#define OPM_72_C_C1_TL 0x72
#define OPM_73_D_C1_TL 0x73
#define OPM_74_E_C1_TL 0x74
#define OPM_75_F_C1_TL 0x75
#define OPM_76_G_C1_TL 0x76
#define OPM_77_H_C1_TL 0x77
#define OPM_78_A_C2_TL 0x78
#define OPM_79_B_C2_TL 0x79
#define OPM_7A_C_C2_TL 0x7A
#define OPM_7B_D_C2_TL 0x7B
#define OPM_7C_E_C2_TL 0x7C
#define OPM_7D_F_C2_TL 0x7D
#define OPM_7E_G_C2_TL 0x7E
#define OPM_7F_H_C2_TL 0x7F
#define OPM_80_A_M1_KS_AR 0x80
#define OPM_81_B_M1_KS_AR 0x81
#define OPM_82_C_M1_KS_AR 0x82
#define OPM_83_D_M1_KS_AR 0x83
#define OPM_84_E_M1_KS_AR 0x84
#define OPM_85_F_M1_KS_AR 0x85
#define OPM_86_G_M1_KS_AR 0x86
#define OPM_87_H_M1_KS_AR 0x87
#define OPM_88_A_M2_KS_AR 0x88
#define OPM_89_B_M2_KS_AR 0x89
#define OPM_8A_C_M2_KS_AR 0x8A
#define OPM_8B_D_M2_KS_AR 0x8B
#define OPM_8C_E_M2_KS_AR 0x8C
#define OPM_8D_F_M2_KS_AR 0x8D
#define OPM_8E_G_M2_KS_AR 0x8E
#define OPM_8F_H_M2_KS_AR 0x8F
#define OPM_90_A_C1_KS_AR 0x90
#define OPM_91_B_C1_KS_AR 0x91
#define OPM_92_C_C1_KS_AR 0x92
#define OPM_93_D_C1_KS_AR 0x93
#define OPM_94_E_C1_KS_AR 0x94
#define OPM_95_F_C1_KS_AR 0x95
#define OPM_96_G_C1_KS_AR 0x96
#define OPM_97_H_C1_KS_AR 0x97
#define OPM_98_A_C2_KS_AR 0x98
#define OPM_99_B_C2_KS_AR 0x99
#define OPM_9A_C_C2_KS_AR 0x9A
#define OPM_9B_D_C2_KS_AR 0x9B
#define OPM_9C_E_C2_KS_AR 0x9C
#define OPM_9D_F_C2_KS_AR 0x9D
#define OPM_9E_G_C2_KS_AR 0x9E
#define OPM_9F_H_C2_KS_AR 0x9F
#define OPM_A0_A_M1_AMS_EN_D1R 0xA0
#define OPM_A1_B_M1_AMS_EN_D1R 0xA1
#define OPM_A2_C_M1_AMS_EN_D1R 0xA2
#define OPM_A3_D_M1_AMS_EN_D1R 0xA3
#define OPM_A4_E_M1_AMS_EN_D1R 0xA4
#define OPM_A5_F_M1_AMS_EN_D1R 0xA5
#define OPM_A6_G_M1_AMS_EN_D1R 0xA6
#define OPM_A7_H_M1_AMS_EN_D1R 0xA7
#define OPM_A8_A_M2_AMS_EN_D1R 0xA8
#define OPM_A9_B_M2_AMS_EN_D1R 0xA9
#define OPM_AA_C_M2_AMS_EN_D1R 0xAA
#define OPM_AB_D_M2_AMS_EN_D1R 0xAB
#define OPM_AC_E_M2_AMS_EN_D1R 0xAC
#define OPM_AD_F_M2_AMS_EN_D1R 0xAD
#define OPM_AE_G_M2_AMS_EN_D1R 0xAE
#define OPM_AF_H_M2_AMS_EN_D1R 0xAF
#define OPM_B0_A_C1_AMS_EN_D1R 0xB0
#define OPM_B1_B_C1_AMS_EN_D1R 0xB1
#define OPM_B2_C_C1_AMS_EN_D1R 0xB2
#define OPM_B3_D_C1_AMS_EN_D1R 0xB3
#define OPM_B4_E_C1_AMS_EN_D1R 0xB4
#define OPM_B5_F_C1_AMS_EN_D1R 0xB5
#define OPM_B6_G_C1_AMS_EN_D1R 0xB6
#define OPM_B7_H_C1_AMS_EN_D1R 0xB7
#define OPM_B8_A_C2_AMS_EN_D1R 0xB8
#define OPM_B9_B_C2_AMS_EN_D1R 0xB9
#define OPM_BA_C_C2_AMS_EN_D1R 0xBA
#define OPM_BB_D_C2_AMS_EN_D1R 0xBB
#define OPM_BC_E_C2_AMS_EN_D1R 0xBC
#define OPM_BD_F_C2_AMS_EN_D1R 0xBD
#define OPM_BE_G_C2_AMS_EN_D1R 0xBE
#define OPM_BF_H_C2_AMS_EN_D1R 0xBF
#define OPM_C0_A_M1_DT2_D2R 0xC0
#define OPM_C1_B_M1_DT2_D2R 0xC1
#define OPM_C2_C_M1_DT2_D2R 0xC2
#define OPM_C3_D_M1_DT2_D2R 0xC3
#define OPM_C4_E_M1_DT2_D2R 0xC4
#define OPM_C5_F_M1_DT2_D2R 0xC5
#define OPM_C6_G_M1_DT2_D2R 0xC6
#define OPM_C7_H_M1_DT2_D2R 0xC7
#define OPM_C8_A_M2_DT2_D2R 0xC8
#define OPM_C9_B_M2_DT2_D2R 0xC9
#define OPM_CA_C_M2_DT2_D2R 0xCA
#define OPM_CB_D_M2_DT2_D2R 0xCB
#define OPM_CC_E_M2_DT2_D2R 0xCC
#define OPM_CD_F_M2_DT2_D2R 0xCD
#define OPM_CE_G_M2_DT2_D2R 0xCE
#define OPM_CF_H_M2_DT2_D2R 0xCF
#define OPM_D0_A_C1_DT2_D2R 0xD0
#define OPM_D1_B_C1_DT2_D2R 0xD1
#define OPM_D2_C_C1_DT2_D2R 0xD2
#define OPM_D3_D_C1_DT2_D2R 0xD3
#define OPM_D4_E_C1_DT2_D2R 0xD4
#define OPM_D5_F_C1_DT2_D2R 0xD5
#define OPM_D6_G_C1_DT2_D2R 0xD6
#define OPM_D7_H_C1_DT2_D2R 0xD7
#define OPM_D8_A_C2_DT2_D2R 0xD8
#define OPM_D9_B_C2_DT2_D2R 0xD9
#define OPM_DA_C_C2_DT2_D2R 0xDA
#define OPM_DB_D_C2_DT2_D2R 0xDB
#define OPM_DC_E_C2_DT2_D2R 0xDC
#define OPM_DD_F_C2_DT2_D2R 0xDD
#define OPM_DE_G_C2_DT2_D2R 0xDE
#define OPM_DF_H_C2_DT2_D2R 0xDF
#define OPM_E0_A_M1_D1L_RR 0xE0
#define OPM_E1_B_M1_D1L_RR 0xE1
#define OPM_E2_C_M1_D1L_RR 0xE2
#define OPM_E3_D_M1_D1L_RR 0xE3
#define OPM_E4_E_M1_D1L_RR 0xE4
#define OPM_E5_F_M1_D1L_RR 0xE5
#define OPM_E6_G_M1_D1L_RR 0xE6
#define OPM_E7_H_M1_D1L_RR 0xE7
#define OPM_E8_A_M2_D1L_RR 0xE8
#define OPM_E9_B_M2_D1L_RR 0xE9
#define OPM_EA_C_M2_D1L_RR 0xEA
#define OPM_EB_D_M2_D1L_RR 0xEB
#define OPM_EC_E_M2_D1L_RR 0xEC
#define OPM_ED_F_M2_D1L_RR 0xED
#define OPM_EE_G_M2_D1L_RR 0xEE
#define OPM_EF_H_M2_D1L_RR 0xEF
#define OPM_F0_A_C1_D1L_RR 0xF0
#define OPM_F1_B_C1_D1L_RR 0xF1
#define OPM_F2_C_C1_D1L_RR 0xF2
#define OPM_F3_D_C1_D1L_RR 0xF3
#define OPM_F4_E_C1_D1L_RR 0xF4
#define OPM_F5_F_C1_D1L_RR 0xF5
#define OPM_F6_G_C1_D1L_RR 0xF6
#define OPM_F7_H_C1_D1L_RR 0xF7
#define OPM_F8_A_C2_D1L_RR 0xF8
#define OPM_F9_B_C2_D1L_RR 0xF9
#define OPM_FA_C_C2_D1L_RR 0xFA
#define OPM_FB_D_C2_D1L_RR 0xFB
#define OPM_FC_E_C2_D1L_RR 0xFC
#define OPM_FD_F_C2_D1L_RR 0xFD
#define OPM_FE_G_C2_D1L_RR 0xFE
#define OPM_FF_H_C2_D1L_RR 0xFF
#endif

View file

@ -2,6 +2,7 @@
#include "interrupt.h"
#include "dev/channel.h"
#include "dev/block.h"
#include "dev/rtc.h"
/***
*** Core system calls
@ -310,10 +311,271 @@ short sys_bdev_ioctrl(short dev, short command, unsigned char * buffer, short si
return syscall(KFN_BDEV_IOCTRL, dev, command, buffer, size);
}
/*
* File System Calls
*/
/**
* Attempt to open a file given the path to the file and the mode.
*
* Inputs:
* path = the ASCIIZ string containing the path to the file.
* mode = the mode (e.g. r/w/create)
*
* Returns:
* the channel ID for the open file (negative if error)
*/
short sys_fsys_open(const char * path, short mode) {
return (short)syscall(KFN_OPEN, path, mode);
}
/**
* Close access to a previously open file.
*
* Inputs:
* fd = the channel ID for the file
*
* Returns:
* 0 on success, negative number on failure
*/
short sys_fsys_close(short fd) {
return (short)syscall(KFN_CLOSE, fd);
}
/**
* Attempt to open a directory for scanning
*
* Inputs:
* path = the path to the directory to open
*
* Returns:
* the handle to the directory if >= 0. An error if < 0
*/
short sys_fsys_opendir(const char * path) {
return (short)syscall(KFN_OPENDIR, path);
}
/**
* Close a previously open directory
*
* Inputs:
* dir = the directory handle to close
*
* Returns:
* 0 on success, negative number on error
*/
short sys_fsys_closedir(short dir) {
return (short)syscall(KFN_CLOSEDIR, dir);
}
/**
* Attempt to read an entry from an open directory
*
* Inputs:
* dir = the handle of the open directory
* file = pointer to the t_file_info structure to fill out.
*
* Returns:
* 0 on success, negative number on failure
*/
short sys_fsys_readdir(short dir, p_file_info file) {
return (short)syscall(KFN_READDIR, dir, file);
}
/**
* Open a directory given the path and search for the first file matching the pattern.
*
* Inputs:
* path = the path to the directory to search
* pattern = the file name pattern to search for
* file = pointer to the t_file_info structure to fill out
*
* Returns:
* the directory handle to use for subsequent calls if >= 0, error if negative
*/
short sys_fsys_findfirst(const char * path, const char * pattern, p_file_info file) {
return (short)syscall(KFN_FINDFIRST, path, pattern, file);
}
/**
* Open a directory given the path and search for the first file matching the pattern.
*
* Inputs:
* dir = the handle to the directory (returned by fsys_findfirst) to search
* file = pointer to the t_file_info structure to fill out
*
* Returns:
* 0 on success, error if negative
*/
short sys_fsys_findnext(short dir, p_file_info file) {
return (short)syscall(KFN_FINDNEXT, dir, file);
}
/*
* Get the label for the drive holding the path
*
* Inputs:
* path = path to the drive
* label = buffer that will hold the label... should be at least 35 bytes
*/
short sys_fsys_get_label(char * path, char * label) {
return (short)syscall(KFN_GET_LABEL, path, label);
}
/*
* Set the label for the drive holding the path
*
* Inputs:
* drive = drive number
* label = buffer that holds the label
*/
short sys_fsys_set_label(short drive, const char * label) {
return (short)syscall(KFN_SET_LABEL, drive, label);
}
/**
* Create a directory
*
* Inputs:
* path = the path of the directory to create.
*
* Returns:
* 0 on success, negative number on failure.
*/
short sys_fsys_mkdir(const char * path) {
return (short)syscall(KFN_MKDIR, path);
}
/**
* Delete a file or directory
*
* Inputs:
* path = the path of the file or directory to delete.
*
* Returns:
* 0 on success, negative number on failure.
*/
short sys_fsys_delete(const char * path) {
return (short)syscall(KFN_DELETE, path);
}
/**
* Rename a file or directory
*
* Inputs:
* old_path = the current path to the file
* new_path = the new path for the file
*
* Returns:
* 0 on success, negative number on failure.
*/
short sys_fsys_rename(const char * old_path, const char * new_path) {
return (short)syscall(KFN_RENAME, old_path, new_path);
}
/**
* Change the current working directory (and drive)
*
* Inputs:
* path = the path that should be the new current
*
* Returns:
* 0 on success, negative number on failure.
*/
short sys_fsys_set_cwd(const char * path) {
return (short)syscall(KFN_SET_CWD, path);
}
/**
* Get the current working drive and directory
*
* Inputs:
* path = the buffer in which to store the directory
* size = the size of the buffer in bytes
*
* Returns:
* 0 on success, negative number on failure.
*/
short sys_fsys_get_cwd(char * path, short size) {
return (short)syscall(KFN_GET_CWD, path, size);
}
/*
* Load a file into memory at the designated destination address.
*
* If destination = 0, the file must be in a recognized binary format
* that specifies its own loading address.
*
* Inputs:
* path = the path to the file to load
* destination = the destination address (0 for use file's address)
* start = pointer to the long variable to fill with the starting address
* (0 if not an executable, any other number if file is executable
* with a known starting address)
*
* Returns:
* 0 on success, negative number on error
*/
short sys_fsys_load(const char * path, long destination, long * start) {
return (short)syscall(KFN_LOAD, path, destination, start);
}
/*
* Register a file loading routine
*
* A file loader, takes a channel number to load from and returns a
* short that is the status of the load.
*
* Inputs:
* extension = the file extension to map to
* loader = pointer to the file load routine to add
*
* Returns:
* 0 on success, negative number on error
*/
short sys_fsys_register_loader(const char * extension, p_file_loader loader) {
return (short)syscall(KFN_LOAD_REGISTER, extension, loader);
}
/*
* Miscellaneous
*/
/*
* Get the number of ticks since the system last booted.
*
* NOTE: a tick is almost, but not quite, 1ms. The RTC periodic interrupt
* period does not line up with a 1ms timer, but it comes close.
* Therefore, a tick will be 976.5625 microseconds... a little faster
* than 1ms.
*
* Returns:
* the number of ticks since the last reset
*/
long sys_rtc_get_ticks() {
return syscall(KFN_TIME_TICKS);
}
/*
* Set the time on the RTC
*
* Inputs:
* time = pointer to a t_time record containing the correct time
*/
void sys_rtc_set_time(p_time time) {
syscall(KFN_TIME_SETRTC, time);
}
/*
* Get the time on the RTC
*
* Inputs:
* time = pointer to a t_time record in which to put the current time
*/
void sys_rtc_get_time(p_time time) {
syscall(KFN_TIME_GETRTC, time);
}
/*
* Return the next scan code from the keyboard... 0 if nothing pending
*/