Back Contents Next
The Emu10k1 has a special patented tram engine used to implement Delay lines as well as table look-ups. The tram engine can use internal RAM (4K samples) or external host based ram (up to 1M samples). From the programmer's perspective tram is accessed via a pair of registers. Tram address registers are used to store an address into the tram (i.e. the address from which you wish to read or write). Tram data registers are used to write/read data to/from the tram.
As is shown in Fig. 1, the tram address registers contain a value which points to a delay-line/look-up location. The data is either written to or read from the tram data register pair. The pairing is straight forward, 0x200 is paired with 0x300, 0x201 is paired with 0x301, etc. There are actually two separate tram spaces. Internal tram is accessed via 0x200/0x300-0x27F/0x27F, external host based tram is accessed via 0x27F/0x37F-0x29F/0x39F. The tram engine updates the values from/in the tram data registers once per sample, thus the emu10k1 is physically limited to 0x7F internal accesses and 0x20 external accesses.
The Tram is 20 bit addressable, meaning only 20 bits of the 32bit tram address register actually represent an address. Bits 20-23 are an "opcode", they tell the tram address what to do (i.e. read or write). The opcodes are only read/writable by the host cpu, dsp programs cannot change a tram opcode, infact, dsp programs cannot even see the opcodes. The address can however be changed. The tram address as viewed from the host cpu are shown below. The two tram spaces do not overlap, so address 0x00000 in In Internal tram is different from 0x00000 in external tram. Table 1, TRAM Address register viewed from Host CPU
The DSP code sees the tram address register differently. The whole register except the MSB (sign bit) is used to represent the tram address. Tram engine, however, only uses the 20 bits from 11-30. The least significant bits are ignored but maintain (one can use these bits when calculating addresses, these bits can represent "fractional" delay value for your dsp programs).
Table 2, TRAM Address register viewed from Emu10k1 processor
The tram space is actually a circular address space. The addresses specified in the Tram Address Registers are added to a pointer known as the Delay Base Address Counter(DBAC), and is used to access the actual tram memory. Fig 2. shows the calculation of the actual tram address. At each cycle, the Address Counter is decremented by 1, and thus an address specified in the tram address register will circulate around the tram space. The circulating space allows the creation of delay-lines as the data will appear to moving at each cycle.
DBAC=0x34, addr 0x11, actual address=0x11+0x34=0x45
DBAC=0x33, The data writen at t=0 is still in the same address (0x45), but from the dsp program's perpective it appears at addr = 0x45-0x33 = 0x12 . Thus, the data appears to have moved forward to the next tram memory location.
In addition, the DBAC is available for dsp programs at register address 0x5B, this allows dsp programs to access tram in a non-circular fasion by "subtrating out" the pointer (more on that later).
One final point about the DBAC is that it always counts from 0xfffff to 0 (or 0x7fff800 to 0 counting down by 0x800, from the dsp programs point of view), and starts over once it reaches 0. The amount of External tram depends on how much was allocated by the driver. Not shown above in Fig 2 is a modulo operation with respect to the tram size. This occurs after the summation operation of the address and the DBAC. The table below shows the possible tram sizes as determined by the driver, note that they sizes are all powers of 2 for simplicity.
Table 3, Possible External Tram Sizes (determined by driver)
|Number of Samples||Modulo value (real)||Modulo Value (with 0x800 shift)||Ram allocated by driver |
Tram can be used to create delay lines. Delay-lines are a basic DSP element. Delay line have a length N+1 (counted from 0). Data written at the beginning of the delay line, propagates down the delay line at the rate of the sample period. Thus for the emu10k1 who internal sample rate is 48Khz, a unit delay is 1/48kHz=20.83usec. To create a 1msec delay, for example, we would need 1m*48k=48 samples.
A delay line can be subdivided into multiple delay-line by writing at multiple places. For example, if we wanted a 16 sample delay-line line and a 32 sample delay-line we would construct the following read/write addresses(from host including read/write ops):
|0x00200000||Write at 0|
|0x00100010||Read at 16|
|0x00200011||Write at 17|
|0x00100031||Read at 49|
The second write, at 17, over writes the previous data effectively starting a new tram line. The above subdividing can be used to divide the entire tram spaces into as many delay-line as is needed by the dsp programs. The address can be written by the host dsp program loader, or can be written to by the dsp program itself. The former allows the delay-line length to be varied (or "modulated").
Since dsp programs and their delay-lines can be relocated by the patch loader, the dsp programs can use the address contained in the write register as an offset when calculating the modulated read address:
[read address]=[write address]+[calculated delay length]
Another important thing to consider is the 11 bit shift of addresses. When calculating the number of desired samples of delay, one must multiply this value by 0x800 to account for the shift. The [write address] is already shifted, thus the final equations becomes:
[read address]=[write address]+[calculated number of delay samples]*0x800
Synchronizing Delay-lines (i.e. finding "0")
Tram can be used as a means of transfering data between the host CPU and the dsp programs (AC3 data, for example). Such a transfer typically would warrant the placement of data starting at know location in tram. Since the tram space appears to be circulating from the dsp program's view, we must have a way to find the beginning of the tram space.
To do so, we can use the Delay Base Address Regiser at 0x5B. Since tram address registers are summed with the DBAC, we must subtract it from from our address, before writing it to the Tram address register.
macints write.a,OFFSET,$5B,$50 ;;
Back Contents Next