123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- //
- // Copyright(c) by Benny Sjostrand (benny@hostmobility.com)
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- //
- //
- // This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
- // to compile it you need a tool named SPASM 3.0 and DSP code owned by
- // Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
- // the "ospparser" tool will genereate the cwcdma.h file it's included from
- // the cs46xx_lib.c file.
- //
- //
- // The purpose of this code is very simple: make it possible to tranfser
- // the samples 'as they are' with no alteration from a PCMreader
- // SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
- // SRC (source rate converters) task always alters the samples in somehow,
- // however it's from 48khz -> 48khz.
- // The alterations are not audible, but AC3 wont work.
- //
- // ...
- // |
- // +---------------+
- // | AsynchFGTxSCB |
- // +---------------+
- // |
- // subListPtr
- // |
- // +--------------+
- // | DMAReader |
- // +--------------+
- // |
- // subListPtr
- // |
- // +-------------+
- // | PCMReader |
- // +-------------+
- // (DMA from host)
- //
- struct dmaSCB
- {
- long dma_reserved1[3];
- short dma_reserved2:dma_outBufPtr;
- short dma_unused1:dma_unused2;
- long dma_reserved3[4];
- short dma_subListPtr:dma_nextSCB;
- short dma_SPBptr:dma_entryPoint;
- long dma_strmRsConfig;
- long dma_strmBufPtr;
- long dma_reserved4;
- VolumeControl s2m_volume;
- };
- #export DMAReader
- void DMAReader()
- {
- execChild();
- r2 = r0->dma_subListPtr;
- r1 = r0->nextSCB;
-
- rsConfig01 = r2->strmRsConfig;
- // Load rsConfig for input buffer
- rsDMA01 = r2->basicReq.daw, , tb = Z(0 - rf);
- // Load rsDMA in case input buffer is a DMA buffer Test to see if there is any data to transfer
- if (tb) goto execSibling_2ind1 after {
- r5 = rf + (-1);
- r6 = r1->dma_entryPoint; // r6 = entry point of sibling task
- r1 = r1->dma_SPBptr, // r1 = pointer to sibling task's SPB
- , ind = r6; // Load entry point of sibling task
- }
- rsConfig23 = r0->dma_strmRsConfig;
- // Load rsConfig for output buffer (never a DMA buffer)
- r4 = r0->dma_outBufPtr;
- rsa0 = r2->strmBufPtr;
- // rsa0 = input buffer pointer
- for (i = r5; i >= 0; --i)
- after {
- rsa2 = r4;
- // rsa2 = output buffer pointer
- nop;
- nop;
- }
- //*****************************
- // TODO: cycles to this point *
- //*****************************
- {
- acc0 = (rsd0 = *rsa0++1);
- // get sample
- nop; // Those "nop"'s are really uggly, but there's
- nop; // something with DSP's pipelines which I don't
- nop; // understand, resulting this code to fail without
- // having those "nop"'s (Benny)
- rsa0?reqDMA = r2;
- // Trigger DMA transfer on input stream,
- // if needed to replenish input buffer
- nop;
- // Yet another magic "nop" to make stuff work
- ,,r98 = acc0 $+>> 0;
- // store sample in ALU
- nop;
- // latency on load register.
- // (this one is understandable)
- *rsa2++1 = r98;
- // store sample in output buffer
- nop; // The same story
- nop; // as above again ...
- nop;
- }
- // TODO: cycles per loop iteration
- r2->strmBufPtr = rsa0,, ;
- // Update the modified buffer pointers
- r4 = rsa2;
- // Load output pointer position into r4
- r2 = r0->nextSCB;
- // Sibling task
- goto execSibling_2ind1 // takes 6 cycles
- after {
- r98 = r2->thisSPB:entryPoint;
- // Load child routine entry and data address
- r1 = r9;
- // r9 is r2->thisSPB
- r0->dma_outBufPtr = r4,,
- // Store updated output buffer pointer
- ind = r8;
- // r8 is r2->entryPoint
- }
- }
|