This is next56.c in view mode; [Download] [Up]
/* 56000 - nExt communication */
/* compiled: cc next56.c -c -O */
/* changed relatively drastically during Feb-94 for port to Intel and so on
* Main change: TRDY => TXDE at DAJ's request to make future device drivers simpler
* (the MusicKit uses TXDE, I originally used TRDY)
* Related change: removed all "l" series functions -- these were debugging conveniences
* Also: removed calls on DSPOpenNoBoot and DSPClose and substituted lower level snddriver calls.
*/
#include "clmdsp.h" /* dsp.h and hostInterface declaration */
#include <sound/sound.h>
#include <sound/sounddriver.h>
#include <mach/mach.h>
#include <sys/file.h>
#include <sys/mman.h> /* protection bits etc */
/* for a Turbo NeXT, delete the word "inline" here and in get_cpu_rx below */
inline put_cpu_tx(int x)
{
#ifdef ARIEL_PC_56D
unsigned char hi = (x >> 16);
unsigned char med = ((x >> 8) & 0xff);
unsigned char low = (x & 0xff);
dsp_putTXRaw(current_active_dsp,hi,med,low);
#else
cpu_HI->data.tx.h = ((x >> 16) & 0xff);
cpu_HI->data.tx.m = ((x >> 8) & 0xff);
cpu_HI->data.tx.l = (x & 0xff);
#endif
}
inline get_cpu_rx(int *x)
{
#ifdef ARIEL_PC_56D
unsigned char hi,med,low;
dsp_getRXRaw(current_active_dsp,&hi,&med,&low);
*x = hi;
*x = (*x << 8) | med;
*x = (*x << 8) | low;
#else
/* byte-wise order should be high middle low (RXDF cleared when low read -- 10-23) */
*x = ((cpu_HI->data.rx.h) << 16);
*x = *x | ((cpu_HI->data.rx.m) << 8);
*x = *x | (cpu_HI->data.rx.l);
#endif
}
static int dsp_fd = -1; /* "static" here apparently means "internal" */
#ifndef ARIEL_PC_56D
static int current_active_dsp = -1;
#endif
int wait_time = 1000000;
#ifndef ARIEL_PC_56D
DSPRegs *getDSPRegs()
/* from (system 1.0) /NextLibrary/Documentation/NeXT/SysRefMan/14_ProgDSP.wn */
/* not documented (or guaranteed to work) in system 2.0, but will work at least another year... */
/* see /usr/include/nextdev/snd_dspreg.h */
/*
* The following function memory-maps the DSP host interface.
* Memory-mapped access can interfere with the Mach Sound/DSP
* driver, so normally the driver is kept unaware during
* memory-mapped control by zeroing RREQ and TREQ in the
* Interrupt Control Register (ICR) of the host interface;
* this ensures that the DSP never interrupts the host, which
* would cause the driver to read and possibly write the DSP.
*/
{
char *alloc_addr; /* page address for DSP memory map */
dsp_fd = open("/dev/dsp",O_RDWR); /* need <sys/file.h> */
if (dsp_fd == -1)
return(NULL);
if (( alloc_addr = (char *)valloc(getpagesize()) ) == NULL)
return(NULL);
if ( -1 == mmap(alloc_addr,
getpagesize(), /* Must map a full page */
PROT_READ|PROT_WRITE, /* rw access <sys/mman.h> */
MAP_SHARED, /* shared access (of course) */
dsp_fd, /* This device */
0) ) /* 0 offset */
return(NULL);
return (DSPRegs *)alloc_addr; /* <dsp/dsp_structs.h> */
}
#endif
/* the following are the indices to direct lisp (from C) function calls (a sort of case statement) */
#define SERVICE_BREAK 0
#define READ_INPUT 1
#define LOCSIZ_SERVICE_BREAK 2
#define AWAIT_GET_SERVICE_BREAK 3
#define AWAIT_PUT_SERVICE_BREAK 4
#define AWAIT_OUTPUT_SERVICE_BREAK 6
wait_a_while (int ticks)
{
int i;
for (i=0;i<=ticks;i++);
}
cleararray(int beg, int end, int *arr)
{
int *i,*j;
j=arr+end; /* C compiler on Next doesn't optimize these expressions out of the loop, so... */
for (i=arr+beg;i<=j;i++) *i=0; /* for (i=beg;i<=end;i++) arr[i]=0; */
}
arrtran (int beg1, int end1, int *arr1, int beg2, int *arr2)
{
int *i,*j,*k;
k=arr1+end1;
for (i=arr1+beg1,j=arr2+beg2;i<=k;i++,j++) *j=*i; /* arr2[beg2 by j]=arr1[beg1 to end1 by i] */
}
cloadfarr(float *tbl, int siz, int beg, int *mem)
{
int i,j,fix,exp23;
exp23=8388608; /* 1 << 23 may be C's way of saying this */
for (i=0,j=beg;i<siz;i++,j++)
{
if (tbl[i] != 1.0)
{
fix=(tbl[i]*exp23);
mem[j]=(fix & 0xffffff);
}
else mem[j]=0x7fffff; /* two's complement 24-bit max pos num -- "fractional" one */
}
}
/* Now some very unfortunate duplication of code -- in system 1.0 this was unnecessary */
/* -------------------------------------- AwaitData ---------------------------------- */
inline int Await_cpu_Data(int ms)
{
int i;
if (CPU_ISR&1) return 0;
i=0;
while ((!(CPU_ISR&1)) && (i<ms)) ++i;
if (CPU_ISR&1) return 0;
return -1;
}
inline int Await_qp_Data(int ms)
{
int i;
if (QP_ISR&1) return 0;
i=0;
while ((!(QP_ISR&1)) && (i<ms)) ++i;
if (QP_ISR&1) return 0;
return -1;
}
inline int AwaitData(int ms)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = Await_cpu_Data(ms);
else i = Await_qp_Data(ms);
}
return i;
}
/* -------------------------------------- AwaitTRDY ---------------------------------- */
/* changed to TXDE at DAJ's request 16-Feb-94 */
inline int Await_cpu_TRDY(int ms)
{
int i;
if (CPU_ISR&2) return 0;
i=0;
while ((!(CPU_ISR&2)) && (i<ms)) ++i;
if (CPU_ISR&2) return 0;
return -1;
}
inline int Await_qp_TRDY(int ms)
{
int i;
if (QP_ISR&2) return 0;
i=0;
while ((!(QP_ISR&2)) && (i<ms)) ++i;
if (QP_ISR&2) return 0;
return -1;
}
inline int AwaitTRDY(int ms)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = Await_cpu_TRDY(ms);
else i = Await_qp_TRDY(ms);
}
return i;
}
/* -------------------------------------- HF2 --------------------------------------- */
inline int cpu_HF2 (void)
{
return (CPU_ISR&8);
}
inline int qp_HF2 (void)
{
return (QP_ISR&8);
}
inline int HF2 (void)
{
int i;
i = -1;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_HF2();
else i = qp_HF2();
}
return i;
}
/* -------------------------------------- HF3 --------------------------------------- */
inline int cpu_HF3 (void)
{
return (CPU_ISR&16);
}
inline int qp_HF3 (void)
{
return (QP_ISR&16);
}
inline int HF3 (void)
{
int i;
i = -1;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_HF3();
else i = qp_HF3();
}
return i;
}
/* -------------------------------------- ISR et al ------------------------------------- */
int get_ISR (void)
{
int i;
i = -1;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = CPU_ISR;
else i = QP_ISR;
}
return i;
}
int get_ICR (void)
{
int i;
i = -1;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = CPU_ICR;
else i = QP_ICR;
}
return i;
}
int get_CVR (void)
{
int i;
i = -1;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = CPU_CVR;
else i = QP_CVR;
}
return i;
}
put_CVR (int word)
{
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
put_cpu_cvr(word);
else put_qp_cvr(word);
}
}
put_ICR (int word)
{
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
put_cpu_icr(word);
else put_qp_icr(word);
}
}
/* -------------------------------------- checkHF3 ------------------------------------- */
int check_cpu_HF3 (void)
{
int i;
long lisp_call(int index);
if ((cpu_HF3() != 0) && (cpu_HF3() != 0))
{
/* see Motorola DSP56000 manual section 10.2.6.5 -- when HF2 and 3 used as a pair (as here) */
/* you may see indeterminate states during a transition, so you have to read twice */
if ((cpu_HF2() == 0) && (cpu_HF2() == 0))
{
i=0;
while ((cpu_HF3() != 0) && (cpu_HF2() == 0) && (i<wait_time)) ++i;
if ((cpu_HF2() == 0) && (cpu_HF3() != 0))
lisp_call(SERVICE_BREAK);
else
if ((cpu_HF2() != 0) && (cpu_HF3() != 0))
{
lisp_call(READ_INPUT);
return 1;
}
/* all of this paranoia is an attempt to deal with an apparent race condition where we jump in */
/* to look for both flags on, and see only one on */
return 0;
}
/* clservicebreak in next56.lisp -- HF3 used as signal for forced break */
/* if returned lisp value ever used, remember it is << 3 */
else
{
lisp_call(READ_INPUT);
return 1;
}
}
return 0;
}
int check_qp_HF3 (void)
{
int i;
long lisp_call(int index);
if ((qp_HF3() != 0) && (qp_HF3() != 0)) /* see note above */
{
if ((qp_HF2() == 0) && (qp_HF2() == 0))
{
i=0;
while ((qp_HF3() != 0) && (qp_HF2() == 0) && (i<wait_time)) ++i;
if ((qp_HF2() == 0) && (qp_HF3() != 0))
lisp_call(SERVICE_BREAK);
else
if ((qp_HF2() != 0) && (qp_HF3() != 0))
{
lisp_call(READ_INPUT);
return 1;
}
return 0;
}
else
{
lisp_call(READ_INPUT);
return 1;
}
}
return 0;
}
int checkHF3 (void)
{
int i;
long lisp_call(int index);
if ((HF3() != 0) && (HF3() != 0)) /* see note above */
{
if ((HF2() == 0) && (HF2() == 0))
{
i=0;
while ((HF3() != 0) && (HF2() == 0) && (i<wait_time)) ++i;
if ((HF2() == 0) && (HF3() != 0))
lisp_call(SERVICE_BREAK);
else
if ((HF2() != 0) && (HF3() != 0))
{
lisp_call(READ_INPUT);
return 1;
}
return 0;
}
else
{
lisp_call(READ_INPUT);
return 1;
}
}
return 0;
}
/* -------------------------------------- put and get ------------------------------------- */
#ifdef ARIEL_PC_56D
inline void arielpc56d_putoneword(int word)
{
unsigned char hi = (word >> 16);
unsigned char med = ((word >> 8) & 0xff);
unsigned char low = (word & 0xff);
dsp_putTX(current_active_dsp,hi,med,low);
}
inline void arielpc56d_getoneword(int *reply)
{
unsigned char hi,med,low;
unsigned int ho;
dsp_getRX(current_active_dsp,&hi,&med,&low);
ho = hi;
ho = (ho << 8) | med;
ho = (ho << 8) | low;
*reply = ho;
}
#endif
inline int cpu_putoneword(int word)
{
#ifdef ARIEL_PC_56D
arielpc56d_putoneword(word);
#else
if (CPU_ISR&2) put_cpu_tx(word);
else
{
if (Await_cpu_TRDY(wait_time) != 0) lisp_call(AWAIT_PUT_SERVICE_BREAK);
put_cpu_tx(word);
}
#endif
return 0;
}
inline int qp_putoneword(int word)
{
if (QP_ISR&2) put_qp_tx(word);
else
{
if (Await_qp_TRDY(wait_time) != 0) lisp_call(AWAIT_PUT_SERVICE_BREAK);
put_qp_tx(word);
}
return 0;
}
inline int dspputoneword (int word)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_putoneword(word);
else i = qp_putoneword(word);
}
return i;
}
inline int cpu_getoneword(void)
{
int reply;
#ifdef ARIEL_PC_56D
arielpc56d_getoneword(&reply);
#else
if (CPU_ISR&1) get_cpu_rx(&reply);
else
{
if (Await_cpu_Data(wait_time) != 0) lisp_call(AWAIT_GET_SERVICE_BREAK);
get_cpu_rx(&reply);
}
#endif
return reply;
}
inline int qp_getoneword(void)
{
int reply;
if (QP_ISR&1) get_qp_rx(&reply);
else
{
if (Await_qp_Data(wait_time) != 0) lisp_call(AWAIT_GET_SERVICE_BREAK);
get_qp_rx(&reply);
}
return reply;
}
inline int dspgetoneword(void)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_getoneword();
else i = qp_getoneword();
}
return i;
}
inline int cpu_putarray(int beg, int end, int *arr)
{
#ifdef ARIEL_PC_56D
dsp_putArray(current_active_dsp,arr+beg,end-beg+1);
#else
int *i,*last;
last=arr+end;
for (i=(arr+beg);i<=last;i++)
{
cpu_putoneword(*i);
}
#endif
return (end-beg+1);
}
inline int qp_putarray(int beg, int end, int *arr)
{
int *i,*last;
last=arr+end;
for (i=(arr+beg);i<=last;i++)
{
qp_putoneword(*i);
}
return (end-beg+1);
}
inline int dspputarray(int beg, int end, int *arr)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_putarray(beg,end,arr);
else i = qp_putarray(beg,end,arr);
}
return i;
}
inline int cpu_getarray(int beg, int end, int *arr)
{
#ifdef ARIEL_PC_56D
dsp_getArray(current_active_dsp,arr+beg,end-beg+1);
#else
int *i,*last;
last=arr+end;
for (i=(arr+beg);i<=last;i++)
{
if (CPU_ISR&1) get_cpu_rx(i);
else (*i)=cpu_getoneword();
}
#endif
return (end-beg+1);
}
inline int qp_getarray(int beg, int end, int *arr)
{
int *i,*last;
last=arr+end;
for (i=(arr+beg);i<=last;i++)
{
if (QP_ISR&1) get_qp_rx(i);
else (*i)=qp_getoneword();
}
return (end-beg+1);
}
inline int dspgetarray(int beg, int end, int *arr)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_getarray(beg,end,arr);
else i = qp_getarray(beg,end,arr);
}
return i;
}
void clear_host_interfaces (void)
{
cpu_HI = NULL;
qp_HI = NULL;
}
#ifdef ARIEL_PC_56D
static void resetPC56d(void)
{
dsp_resetOn(current_active_dsp);
/* usleep(10000); */
wait_a_while(10000); /* usleep in the past has caused lisp to hang -- will try it later */ /* 100000 ok */
dsp_resetOff(current_active_dsp);
}
#endif
#define ARIEL_PC_IS_OPEN (-2)
static port_t dev_port, owner_port, cmd_port;
static int clm_dsp_error;
int get_clm_dsp_error(void) {return clm_dsp_error;}
int cpu_boot(int end, int *program) /* get Next built-in 56000, reset and load it */
{
#ifdef ARIEL_PC_56D
dsp_open(0);
resetPC56d();
dsp_selectMemoryMap(current_active_dsp,1);
dsp_fd = ARIEL_PC_IS_OPEN;
cpu_putarray(0,end,program);
#else
int i,err;
int *j,*pend;
dev_port = 0; owner_port = 0; cmd_port = 0;
err = SNDAcquire(SND_ACCESS_DSP, 10, 0, 0, NULL_NEGOTIATION_FUN, 0, &dev_port, &owner_port);
if (err == 0)
{
err = snddriver_get_dsp_cmd_port(dev_port,owner_port,&cmd_port);
if (err == 0)
{
err = snddriver_dsp_reset(cmd_port,SNDDRIVER_LOW_PRIORITY);
}
}
clm_dsp_error = err;
i=err;
if (i != 0) return -2;
cpu_HI = getDSPRegs(); /* get memory-mapped host interface */
if (cpu_HI == NULL) return -1;
pend=program+end;
for (j=program;j<=pend;j++)
put_cpu_tx(*j); /* load program -- see lib56.lisp for the monitor code */
#endif
put_cpu_icr(8); /* set HF0 to signal boot done -- see 56000 manual 10-43 */
return 0;
}
int cpu_close(void)
{
int err;
#ifdef ARIEL_PC_56D
if (dsp_fd == ARIEL_PC_IS_OPEN) dsp_close(current_active_dsp);
dsp_fd = -1;
return 0;
#else
if (cmd_port != 0) clm_dsp_error=port_deallocate(task_self(),cmd_port);
/* the close code in DSPObject.c deallocates the command port before calling SNDRelease */
/* if we call it afterwards, port_deallocate returns 4 */
err=SNDRelease(SND_ACCESS_DSP,dev_port,owner_port);
clm_dsp_error = ((clm_dsp_error << 16) | err);
if (cpu_HI != NULL)
free((char *)cpu_HI);
else err = -2;
cpu_HI = NULL;
if (dsp_fd != -1)
close(dsp_fd);
else err = -3;
dsp_fd = -1;
return err;
#endif
}
inline int checkhostInterface (void)
{
#ifdef ARIEL_PC_56D
return (dsp_fd == ARIEL_PC_IS_OPEN) ? 0 : -1;
#else
if ((cpu_HI == NULL) && (qp_HI == NULL)) return -1;
return 0;
#endif
}
int hival(void)
{
int i;
i = 0;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = (int)cpu_HI;
else i = (int)qp_HI;
}
return i;
}
inline int dspisopen (void)
{
#ifdef ARIEL_PC_56D
return (dsp_fd == ARIEL_PC_IS_OPEN) ? 1 : 0;
#else
if (dsp_fd == -1) return(0);
return(1);
#endif
}
/* on chip, output results are collected in buffers to be flushed out when full. */
/* The HF2 bit is set when the dsp has filled its output buffers. We build a list */
/* at run time on the lisp side of the locations and sizes of these buffers, and */
/* here we read the contents. If needed, input data is also sent to the chip at */
/* this time. Then, the dsp sets out on its next buffer, while we merge the results */
/* into the respective files. Once that is finished, we return to lisp awaiting HF2 */
/* External delay lines change this scenario a bit. */
/* #define DATSIZ 32768 */
#define DATSIZ 131072
/* static int datbuf[DATSIZ]; */ /* dump dsp's "external memory" here (16K for QP) (32K for exp mem) (65536*2 for SFSU mem) */
/* If we ever take advantage of SFSU P mem for delay lines, change this to 65536*3 */
#ifdef ARIEL_PC_56D
#define ZERO_SIZE 4096
static int *zero_buf;
#endif
static int *datbuf;
static int data_ok = -1;
check_datbuf (void)
{
int i;
if (data_ok == -1)
{
datbuf = (int *)calloc((DATSIZ),sizeof(int));
#ifdef ARIEL_PC_56D
zero_buf = (int *)calloc((ZERO_SIZE),sizeof(int));
for (i=0;i<ZERO_SIZE;i++) zero_buf[i]=0;
#endif
}
data_ok = 0;
}
#define NO_IO -1
#define OUT_N 0
#define IN_N 1
#define EXT_DLY 2
/* RAN_IN_N = 3 and EXT_ZDLY = 4, but only used in debugging */
inn(int beg, int siz, int bufbeg, int *arr, int fsize)
{
/* file data in ARR starts at file sample BEG, file size is FSIZE, we want SIZ samples, and */
/* we are currently at BUFBEG within ARR */
int num,zeros,k;
num = fsize-beg-bufbeg; /* max actual samples that could be read (can be negative) */
zeros = siz; /* in worst case (past eof), all samples are 0 */
if (num>0) /* if there are samples in arr (not past eof) */
{
if (siz<num)
k=siz;
else k=num;
if (current_active_dsp == 0)
{
cpu_putarray(bufbeg,bufbeg+k-1,arr);
}
else
{
qp_putarray(bufbeg,bufbeg+k-1,arr);
}
zeros = zeros - k;
}
if (zeros>0)
{
if (current_active_dsp == 0)
{
#ifdef ARIEL_PC_56D
for (k=0;k<zeros;k+=ZERO_SIZE)
{
if ((zeros-k) < ZERO_SIZE) { num=zeros-k; num-=1; } else num=ZERO_SIZE-1;
/* cc -O3 -DVOL=volatile -fwritable-strings -DARIEL_PC_56D -O -c -I. akkcl-c56.c -w */
/* if ((zeros-k) < ZERO_SIZE) num=zeros-k-1; else num=ZERO_SIZE-1; */
/* on the Pentium this compiles num=zeros+k+1 */
cpu_putarray(0,num,zero_buf);
}
#else
for (k=0;k<zeros;k++)
cpu_putoneword(0);
#endif
}
else
{
for (k=0;k<zeros;k++)
qp_putoneword(0);
}
}
}
inline outn (int outbeg, int outend, int *outa, int dspbeg, int *dspa)
{
int *i,*j,*last;
last=outa+outend;
if (outa != 0)
{
for (i=(outa+outbeg),j=(dspa+dspbeg);i<=last;i++,j++)
{
#ifdef ARIEL_PC_56D
*i += *j;
#else
if ((*j) & 0x800000)
*i += ((*j) | 0xffff0000);
else *i += *j;
#endif
}
}
}
/* outonebuf = dsp-merge-one-buffer and is used only in qplib56.lisp for partial DMEM flushes */
inline int cpu_outonebuf(int start, int stop, int *outloc)
{
int *i,*last, *first;
int val;
first=outloc+start;
last=outloc+stop;
for (i=first;i<=last;i++)
{
if (CPU_ISR&1) get_cpu_rx(&val);
else val=cpu_getoneword();
if (val & 0x800000)
*i += (val | 0xffff0000);
else *i += val;
}
return 0;
}
inline int qp_outonebuf(int start, int stop, int *outloc)
{
int *i,*last, *first;
int val;
first=outloc+start;
last=outloc+stop;
for (i=first;i<=last;i++)
{
if (QP_ISR&1) get_qp_rx(&val);
else val=qp_getoneword();
if (val & 0x800000)
*i += (val | 0xffff0000);
else *i += val;
}
return 0;
}
inline int outonebuf(int start, int stop, int *outloc)
{
int i;
i = -1;
if (current_active_dsp != -1)
{
if (current_active_dsp == 0)
i = cpu_outonebuf(start,stop,outloc);
else i = qp_outonebuf(start,stop,outloc);
}
return i;
}
inline dspsendinput(int *beg, int cursiz, int *sigops, int *sigptrs, int **sigadrs, int *sigsizes, int sigsiz)
{
int i;
dspputoneword(cursiz);
for (i=0;i<sigsiz;i++)
{
if (sigops[i] == IN_N)
{
inn(beg[i],cursiz,sigptrs[i],sigadrs[i],sigsizes[i]);
sigptrs[i] += cursiz;
}
}
}
inline WaitForHF2_NotHF3 (void)
{
/* be real patient here -- make the wait time out pretty excessive */
int happy,i,waiting;
happy = 1;
waiting = 0;
i = 0;
while (happy)
{
i++;
if (i>1000000)
{
put_CVR(0x96);
while ((HF2() == 0) || (HF3() != 0))
{
waiting++;
if (waiting>2000)
{
lisp_call(AWAIT_OUTPUT_SERVICE_BREAK);
}
}
}
if (HF2() != 0)
{
if ((HF3() != 0) && (HF2() != 0))
{
lisp_call(READ_INPUT);
i = 0;
}
else if (HF3() == 0)
{
happy = 0;
}
}
}
}
inline cpu_WaitForHF3_NotHF2 (void)
{
/* be real patient here -- make the wait time out pretty excessive */
int happy,i;
happy = 1;
i = 0;
while (happy)
{
if (cpu_HF3() != 0)
{
if ((cpu_HF2() != 0) && (cpu_HF3() != 0))
{
lisp_call(READ_INPUT);
i = 0;
}
else if ((cpu_HF2() == 0) && (cpu_HF3() != 0))
{
happy = 0;
}
}
else
{
i++;
if (i>1000000)
lisp_call(AWAIT_GET_SERVICE_BREAK);
}
}
}
inline qp_WaitForHF3_NotHF2 (void)
{
/* be real patient here -- make the wait time out pretty excessive */
int happy,i;
happy = 1;
i = 0;
while (happy)
{
if (qp_HF3() != 0)
{
if ((qp_HF3() != 0) && (qp_HF2() != 0))
{
lisp_call(READ_INPUT);
i = 0;
}
else if (qp_HF2() == 0)
{
happy = 0;
}
}
i++;
if (i>1000000)
lisp_call(AWAIT_GET_SERVICE_BREAK);
}
}
inline WaitForHF3_NotHF2 (void)
{
if (current_active_dsp == 0)
cpu_WaitForHF3_NotHF2();
else qp_WaitForHF3_NotHF2();
}
#define LOCSIZ 256
static int locs[LOCSIZ];
basicdspread (int beg, int end, int sigsiz, int dlys, int ins,
int *sigops, int **sigadrs, int *sigptrs,
int *sigbas, int *sigtop, int *sigsizes)
{
int i,k,curdsploc,num,cursiz,readsize;
if (sigsiz>LOCSIZ) lisp_call(LOCSIZ_SERVICE_BREAK);
check_datbuf();
if (dlys != 0) /* we have external delay lines in operation */
{
for (i=beg;i<=end;i++)
{
for (k=0;k<sigsiz;k++)
{
if (sigops[k] == EXT_DLY)
{
int *pt,*sp;
sp=sigptrs+k;
pt=sigadrs[k]+(*sp);
WaitForHF3_NotHF2();
dspputoneword(*pt);
(*pt)=dspgetoneword();
(*sp)++;
if ((*sp)>sigtop[k]) (*sp)=0; /* sigbas is index into *clm-delay-lines* */
}
}
}
}
curdsploc=0;
cursiz=(end-beg);
readsize=cursiz+1;
WaitForHF2_NotHF3();
dspputoneword(readsize);
for (i=0;i<sigsiz;i++)
{
if (sigops[i] == OUT_N)
{
locs[i] = curdsploc;
num=dspgetarray(curdsploc,curdsploc+cursiz,datbuf);
curdsploc += num;
}
}
if (ins != 0)
{
dspsendinput(sigbas,readsize,sigops,sigptrs,sigadrs,sigsizes,sigsiz);
}
/* now the dsp should be running again -- merge current output into output buffers */
for (i=0;i<sigsiz;i++)
{
if (sigops[i] == OUT_N)
{
outn(beg,end,sigadrs[i],locs[i],datbuf);
}
}
}
rpc_dsp_merge_all_output(int beg, int end, int **sigadrs, int *sigops, int sigsiz, int *ldatbuf)
{
int cursiz,curloc,i;
cursiz = (end-beg);
curloc = 0;
for (i=0;i<sigsiz;i++)
{
if (sigops[i] == OUT_N)
{
outn(beg,end,sigadrs[i],curloc,ldatbuf);
curloc += cursiz;
}
}
}
#define RTS_op 12
#define Clear_HF3 698372
#define Move_X_HTX 585899
#define No_op 0
int dspstartagain(int tag, int tagloc)
{
return ( (checkhostInterface() == 0) && /* it appears that we have a pointer to its registers */
(HF3() != 0) && (HF3() != 0) && /* it appears to be sitting at our breakpoint handler */
(HF2() == 0) && (HF2() == 0) && /* (not bug56...) (on repeat reads see note under hf3) and */
(dspputoneword(Clear_HF3) != -1) && /* BCLR M-HF3 X-IO M-HCR... */
(dspputoneword(No_op) != -1) && /* NOP (2 wrd command in breakpoint handler)... */
(HF3() == 0) && /* executed ok! -- we must be at .break and */
(dspputoneword(Move_X_HTX) != -1) && /* MOVE X tag-loc X-IO M-HTX... */
(dspputoneword(tagloc) != -1) && /* (tag-loc)... */
(dspgetoneword() == tag) && /* tag is the same -- current instrument must already be loaded and */
(dspputoneword(RTS_op) != -1) && /* RTS (from .break)... */
(dspputoneword(No_op) != -1)); /* NOP (2nd word) -- we should now be awaiting the next note's data */
} /* Otherwise, reset chip and load everything */
int dspdataready (void)
{
int i;
i = 0;
if (checkhostInterface() == 0) i = checkHF3();
if (i == 1) return 0;
return ( (checkhostInterface() == 0) &&
(HF2() != 0) && (HF2() != 0) && /* if we see .input's flags here by accident, endless trouble */
(HF3() == 0) && (HF3() == 0) && /* so read everything twice -- if only we had more of these flags... */
(HF2() != 0) && (HF3() == 0));
}
int dspsetupprogram(int ix, int iy, int ex, int ey, int ep, int xoff, int yoff, int poff, int *ixarr, int *iyarr, int *earr)
{
if (dspputoneword(ix) != 0) return 1;
if (ix != 0)
{
dspputoneword(0);
if (dspputarray(0,ix-1,ixarr) != ix) return 2;
}
if (dspputoneword(iy) != 0) return 3;
if (iy != 0)
{
dspputoneword(0);
if (dspputarray(0,iy-1,iyarr) != iy) return 4;
}
if (dspputoneword(ex) != 0) return 5;
if (ex != 0)
{
dspputoneword(xoff);
if (dspputarray(0,ex-1,earr) != ex) return 6;
}
if (dspputoneword(ey) != 0) return 7;
if (ey != 0)
{
dspputoneword(xoff); /* xoff because we're asking here for the chip's notion of the start of Y memory, not our own */
/* then yoff in the put array call because there we're dealing with our offset into external-memory */
if (dspputarray(yoff,yoff+ey-1,earr) != ey) return 8;
}
if (dspputoneword(ep) != 0) return 9;
if (ep != 0)
{
dspputoneword(poff);
if (dspputarray(poff,poff+ep-1,earr) != ep) return 10;
}
return 0;
}
set_active_dsp(int num) {current_active_dsp = num;}
int get_active_dsp(void) {return current_active_dsp;}
int set_wait_time (int ms)
{
int old_wait;
old_wait = wait_time;
wait_time = ms;
return old_wait;
}
int get_wait_time (void) {return wait_time;}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.