Paměťový interface

     Na začátku jsem  již napsal, že EMU je  vybaveno 24-bitovým paměťovým
     interfacem. Adresace však  neprobíhá po bytech, ale po wordech, a tím
     je EMU (bohu dík) odsouzeno k používání výhradně 16-bitových samplů.
     Paměťový prostor EMU je rozdělen do  dvou částí. První část od adresy
     000000h-1FFFFFh je obsazena 1MB (0.5MB) MGM ROM. Je to divné, ale EMU
     pro ROM vyhradilo 4MB. Zbylých 28MB  od adresy 200000h je mapováno do
     DRAM,  která je  integrována mimo  čip. Prostor  0FFFFE0h-0FFFFFFh je
     rezervován a není použit (pochybuju, že vám bude někdy chybět).

     Pro čtení  nebo zápis dat do  pamětí musí být jeden  nebo více kanálů
     nastaveno na  DMA  přenos.  Pokud  si  alokujete  větší počet kanálů,
     rychlost přenosu je větší. Rychlost přenosu je odvozena od základního
     kmitočtu oscilátoru  a ten je  44.1kHz, takže pokud  si alokujete pro
     DMA  všech 32  kanálů (což, jak se  dále dočtete, není možné), tak je
     rychlost přenosu 32 x 44.1kHz = asi 1.34 MB/sec.

     Jak  už  jste  si  asi  všimli  v  tabulce  registrů,  EMU má 4 druhy
     paměťových přístupů: Left Read, Right Read, Left Write, Right Write.
     Pro čtení a  zápis jsou zde vždy dva kanály a u každého kanálu můžeme
     použít různou  adresu. Asi jste  si taky všimli,  že registry SMLD  a
     SMRD mají stejné číslo a datové  porty jsou umístěny vedle sebe. Toto
     se  přímo  nabízí  pro  přenos   stereofonních  samplů,  kde si např.
     naprogramujete Right DMA  na adresu Left + délka  samplu a pak budete
     kopírovat sampl po dwordech - oba kanály naráz.

     Nyní  si  popíšeme  způsob, jak  lze  uvést  oscilátor (kanál) do DMA
     režimu.

     Procedure SetChanelToDMA(o:oscilator,m:DMAmode);

           out(DCYSUSV[o],80h);
             {vypneme generátor obálek}

           out(VTFT[o],0);
           out(CVCF[o],0);
             {hlasitost a cutoff na nulu}

           out(PTRX[o],40000000h);
           out(CPF[o],40000000h);
             {pitch na nulu}

           out(PSST[o],0);
           out(CLS[o],0);
             {Loop Start a Loop End na nulu}

           out(CCCA[o],4000000+(m shl 24));
             {nastav a povol DMA režim}

     Procedure_End;

          Mód   CCCA        Režim
           0    4000000h    Left Read
           1    5000000h    Right Read
           2    6000000h    Left Write
           3    7000000h    Right Write

     Adresa  se  poté  zapíše  do  příslušného  SMA  registru.  Adresa  se
     automaticky inkrementuje.
     DMA  režim se vypne, pokud  do registru  CCCA příslušného  oscilátoru
     zapíšete nulu.

     Při zápisu se musí kontrolovat bit  "FULL" v SMAxW registru. Pokud je
     tento  bit nulový,  je možné  zapsat na  SMxD registr  další hodnotu,
     kterou chcete uložit do paměti.

     Při  čtení se  postupuje obdobně   jako u  zápisu, ale  testujeme bit
     "EMPTY"  v SMAxR  registru. Pokud  je bit  nulový, můžeme  číst další
     hodnotu.

     Při programování EMU a práci s pamětí jsou ovšem dva problémy. Prvním
     problémem je, že EMU neumí přehrávat jednoduché (single-shot) samply.
     Musíte si  tedy přizpůsobit  LOOP tak, aby  byla při  skončení samplu
     přehrávána krátká smyčka (obvykle 4 samply kvůli interpolaci).
     Druhý  problém je  to, že  přídavná pamět  je typu  DRAM a  tím pádem
     potřebuje  občerstvovat. EMU  ale  občerstvování  paměti neumí  a tak
     musíme  obětovat dva  oscilátory (30  a 31)  na občerstvování paměti.
     Kromě občerstvování  paměti umí tento režim  taky produkovat Reverb a
     Chorus  pro  FM  OPL3.  Tuto  rutinu  vám asi kompletně neokomentuju,
     protože sám nevím  jak pracuje. Je to opsané  z Grinusova AWE Control
     Packu a  jak se mi svěřil,  tak to zase opsal  z AWE Developer Packu,
     takže jak  to funguje, ví jenom u Creative a u  EMU Systems. Berte to
     jako černou skříňku. :)

     Procedure RefreshFMEff(r:reverb,c:chorus);

           out(DCYSUSV[30],80h);
           out(PSST[30],0FFFFFFE0h);
           out(CSL[30],0FFFFE8h+(c shl 24));
           out(PTRX[30],r shl 8);
           out(CPF[30],0);
           out(CCCA[30],0FFFFE3h);

           out(DCYSUSV[31],80h);
           out(PSST[31],0FFFFF0h);
           out(CSL[31],0FFFFE8h+(c shl 24));
           out(PTRX[31],(r shl 8)+0FFh);
           out(CPF[31],8000h);
           out(CCCA[31],0FFFFF3h);

           asm
                 cli
                 mov   dx,BASE+802h      {E22h}
                 mov   ax,3Eh
                 out   dx,ax
                 xchg  bx,dx
                 mov   dx,BASE           {620h}
                 xor   ax,ax
                 out   dx,ax
                 xchg  bx,dx
           L1:   in    ax,dx
                 test  ah,10h
                 jz    L1
           L2:   in    ax,dx
                 test  ah,10h
                 jnz   L2
                 mov   dx,bx
                 add   dx,2
                 mov   ax,4828h
                 out   dx,ax
                 mov   dx,BASE+802h      {E22h}
                 mov   ax,3Ch
                 out   dx,ax
                 mov   dx,bx
                 add   dh,4
                 xor   ax,ax
                 out   dx,ax
                 sti
           asm_end;

           out(VTFT[30],8000FFFFh);
           out(VTFT[31],8000FFFFh);

           Procedure_End;


            výheň