Subject: Priority and speed (Long...)
To: None <port-i386@netbsd.org>
From: Grant Stockly <gussie@stockly.com>
List: port-i386
Date: 06/17/1999 00:23:02
I've got a little problem. I've written two different software programs.
One compiles for DOS, one on a i386 BSD machine (and I don't know what else).
I'm having a little problem with the BSD machine. The programs I've
written stream data 8bits at a time through the parallel port at 16kbytes/s
-EXACTLY-. The computer sends another byte when the BUSY line physically
goes high (from outside the computer) [computer thinks its low].
So, at 128000 wires a second, the 486DX20 dies a very quick death.
Stats:
Computers running PASCAL DOS program:
486 SX 16 - Plays from ram at full speed, skips when HD read.
486 SX 33 - Plays from ram at full speed, skips every 5 HD access (HD
access every second)
486 DX 120 - Plays from ram at full speed, skips every 20 to 3 seconds (it
is a strange computer. Today the primary IDE bus stopped working. :\ )
PII 200MHz - Plays full speed from both ram and HD. works like a charm.
Computer running C DOS program:
486 DX 20 - Plays from ram at 1/7th full speed, doesn't ever play when HD
accessed.
I'm not about to beleive that a DOS box running a Pascal program is faster
than a UNIX box.
Some things that you might find interesting:
UID of app: 8065
PRI of app: 52-64 (it was changing constantly!)
RAM used: 423k (ram buffer...)
CPU used: 92%
I'm guessing there might be a way to set priority of a program? I'd like
to force the program to use the best priority available. I don't care
about network access or any other server tasks that might be setup. I'm
also wondering if there is a way to read a file in the background. Kind of
like a circular buffer. I'd like to be able to play from a buffer [a], and
while streaming that buffer it will fill buffer [b].
Thanks for your time,
Grant
Pascal code that runs on DOS machines: (UNIX code futher down...)
program mp_play;
uses crt,dos;
const lpt_data = $278;
lpt_ctrl = lpt_data+1;
const max_block_size =16*1024;
BUSY = 128;
INIT = 4;
STROBE = 1;
type TArray = array[0..max_block_size-1] of byte;
PArray = ^TArray;
procedure PlayByte(b:byte);
VAR ctrl : Byte;
Begin
asm
cli;
end;
while (port[lpt_ctrl] and BUSY)=BUSY do;
port[lpt_data] := b;
ctrl := port[lpt_ctrl+1];
port[lpt_ctrl+1] := ctrl OR 1; { STROBE }
while (port[lpt_ctrl] and BUSY)<>BUSY do; { processing...}
port[lpt_ctrl+1] := ctrl AND ($e); { /Strobe }
asm
sti;
end;
End;
procedure PlayBuffer(P:PArray;size:word);
Var i : word;
b : byte;
ctrl : Byte;
Begin
For i := 0 to size-1 do
begin
{ PlayByte(p^[i-1]);}
asm
{ cli;}
end;
while (port[lpt_ctrl] and BUSY)=BUSY do;
port[lpt_data] := p^[i];
ctrl := port[lpt_ctrl+1];
port[lpt_ctrl+1] := ctrl OR 1; { STROBE }
while (port[lpt_ctrl] and BUSY)<>BUSY do; { processing...}
port[lpt_ctrl+1] := ctrl AND ($e); { /Strobe }
asm
sti;
end;
end;
End;
procedure play_mp3(name : String);
VAR Buf : PArray;
f : File;
result : word;
i,l : longint;
h0,h1,m0,m1,s0,s1,hs0,hs1:Word;
t0,t1:Extended;
begin
port[lpt_ctrl+1] := port[lpt_ctrl+1] OR INIT;
delay(100);
GetMem(Buf,SizeOf(Tarray)); { Get memory }
{$i-}
Assign(f,name);
Reset(f,1);
{$i+}
if ioresult=0 Then Begin
l := filesize(f) div max_block_size;
i := 0;
GetTime(h0,m0,s0,hs0);
t0 := s0+m0*60;
t1 := t0;
Repeat
write('Playing block ',i,' of ',l+1,' kB/s:
',(i*max_block_size*8)/(t1-t0+1):10:10,' ',#13);
inc(i);
BlockRead(f,buf^,max_block_size,result);
PlayBuffer(buf,result);
GetTime(h1,m1,s1,hs1);
t1 := s1+m1*60;
until eof(f) or keypressed or (result<>max_block_size);
Close(f);
end else writeln('File error!');
FreeMem(Buf,SizeOf(Tarray)); { release memory }
{ port[lpt_ctrl+1] := port[lpt_ctrl+1] AND ($F-INIT);}
end;
begin
clrscr;
Writeln('Playing file:'+paramstr(1));
repeat
play_mp3(paramstr(1));
until keypressed;
end.
C code running on UNIX:
#include <stdio.h>
#include <err.h>
#include <sys/types.h>
#include <machine/pio.h>
#include <machine/sysarch.h>
#define DATA 0x378
#define STATUS 0x378+1
#define CONTROL 0x378+2
#define BUSYo 0x80
#define STROBEo 0x01
#define BUSYa 0x7F
#define STROBEa 0xFE
#define mp3_second 128000
#define file_second mp3_second
static inline void
setaccess(u_long * map, u_int bit, int allow)
{
u_int word;
u_int shift;
u_long mask;
word = bit / 32;
shift = bit - (word * 32);
mask = 0x000000001 << shift;
if (allow)
map[word] &= ~mask;
else
map[word] |= mask;
}
int
main(int argc, char **argv)
{
u_long iomap[32];
u_long i;
FILE *mpeg_file;
u_long filesize;
u_long curread;
char mpeg_storage[file_second];
int stop;
char *namefile;
if( (mpeg_file = fopen("./sample.file", "rb")) == NULL) {
printf("Error reading %s!\n", namefile);
exit(1);
};
fseek(mpeg_file, 0, SEEK_SET);
filesize = 0;
curread = 0;
stop = 0;
if (i386_get_ioperm(iomap) == -1)
errx(1, "i386_get_ioperm failed");
setaccess(iomap, CONTROL, 1);
setaccess(iomap, STATUS, 1);
setaccess(iomap, DATA, 1);
if (i386_set_ioperm(iomap) == -1)
errx(1, "i386_set_ioperm failed");
do {
curread = fread(mpeg_storage, 1, file_second, mpeg_file);
filesize = filesize + curread;
printf("Played %d bytes\n", filesize);
if ( curread < file_second ) {
stop = 1;
};
i = 0;
do {
while((inb(STATUS) & BUSYo) == BUSYo);
outb(DATA, mpeg_storage[i]);
outb(CONTROL, (inb(CONTROL) | STROBEo));
while((inb(STATUS) & BUSYo) != BUSYo);
outb(CONTROL, (inb(CONTROL) & STROBEa));
i++;
} while( i != curread ) ;
} while( stop != 1 );
return(1);
};