00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <stdlib.h>
00033
00034 #include "tdef.h"
00035 #include "xalloc.h"
00036 #include "lmem.h"
00037 #include "dma.h"
00038 #include "dmabuff.h"
00039 #include "intrs.h"
00040 #include "sb.h"
00041 #include "blaster.h"
00042
00043 #include "xsnd.h"
00044
00045
00046
00047
00048
00049 #define MAX_BLK_PER_SEC 1000;
00050
00051
00052
00053 PRIVATE BOOL _initialized = FALSE;
00054
00055 PRIVATE UINT16 _baseport;
00056 PRIVATE UINT16 _irq;
00057 PRIVATE UINT16 _dmach;
00058
00059 PRIVATE BOOL _record;
00060 PRIVATE UINT16 _srate;
00061 PRIVATE BOOL _stereo;
00062
00063 PRIVATE IntrServiceFunc _oldint;
00064
00065 PRIVATE UINT16 _nblk;
00066 PRIVATE UINT16 _dmablk;
00067 PRIVATE UINT16 _qblk;
00068 PRIVATE UINT32 _blklen;
00069 PRIVATE UINT16 _qtail;
00070
00071 PRIVATE UINT16 _taillen;
00072 PRIVATE phINT8 _buffptr;
00073 PRIVATE UINT32 _bufflmem;
00074 PRIVATE pfVOID _buffmem;
00075 PRIVATE UINT16 _samplelen;
00076 PRIVATE UINT16 _sblen;
00077 PRIVATE BOOL _inusrproc;
00078 PRIVATE UINT16 _overrun;
00079
00080 PRIVATE INT16 _status;
00081 enum STATUS { AWAIT=1, WAIT1, WAIT1A, WAIT2, WAIT3,
00082 WAIT4, WAIT5, WAIT6, WAIT6A, BLOCK };
00083
00084 PRIVATE VOID (PTRF _usrproc) ( BOOL last );
00085
00086
00087
00088 PRIVATE VOID INTERRUPT _newint( VOID )
00089 {
00090 BOOL up = FALSE;
00091
00092 if ((sb_IRQ_stat(_baseport) & DSP_MASK_IRQ_DMA8MIDI) != 0) {
00093 switch (_status) {
00094 case WAIT1:
00095 if (_qblk>1) {
00096 sb_IRQ_ack_dma8midi(_baseport);
00097 _status = WAIT2;
00098 }
00099 else if (!_qtail) {
00100 _status = WAIT1A;
00101 }
00102 else if (_qtail==1) {
00103 sb_DSP_8(_baseport, _record, SB_DSP_SINGLE_CICLE,
00104 SB_DSP_FIFO_ON, _stereo, SB_DSP_UNSIGNED, _taillen);
00105 sb_IRQ_ack_dma8midi(_baseport);
00106 _status = WAIT3;
00107 }
00108 else {
00109 sb_DSP_8_exit(_baseport);
00110 sb_IRQ_ack_dma8midi(_baseport);
00111 _status = WAIT4;
00112 }
00113 break;
00114 case WAIT2:
00115 sb_IRQ_ack_dma8midi(_baseport);
00116 _qblk--;
00117 if ((++_dmablk)==_nblk)
00118 _dmablk = 0;
00119 _status = WAIT1;
00120 up = TRUE;
00121 break;
00122 case WAIT3:
00123 sb_IRQ_ack_dma8midi(_baseport);
00124 _qblk--;
00125 _status = WAIT4;
00126 up = TRUE;
00127 break;
00128 case WAIT4:
00129 sb_IRQ_ack_dma8midi(_baseport);
00130 _status = BLOCK;
00131 up = TRUE;
00132 break;
00133 case WAIT5:
00134 sb_DSP_8_exit(_baseport);
00135 sb_IRQ_ack_dma8midi(_baseport);
00136 _status = WAIT4;
00137 up = TRUE;
00138 break;
00139 case WAIT6:
00140 sb_IRQ_ack_dma8midi(_baseport);
00141 _status = WAIT6A;
00142 up = TRUE;
00143 break;
00144 case WAIT6A:
00145 sb_DSP_8_exit(_baseport);
00146 sb_IRQ_ack_dma8midi(_baseport);
00147 _status = WAIT4;
00148 break;
00149 }
00150 PIC_SEND_EOI(_irq);
00151 if (_usrproc && up) {
00152 if (_inusrproc)
00153 _overrun++;
00154 else {
00155 _inusrproc = TRUE;
00156 _usrproc(_status==BLOCK);
00157 _inusrproc = FALSE;
00158 }
00159 }
00160 }
00161 else
00162 _oldint();
00163 }
00164
00165
00166
00167 UINT16 xsnd8_reset( VOID )
00168 {
00169 sb_DSP_8_pause(_baseport);
00170
00171 _status = -AWAIT;
00172 _dmablk = 0;
00173 _qblk = (_record?_nblk:0);
00174 _qtail = 0;
00175 _overrun = 0;
00176
00177
00178 dma_set(_dmach, DMA_INCREMENT, DMA_AUTO_INIT,
00179 _record?DMA_WRITE_TO_MEM:DMA_READ_FROM_MEM,
00180 _bufflmem, (UINT16)(_samplelen*_nblk*_blklen - 1), DMA_ENABLE);
00181
00182 return 0;
00183 }
00184
00185
00186
00187 UINT16 xsnd8_open( BOOL record, UINT16 srate, BOOL stereo,
00188 UINT32 blklen, UINT16 numblk, VOID (PTRF usrproc) ( BOOL last) )
00189 {
00190 UINT32 maxlen, minlen, bufflen;
00191 UINT32 len, use;
00192
00193 if (_initialized)
00194 return 1;
00195
00196
00197 _baseport = blaster_env(BLASTER_BASEPORT,
00198 BLASTER_DEFAULT_BASEPORT, BLASTER_DECHEX_BASEPORT);
00199 _irq = blaster_env(BLASTER_IRQ,
00200 BLASTER_DEFAULT_IRQ, BLASTER_DECHEX_IRQ);
00201 _dmach = blaster_env(BLASTER_DMA8,
00202 BLASTER_DEFAULT_DMA8,BLASTER_DECHEX_DMA8);
00203
00204 if (record) {
00205 if (sb_DSP_in_rate(_baseport,srate))
00206 return 1;
00207 }
00208 else
00209 if (sb_DSP_out_rate(_baseport,srate))
00210 return 1;
00211
00212 _record = record;
00213 _stereo = stereo;
00214 _srate = srate;
00215 _blklen = blklen;
00216 _usrproc = usrproc;
00217 _inusrproc = FALSE;
00218
00219 _samplelen = ( stereo ? 2 : 1 );
00220 maxlen = (1024L*64L)/_samplelen;
00221 minlen = _srate/MAX_BLK_PER_SEC;
00222
00223 if (_blklen>maxlen)
00224 return 1;
00225 if (_blklen<minlen)
00226 return 1;
00227 if (_blklen<2)
00228 return 1;
00229 if (_blklen % 2)
00230 return 1;
00231
00232 _sblen = (UINT16)((stereo?_blklen:_blklen/2)-1);
00233 _nblk = (UINT16)(numblk ? numblk : maxlen/_blklen);
00234
00235 do {
00236 bufflen = _blklen*_nblk;
00237 if (bufflen > maxlen)
00238 return 1;
00239 _buffmem = dmabuff_malloc(bufflen*_samplelen, 64, 1,
00240 blklen*_samplelen,&len);
00241 if (_buffmem==NULL) {
00242
00243 if ((!numblk) && (_nblk>1))
00244 _nblk--;
00245 else
00246 return 1;
00247 }
00248 } while (_buffmem==NULL);
00249
00250 _buffptr = (pfINT8)fixmem(_buffmem, len, 64, 1,
00251 blklen*_samplelen, &_bufflmem, &use);
00252
00253 xsnd8_reset();
00254
00255 _oldint = INT_GET_VEC(IRQ_INTN(_irq));
00256 INT_SET_VEC(IRQ_INTN(_irq),_newint);
00257 PIC_ENABLE(_irq);
00258 PIC_SEND_EOI(_irq);
00259
00260 _initialized = TRUE;
00261
00262 return 0;
00263 }
00264
00265
00266
00267 UINT16 xsnd8_close( VOID )
00268 {
00269 if (!_initialized)
00270 return 1;
00271
00272 sb_DSP_8_pause(_baseport);
00273
00274
00275 dma_disable(_dmach);
00276
00277
00278
00279
00280
00281 INT_SET_VEC(IRQ_INTN(_irq),_oldint);
00282
00283 xfree(_buffmem);
00284
00285 _initialized = FALSE;
00286
00287 return 0;
00288 }
00289
00290
00291
00292 UINT16 xsnd8_start( VOID )
00293 {
00294 if (_status>AWAIT)
00295 return 1;
00296 if (_status<0)
00297 _status = -_status;
00298
00299 if (_status>AWAIT)
00300 sb_DSP_8_continue(_baseport);
00301 else if (_qblk) {
00302 _status=WAIT1;
00303 sb_DSP_8(_baseport, _record, SB_DSP_AUTO_INIT,
00304 SB_DSP_FIFO_ON, _stereo, SB_DSP_UNSIGNED, _sblen);
00305 }
00306 else if (_qtail==1) {
00307 _status=WAIT4;
00308 sb_DSP_8(_baseport, _record, SB_DSP_SINGLE_CICLE,
00309 SB_DSP_FIFO_ON, _stereo, SB_DSP_UNSIGNED, _taillen);
00310 }
00311 else if (_qtail==2) {
00312 _status=BLOCK;
00313 }
00314
00315 return 0;
00316 }
00317
00318
00319
00320 UINT16 xsnd8_stop( VOID )
00321 {
00322 sb_DSP_8_pause(_baseport);
00323 if (_status<0)
00324 return 1;
00325
00326 _status = -_status;
00327 return 0;
00328 }
00329
00330
00331
00332 UINT16 xsnd8_getoverrun( VOID )
00333 {
00334 UINT16 or;
00335
00336 INT_DISABLE();
00337 or = _overrun;
00338 _overrun = 0;
00339 INT_ENABLE();
00340
00341 return or;
00342 }
00343
00344
00345
00346 pfUINT8 xsnd8_getblknum( UINT16 nblk )
00347 {
00348 return (pfUINT8)(_buffptr + (_samplelen*_blklen*nblk));
00349 }
00350
00351
00352
00353 UINT16 xsnd8_getnblk( VOID )
00354 {
00355 return _nblk;
00356 }
00357
00358
00359
00360 pfUINT8 xsnd8_getblk( VOID )
00361 {
00362 UINT16 n;
00363
00364 if ((_qblk==_nblk)||(_qtail))
00365 return NULL;
00366
00367 INT_DISABLE();
00368 n = _dmablk+_qblk;
00369 INT_ENABLE();
00370
00371 return (pfUINT8)(_buffptr + ((n % _nblk)*_blklen*_samplelen));
00372 }
00373
00374
00375
00376 UINT16 xsnd8_addblk( VOID )
00377 {
00378 if ((_qblk==_nblk)||(_qtail))
00379 return 1;
00380
00381 INT_DISABLE();
00382 _qblk++;
00383 if (_status==AWAIT)
00384 xsnd8_start();
00385 else if (abs(_status)==WAIT1A) {
00386 _status = (_status<0)?-WAIT2:WAIT2;
00387 sb_IRQ_ack_dma8midi(_baseport);
00388 }
00389 INT_ENABLE();
00390
00391 return 0;
00392 }
00393
00394
00395
00396 UINT16 xsnd8_addlastblk( UINT32 len )
00397 {
00398 UINT16 i, n;
00399 pfVOID p;
00400 UINT8 u8;
00401 UINT16 u16;
00402
00403 if ((_qblk==_nblk)||(_qtail))
00404 return 1;
00405
00406 INT_DISABLE();
00407 _qtail = (len>0)?1:2;
00408 _taillen = (UINT16)(len-1);
00409 if (_status==AWAIT)
00410 xsnd8_start();
00411 else if (abs(_status)==WAIT1A) {
00412 sb_IRQ_ack_dma8midi(_baseport);
00413 if (len<=_blklen/2) {
00414 _status = (_status<0)?-WAIT5:WAIT5;
00415 if (_record) {
00416 len=_blklen/2;
00417 n = (UINT16)(_blklen-1);
00418 }
00419 else
00420 n = (UINT16)(_blklen/2-1);
00421 p = _buffptr + (((_dmablk+_qblk) % _nblk) * _blklen*_samplelen);
00422 if (_stereo) {
00423 if (_record)
00424 u16 = 0x8080;
00425 else if (len)
00426 u16 = ((pfUINT16)p)[(UINT16)(len-1)];
00427 else
00428 u16 = ((pfUINT16)(_buffptr+(((_dmablk+_qblk-1)%_nblk)*
00429 _blklen*_samplelen)))[(UINT16)(_blklen-1)];
00430 for (i=(UINT16)len; i<=n; i++)
00431 ((pfUINT16)p)[i]=u16;
00432 }
00433 else {
00434 if (_record)
00435 u8 = 0x80;
00436 else if (len)
00437 u8 = ((pfUINT8)p)[(UINT16)(len-1)];
00438 else
00439 u8 = ((pfUINT8)(_buffptr+(((_dmablk+_qblk-1)%_nblk)*
00440 _blklen*_samplelen)))[(UINT16)(_blklen-1)];
00441 for (i=(UINT16)len; i<=n; i++)
00442 ((pfUINT8)p)[i]=u8;
00443 }
00444 }
00445 else {
00446 _status = (_status<0)?-WAIT6:WAIT6;
00447 if ((!_record)&&(len<_blklen)) {
00448 n = (UINT16)(_blklen-1);
00449 p = _buffptr+(((_dmablk+_qblk) % _nblk)*_blklen*_samplelen);
00450 if (_stereo) {
00451 u16 = ((pfUINT16)p)[(UINT16)(len-1)];
00452 for (i=(UINT16)len; i<=n; i++)
00453 ((pfUINT16)p)[i]=u16;
00454 }
00455 else {
00456 u8 = ((pfUINT8)p)[(UINT16)(len-1)];
00457 for (i=(UINT16)len; i<=n; i++)
00458 ((pfUINT8)p)[i]=u8;
00459 }
00460 }
00461 }
00462 }
00463 INT_ENABLE();
00464
00465 return 0;
00466 }
00467
00468
00469
00470 BOOL xsnd8_stopped( VOID )
00471 {
00472 return (_status<0);
00473 }
00474
00475
00476
00477 BOOL xsnd8_blocked( VOID )
00478 {
00479 return (_status==BLOCK);
00480 }
00481
00482
00483
00484 UINT16 xsnd8_srate( UINT16 srate )
00485 {
00486 if (!_initialized)
00487 return 1;
00488
00489 _srate = srate;
00490 if (_record) {
00491 if (sb_DSP_in_rate(_baseport,srate))
00492 return 1;
00493 }
00494 else
00495 if (sb_DSP_out_rate(_baseport,srate))
00496 return 1;
00497
00498 return 0;
00499 }
00500
00501
00502
00503 DOUBLE xsnd8_getsrate( VOID )
00504 {
00505 return sb_DSP_tc2dsr(sb_DSP_sr2tc(_srate,(_stereo?2:1)), (_stereo?2:1));
00506 }
00507
00508
00509
00510 UINT16 xsnd8_initialize( VOID )
00511 {
00512 return sb_DSP_reset( blaster_env(BLASTER_BASEPORT,
00513 BLASTER_DEFAULT_BASEPORT, BLASTER_DECHEX_BASEPORT));
00514 }
00515
00516
00517
00518 UINT16 xsnd8_getqblk( VOID )
00519 {
00520 if (_status==BLOCK) return 0;
00521 return _qblk+(_qtail?1:0);
00522 }
00523
00524