home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / msdos / sndbords / proaudio / pas_sdk1 / pas / subs / pcm / pcmioa.asm < prev    next >
Assembly Source File  |  1992-09-28  |  15KB  |  669 lines

  1. ;$Author:   DCODY  $
  2. ;$Date:   23 Sep 1992 10:57:04  $
  3. ;$Header:   X:/sccs/pcm/pcmioa.asv   1.4   23 Sep 1992 10:57:04   DCODY  $
  4. ;$Log:   X:/sccs/pcm/pcmioa.asv  $
  5. ;  
  6. ;     Rev 1.4   23 Sep 1992 10:57:04   DCODY
  7. ;  more work on playthisblock, continuethisblock...
  8. ;  
  9. ;     Rev 1.3   26 Aug 1992 10:58:26   DCODY
  10. ;  added Playthisblock and RecordthisBlock support routines
  11. ;  
  12. ;     Rev 1.2   12 Aug 1992 17:10:56   DCODY
  13. ;  major change to eliminate the foreground buffers and background
  14. ;  processing responsibilities.
  15. ;  
  16. ;     Rev 1.1   23 Jun 1992 17:11:34   DCODY
  17. ;  PAS2 update
  18. ;  
  19. ;     Rev 1.0   15 Jun 1992 09:44:36   BCRANE
  20. ;  Initial revision.
  21. ;$Logfile:   X:/sccs/pcm/pcmioa.asv  $
  22. ;$Modtimes$
  23. ;$Revision:   1.4  $
  24. ;$Workfile:   pcmioa.asm  $ 
  25.  
  26.  
  27.     page    64,131
  28.     Title    PCMIOA    --  Background Task for PCM I/O
  29.  
  30. ;   /*\
  31. ;---|*|
  32. ;---|*|------------====< PCMIOA.ASM >====------------
  33. ;---|*|
  34. ;---|*| Copyright (c) 1991, Media Vision, Inc. All rights reserved
  35. ;---|*|
  36. ;   \*/
  37.  
  38.         .xlist
  39.     include model.inc
  40.     include masm.inc
  41.         include common.inc
  42.     include binary.inc
  43.     .list
  44.  
  45. PCMCODEVERSION    equ    0003h        ; version 00.03
  46.  
  47. ;
  48. ;-----------------------================================-----------------------
  49. ;-----------------------====< Code/Data Generation >====-----------------------
  50. ;-----------------------================================-----------------------
  51. ;
  52.  
  53. BLOCKOUT    = 0        ; builds block output code only
  54. BLOCKIN     = 0        ; builds block input code only
  55. COMMDATA    = 0        ; builds both common code and data
  56.  
  57. ifdef  BUILDBO
  58.   BLOCKOUT    = 1
  59. endif
  60.  
  61. ifdef  BUILDBI
  62.   BLOCKIN    = 1
  63. endif
  64.  
  65. ifdef  BUILDCO
  66.   COMMDATA    = 1
  67. endif
  68.  
  69. ;
  70. ;---------------------------========================---------------------------
  71. ;---------------------------====< DATA SECTION >====---------------------------
  72. ;---------------------------========================---------------------------
  73. ;
  74.         .data
  75. ;
  76. ; Code Model Dependencies
  77. ;
  78. if @datasize
  79.   cptr    equ    <dword>         ; C pointer is FAR
  80. else
  81.   cptr    equ    <word>            ; C pointer is NEAR
  82. endif
  83.  
  84. NODIRECTION    equ    0
  85. DMAINPUT    equ    1
  86. DMAOUTPUT    equ    2
  87.  
  88. PCMFILEINPUT    equ    DMAINPUT
  89. PCMFILEOUTPUT    equ    DMAOUTPUT
  90. PCMBLOCKINPUT    equ    DMAINPUT+80h
  91. PCMBLOCKOUTPUT    equ    DMAOUTPUT+80h
  92.  
  93. ;
  94. ; Structure Definitions
  95. ;
  96. buffptr struc
  97.  
  98.  BPstatus       dw      0               ; 0=empty, 1=full
  99.  BPcount    dw    0        ; # of bytes in the buffer
  100.  BPsize     dw    0        ; total size of allocated buff
  101.  BPbuffer    dd    0        ; pointer to buffer data
  102.  
  103.   if @datasize
  104.    BPnextptr    dd    0        ; pointer to buffer data
  105.   else
  106.    BPnextptr    dw    0        ; pointer to buffer data
  107.   endif
  108.  
  109. buffptr ends
  110. ;
  111. ;--------------====< code generation dependent declarations >====------------
  112. ;
  113.  
  114. if    COMMDATA
  115. ;
  116. ; Local data declarations
  117. ;
  118.     public    CountdownBuffers
  119. CountdownBuffers    db    00    ; countdown value
  120.     public    NextDMAPtr
  121. NextDMAPtr        dd    00    ; our pointer to the DMA's buffer
  122.     public    DMAUnitSize
  123. DMAUnitSize        dw    00    ; size of DMA buffer divisions
  124.  
  125.     public    __callersroutine
  126.   if @codesize
  127. __callersroutine        dd      00
  128.   else
  129. __callersroutine    dw    00
  130.   endif
  131.  
  132. else
  133.     extrn    __callersroutine :word
  134.     extrn    __NextPtr     :dword ; pointer to circular buffer list
  135. ;
  136. ; Local data declarations
  137. ;
  138.     extrn    CountdownBuffers :byte    ; countdown value
  139.     extrn    NextDMAPtr     :dword ; our pointer to the DMA's buffer
  140.     extrn    DMAUnitSize     :word    ; size of DMA buffer divisions
  141.  
  142. endif
  143.     externPTR    HeadOfBuffers        ; pointer to buffer linked list
  144.     extrn    BufferDataCount  :word    ; # of full buffers (0=done)
  145.     extrn    DMARunning     :word    ; DMA status (0=off,1=running)
  146.     extrn    StartOfDMABuffer :dword ; always a far * to start of DMA buffer
  147.     extrn __pcmdatasize     :byte    ; default to 8 bit pcm
  148.     extrn    MaxBuffCount     :word    ; count of DMA blocks
  149.     extrn    ProcessedBlockCount:word; # of full buffers (0=done)
  150.     extrn    __synccallback     :dword ; callback to application at int
  151.  
  152. ;
  153. ;---------------------------========================---------------------------
  154. ;---------------------------====< CODE SECTION >====---------------------------
  155. ;---------------------------========================---------------------------
  156. ;
  157.         .code
  158.  
  159.     externADDR    InitPCM         ; initialize the PCM low level code
  160.     externADDR    StopPCM         ; Kill the PCM hardware
  161.     externADDR    PCMPlay         ; start the PCM output
  162.     externADDR    PCMRecord        ; start the PCM input
  163.     externADDR    UserFunc        ; sets up the call-back routine
  164.  
  165. if (BLOCKOUT or BLOCKIN)
  166.     externADDR    _resetdmaptrs        ; reset the criticals
  167. endif
  168.  
  169. if COMMDATA
  170. ;
  171. ;   /*\
  172. ;---|*|
  173. ;---|*|------------====< BackgroundInit( int, int ) >====------------
  174. ;---|*|
  175. ;---|*| Initialize our internal variables, etc...
  176. ;---|*|
  177. ;---|*| Entry Conditions:
  178. ;---|*|     wParm1 - Size of DMA buffer
  179. ;---|*|     wParm2 - # of DMA buffer divisions
  180. ;---|*|
  181. ;---|*| Exit Conditions:
  182. ;---|*|     No return value
  183. ;---|*|
  184. ;---|*| Functionality:
  185. ;---|*|
  186. ;---|*|     Clear interrupt mechanisms.
  187. ;---|*|     Disable DMA channel.
  188. ;---|*|     Set DMARunning to 0;
  189. ;---|*|
  190. ;   \*/
  191.  
  192.         public  BackgroundInit
  193. BackgroundInit    proc
  194.     push    bp
  195.     mov    bp,sp
  196.     push    es
  197. ;
  198. ; get the # of buffers in the linked list
  199. ;
  200.     mov    ax,wParm1
  201.     mov    [DMAUnitSize],ax    ; max size of each DMA division
  202. ;
  203. ; flush any prior low-level setup
  204. ;
  205.     call    InitPCM
  206.     mov    DMARunning,0        ; signal it dead
  207. ;
  208. ; all done, return home
  209. ;
  210.     pop    es
  211.     pop    bp
  212.     ret
  213.  
  214. BackgroundInit    endp
  215. endif   ; COMMDATA
  216.  
  217. if BLOCKOUT
  218. ;   /*\
  219. ;---|*|
  220. ;---|*|--------------====< FlushBuffer >====-----------------
  221. ;---|*|
  222. ;---|*| Flush the buffer by filling it with silence (value of 0x80)
  223. ;---|*|
  224. ;---|*| Entry Conditions:
  225. ;---|*|       dParm1 is the far pointer to the block
  226. ;---|*|       wParm2 is an unsigned integer which is the block length
  227. ;---|*|
  228. ;---|*| Exit Conditions:
  229. ;---|*|       DX:AX hold the ending pointer
  230. ;---|*|
  231. ;---|*| Prototype:
  232. ;---|*|
  233. ;---|*| char far * FlushBuffer (char far *, int)
  234. ;---|*|
  235. ;---|*|
  236. ;   \*/
  237.  
  238.         public  FlushBuffer
  239. FlushBuffer    proc
  240.     push    bp
  241.     mov    bp,sp
  242.  
  243.     push    es
  244.     push    di
  245.  
  246.     pushf
  247.     cld
  248.  
  249.     les    di,dParm1        ; grab 2 words off the stack
  250.     mov    cx,wParm3        ; wParm3 is used to skip the 2nd word
  251.  
  252.     cmp    [__pcmdatasize],9    ; 8 bit sets the carry
  253.     sbb    al,al            ; al = ff if 8 bit PCM
  254.     and    al,80h            ; al = 80 if 8 bit, 00 if 16 bit
  255.  
  256.     jcxz    @F
  257.     rep    stosb
  258.     @@:
  259.  
  260.     mov    dx,es            ; return the ending ptr
  261.     mov    ax,di
  262.  
  263.         popf
  264.  
  265.     pop    di
  266.     pop    es
  267.     pop    bp
  268.     ret
  269.  
  270. FlushBuffer    endp
  271. endif    ; BLOCKOUT
  272.  
  273.  
  274. if BLOCKIN
  275. ;   /*\
  276. ;---|*|
  277. ;---|*|------------====< StartTheDMAInput() >====------------
  278. ;---|*|
  279. ;---|*| Calculate the H/W timer value (internal routine)
  280. ;---|*|
  281. ;---|*| Entry Conditions:
  282. ;---|*|       pointer to a routine
  283. ;---|*|
  284. ;---|*| Exit Conditions:
  285. ;---|*|       AX =  0 indicates DMA running
  286. ;---|*|       AX = -1 indicates a failure
  287. ;---|*|
  288. ;---|*| Functionality:
  289. ;---|*|
  290. ;---|*|     Reset input pointer to the DMA buffer.
  291. ;---|*|     Load next buffer of data into the DMA buffer.
  292. ;---|*|     Enable DMA & interrupts.
  293. ;---|*|     Set DMARunning to 1;
  294. ;---|*|
  295. ;   \*/
  296.  
  297.     public StartTheDMAInput
  298. StartTheDMAInput        proc
  299.     push    bp
  300.     mov    bp,sp
  301.  
  302.         push    es
  303. ;
  304. ; Reset the DMA's internal buffer pointer & counter
  305. ;
  306.     call    _resetdmaptrs        ; reset the criticals
  307. ;
  308. ; Validate some critical data
  309. ;
  310.     mov    ax,-1            ; setup for bad return
  311.  
  312.     cmp    DMAUnitSize,0        ; we must have a valid size of units
  313.     jz    stdmaout_bad
  314.  
  315.     les    bx,[NextDMAPtr]     ; we must have a valid DMA buffer
  316.     mov    cx,es
  317.     or    bx,cx
  318.         jz      stdmaout_bad
  319. ;
  320. ; setup the callers callback
  321. ;
  322.       if @codesize
  323.     mov    ax,wParm1+0
  324.     mov    dx,wParm1+2
  325.     mov    wptr [__callersroutine+0],ax
  326.     mov    wptr [__callersroutine+2],dx
  327.       else
  328.         mov     ax,wParm1+0
  329.     mov    [__callersroutine],ax
  330.       endif
  331. ;
  332. ; setup our call-back routine
  333. ;
  334.     lea    ax,InputBackgroundTask
  335.     push    cs
  336.     push    ax
  337.     call    UserFunc
  338.     add    sp,4
  339. ;
  340. ; The DMA is loaded, let'er rip!!!
  341. ;
  342.     call    PCMRecord
  343.     mov    DMARunning,1
  344.  
  345.     sub    ax,ax
  346. ;
  347. stdmaout_bad:
  348.     pop    es
  349.     pop    bp
  350.     ret
  351.  
  352. StartTheDMAInput    endp
  353. endif    ; BLOCKIN
  354.  
  355.  
  356. if BLOCKOUT
  357. ;   /*\
  358. ;---|*|
  359. ;---|*|------------====< StartTheDMAOutput() >====------------
  360. ;---|*|
  361. ;---|*| Calculate the H/W timer value (internal routine)
  362. ;---|*|
  363. ;---|*| Entry Conditions:
  364. ;---|*|       None
  365. ;---|*|
  366. ;---|*| Exit Conditions:
  367. ;---|*|       AX =  0 indicates DMA running
  368. ;---|*|       AX = -1 indicates a failure
  369. ;---|*|
  370. ;---|*| Functionality:
  371. ;---|*|
  372. ;---|*|     Reset input pointer to the DMA buffer.
  373. ;---|*|     Load next buffer of data into the DMA buffer.
  374. ;---|*|     Enable DMA & interrupts.
  375. ;---|*|     Set DMARunning to 1;
  376. ;---|*|
  377. ;   \*/
  378.  
  379.     public    StartTheDMAOutput
  380. StartTheDMAOutput       proc
  381.         push    bp
  382.         mov     bp,sp
  383.     push    es
  384. ;
  385. ; Reset the DMA's internal buffer pointer & counter
  386. ;
  387.         call    _resetdmaptrs           ; reset the criticals
  388. ;
  389. ; Validate some critical data
  390. ;
  391.     mov    ax,-1            ; setup for bad return
  392.  
  393.     cmp    DMAUnitSize,0        ; we must have a valid size of units
  394.     jz    stdmaout_bad
  395.  
  396.     les    bx,[NextDMAPtr]     ; we must have a valid DMA buffer
  397.     mov    cx,es
  398.     or    bx,cx
  399.         jz      stdmaout_bad
  400. ;
  401. ; setup the callers callback
  402. ;
  403.       if @codesize
  404.     mov    ax,wParm1+0
  405.     mov    dx,wParm1+2
  406.     mov    wptr [__callersroutine+0],ax
  407.     mov    wptr [__callersroutine+2],dx
  408.       else
  409.         mov     ax,wParm1+0
  410.     mov    [__callersroutine],ax
  411.       endif
  412. ;
  413. ; setup our call-back routine
  414. ;
  415.     lea    ax,OutputBackgroundTask
  416.     push    cs
  417.     push    ax
  418.     call    UserFunc
  419.     add    sp,4
  420. ;
  421. ; The DMA is loaded, let'er rip!!!
  422. ;
  423.     call    PCMPlay
  424.     mov    DMARunning,1
  425.  
  426.     sub    ax,ax
  427. ;
  428. stdmaout_bad:
  429.     pop    es
  430.         pop     bp
  431.     ret
  432.  
  433. StartTheDMAOutput    endp
  434. endif ;; BLOCKOUT
  435.  
  436. ;
  437. ;--------------------------=============================-----------------------
  438. ;--------------------------====< Internal Routines >====-----------------------
  439. ;--------------------------=============================-----------------------
  440. ;
  441.  
  442. if BLOCKIN
  443. ;   /*\
  444. ;---|*|
  445. ;---|*|------------====< InputBackgroundTask() >====------------
  446. ;---|*|
  447. ;---|*| This is the interrupt code for processing DMA-buffer-has-data interrupts
  448. ;---|*|
  449. ;---|*| Entry Conditions:
  450. ;---|*|     None
  451. ;---|*|
  452. ;---|*| Exit Conditions:
  453. ;---|*|     None
  454. ;---|*|
  455. ;---|*| Interrupt handling:
  456. ;---|*|
  457. ;---|*|     if Next Buffer has data,
  458. ;---|*|     Kill-the-DMA;
  459. ;---|*|     set DMARunning to 0;
  460. ;---|*|     exit interrupt.
  461. ;---|*|     else
  462. ;---|*|        Load DMA into Next buffer.
  463. ;---|*|
  464. ;---|*|     Increment BufferDataCount.
  465. ;---|*|     Increment ProcessBlockCount.
  466. ;---|*|
  467. ;   \*/
  468.  
  469. InputBackgroundTask     proc    far
  470.     push    ax            ; save the entire state
  471.     push    bx
  472.     push    cx
  473.     push    dx
  474.     push    si
  475.     push    di
  476.     push    ds
  477.     push    es
  478. ;
  479. ; initialize the segment registers to point to our local static segment
  480. ;
  481.     mov    ax,@data        ; load our data segment
  482.     mov    ds,ax            ; DS too in case of failure
  483. ;
  484. ; Save the next DMA pointer, increment our internal buffer-loaded count
  485. ;
  486.         inc     ProcessedBlockCount     ; total block count the DMA has seen
  487.         inc     BufferDataCount         ; tell the world, we have new data
  488.     mov    ax,BufferDataCount
  489.     cmp    ax,MaxBuffCount
  490.     jb    inbkgrtsk_exit
  491. ;
  492. ; Yuck! We just ran out of buffer space, we must kill the DMA
  493. ;
  494.         call    StopPCM                 ; kill the interrupts...
  495.     mov    DMARunning,0
  496. ;
  497. inbkgrtsk_exit:
  498.   if @codesize
  499.     cmp    wptr [__callersroutine+2],0  ; if there is no vector, just exit
  500.     jz    @F
  501.     call    dptr [__callersroutine]      ; call the user routine
  502.       @@:
  503.   else
  504.     cmp    wptr [__callersroutine],0    ; if there is no vector, just exit
  505.     jz    @F
  506.     call    wptr [__callersroutine]      ; call the user routine
  507.       @@:
  508.   endif
  509. ;
  510. ; Call the application level it it wants a slice of time...
  511. ;
  512.         cmp     wptr [__synccallback+2],0    ; if no App. vector, just exit
  513.     jz    @F
  514.     call    dptr [__synccallback]         ; if no App. vector, just exit
  515.     @@:
  516. ;
  517. ; finally, all done.
  518. ;
  519.         pop     es
  520.     pop    ds
  521.     pop    di
  522.     pop    si
  523.     pop    dx
  524.     pop    cx
  525.     pop    bx
  526.     pop    ax
  527.     retf
  528.  
  529. InputBackgroundTask    endp
  530. endif    ; BLOCKIN
  531.  
  532.  
  533. if BLOCKOUT
  534. ;   /*\
  535. ;---|*|
  536. ;---|*|------------====< OutputBackgroundTask() >====------------
  537. ;---|*|
  538. ;---|*| This is the interrupt code for processing DMA buffer
  539. ;---|*| empty interrupts for the file output routines.
  540. ;---|*|
  541. ;---|*| Entry Conditions:
  542. ;---|*|     None
  543. ;---|*|
  544. ;---|*| Exit Conditions:
  545. ;---|*|     None
  546. ;---|*|
  547. ;---|*| Interrupt handling:
  548. ;---|*|
  549. ;---|*|     If BufferDataCount       is zero,
  550. ;---|*|     Kill-the-DMA;
  551. ;---|*|     set DMARunning to 0;
  552. ;---|*|
  553. ;---|*|     Attempt to load as many blocks as possible into the DMA buffer.
  554. ;---|*|
  555. ;---|*|     If data is loaded and DMARunning = 0,
  556. ;---|*|     restart the DMA;
  557. ;---|*|     set DMARunning to -1;
  558. ;---|*|
  559. ;---|*|     Exit interrupt.
  560. ;---|*|
  561. ;   \*/
  562.  
  563. OutputBackgroundTask    proc    far
  564.     push    ax            ; save the entire state
  565.     push    bx
  566.     push    cx
  567.     push    dx
  568.     push    si
  569.     push    di
  570.     push    ds
  571.     push    es
  572. ;
  573. ; initialize the data segment to point to our local static segment
  574. ;
  575.         mov     ax,@data                ; load our data segment
  576.     mov    ds,ax
  577. ;
  578. ; We just finished a block. If done (0), stop the DMA, else go load another
  579. ;
  580.     inc    ProcessedBlockCount    ; total block count the DMA has seen
  581.         sub     BufferDataCount,1       ; decrement the internal buffered data
  582.     adc    BufferDataCount,0    ; count down to zero
  583.     jnz    bkgrtsk_05        ; more data, go load it...
  584. ;
  585. ; Yuck! We just ran out of data, we must silence the DMA
  586. ;
  587.         call    StopPCM                 ; kill the interrupts...
  588.     mov    DMARunning,0
  589. ;
  590. bkgrtsk_05:
  591.   if @codesize
  592.     cmp    wptr [__callersroutine+2],0  ; if there is no vector, just exit
  593.     jz    @F
  594.     call    dptr [__callersroutine]      ; call the user routine
  595.       @@:
  596.   else
  597.     cmp    wptr [__callersroutine],0    ; if there is no vector, just exit
  598.     jz    @F
  599.         call    wptr [__callersroutine]      ; call the user routine
  600.       @@:
  601.   endif
  602. ;
  603. ; Call the application level it it wants a slice of time...
  604. ;
  605.         cmp     wptr [__synccallback+2],0    ; if no App. vector, just exit
  606.     jz    @F
  607.     call    dptr [__synccallback]         ; if no App. vector, just exit
  608.     @@:
  609. ;
  610. ; finally, all done.
  611. ;
  612.         pop     es
  613.     pop    ds
  614.     pop    di
  615.     pop    si
  616.     pop    dx
  617.     pop    cx
  618.     pop    bx
  619.     pop    ax
  620.     retf
  621.  
  622. OutputBackgroundTask    endp
  623. endif    ; BLOCKOUT
  624.  
  625. if COMMDATA
  626. ;
  627. ;   /*\
  628. ;---|*|
  629. ;---|*|------------====< _resetdmaptrs >====----------------
  630. ;---|*|
  631. ;---|*| Reset the DMA starting point
  632. ;---|*|
  633. ;---|*| Entry Conditions:
  634. ;---|*|     DS points to the default data segment
  635. ;---|*|
  636. ;---|*| Exit Conditions:
  637. ;---|*|     None
  638. ;---|*|
  639. ;   \*/
  640.  
  641. _resetdmaptrs    proc
  642.     push    es
  643. ;
  644. ; load the number of buffer divisions. this tells us when to wrap the DMA buff
  645. ;
  646.     mov    al,byte ptr [MaxBuffCount]
  647.     mov    [CountdownBuffers],al
  648. ;
  649. ; reset the DMA buffer offset
  650. ;
  651.     les    ax,[StartOfDMABuffer]
  652.     mov    wptr [NextDMAPtr+0],ax
  653.     mov    wptr [NextDMAPtr+2],es
  654.  
  655.         pop     es
  656.     ret
  657.  
  658. _resetdmaptrs   endp
  659.  
  660. endif    ; COMMDATA
  661.  
  662. ;   /*\
  663. ;---|*| end of PCMIOA.ASM
  664. ;   \*/
  665.  
  666.         end
  667.  
  668.  
  669.