mirror of
https://github.com/gmcn42/mt32-pi-control.git
synced 2026-09-22 18:37:58 +00:00
88 lines
1.9 KiB
C
88 lines
1.9 KiB
C
/*
|
|
* mt32-pi-control
|
|
*
|
|
* An mt32-pi control program for DOS PCs
|
|
* and Amiga computers
|
|
*
|
|
* dos_src/delay.c - non-stdlib delay function
|
|
* using the 8254 timer in DOS PCs
|
|
*
|
|
* Copyright (C) 2021 Andreas Zdziarstek
|
|
*/
|
|
|
|
#include <dos.h>
|
|
#include <conio.h>
|
|
|
|
#include "delay.h"
|
|
|
|
static void interrupt (*orig_isr)(void);
|
|
static volatile unsigned int ticks = 0, doscall_counter = 0;
|
|
|
|
/* interrupt handler for Timer 0 */
|
|
static void interrupt tim_0_isr(void) {
|
|
ticks++;
|
|
doscall_counter++;
|
|
|
|
/* Call original DOS handler about every 55ms (approx 18.2Hz) */
|
|
if (doscall_counter >= 55) {
|
|
doscall_counter = 0;
|
|
_chain_intr(orig_isr);
|
|
} else {
|
|
/* if not, signal EOI to the PIC */
|
|
outp(0x20, 0x20);
|
|
}
|
|
}
|
|
|
|
/* Hardware timer delay funtion, busy-waits for
|
|
* delay milliseconds using the 8254 timer 0
|
|
*/
|
|
void delay_ms(unsigned int delay) {
|
|
/* Save the address of the original 18.2Hz DOS
|
|
* Timer ISR
|
|
*/
|
|
orig_isr = _dos_getvect(0x08);
|
|
|
|
//reset ticks and doscall counter
|
|
ticks = 0;
|
|
doscall_counter = 0;
|
|
|
|
/* Disable interrupts */
|
|
_disable();
|
|
|
|
/* Install our new timer ISR */
|
|
_dos_setvect(0x08, tim_0_isr);
|
|
|
|
/* Set Timer 0 prescaler and start counting*/
|
|
outp(0x43, 0x36);
|
|
outp(0x40, 0xA8); // Prescaler 0x04A8 == 1192
|
|
outp(0x40, 0x04); // 1192/1193180Hz is approx 1ms
|
|
// We could also do 1193 but 1192 gives a better
|
|
// approximation to the 18.2Hz DOS interrupt.
|
|
// Don't really know if that's important though.
|
|
|
|
/* Enable interrupts */
|
|
_enable();
|
|
|
|
// Busy-wait delay ms
|
|
while(ticks < delay);
|
|
|
|
// Disable interrupts
|
|
_disable();
|
|
// Restore the original timer 0 ISR
|
|
_dos_setvect(0x08, orig_isr);
|
|
|
|
// Restore Timer 0 configuration
|
|
// 0x0000 is a special case that
|
|
// gets interpreted as the highest
|
|
// possible prescaler of 65536, yielding
|
|
// the good old 18.2 Hz interrupt
|
|
outp(0x43, 0x36);
|
|
outp(0x40, 0x00);
|
|
outp(0x40, 0x00);
|
|
|
|
// Enable interrupts again and we're done,
|
|
// hopefully without breaking anything :)
|
|
_enable();
|
|
}
|
|
|