ToneCore DSP Developer Kit Guide
- So you want to design your own effects?
- Signal Processing for Dummies
- Assembly Programming
- Program Flow
- Delay Pedal Example
- Debug Interfaces
- Using the Simulator
- Prototyping in Python
- Developing under Linux (or OS X)
- Code Library
"Give me a lever and I will move the contents of the accumulator to memory." -- Archimedes, 225 B.C.
If you bought the kit under the impression that C programming was possible you're probably a little mad right now. It is possible with a non-free compiler (the Tasking toolchain). But forget about that, we're going to do it all in assembly because we're real men and that's what real men program in when nobody gives them a compiler. We'll also end up learning a lot more about how the DSP works by coding for it in assembly.
The assembly language used is Motorola 56k assembly. The Freescale 563xx line is a spinoff of the Motorola 563xx line and uses the same tools. The good news is the 563xx processors are very simple and are easy to program for.
Most of the syntax can be summed up by this example:
my_loop ; some instructions to populate some registers move #>0.5,x0 move #>0.2,x1 mpy x0,x1,a ; x0*x1 -> a jmp my_loopThis shows a few things. Labels ("my_loop") are anything that starts in the first column. The assembler converts these to addresses, so you can jump/branch to them. Instructions must be one or more spaces/tabs in. Operands to the instructions are comma separated (no spaces!). Comments are anything following a semicolon. Easy enough, right?
The below table lists some of the instructions you'll be using most frequently. Freescale's DSP56300 family manual contains full documentation for all instructions.
|move||Move between registers or between a register and a memory location. Equivalent to store/load instructions on some other processors.|
move #>$0a0b0c,x0 ; x0 gets 0x0a0b0c move x0,a ; a gets x0
|jmp||Jumps to a particular place in memory. Typically used to jump to a label.|
|jsr||Jumps to a sub routine. Similar to jmp except you can use rts to get back.|
|cmp||Comparison. Use with conditional branches (beq, bne, blt, ble, bgt, bge, etc) to achieve program control.|
move x0,a cmp x1,a ; do comparison blt SomeLabel ; branch if a < x1
|add, sub||Addition and subtraction.|
; add x0 + x1 move x1,a add x0,a ; result in a ; subtract x0 - x1 move x1,a sub x0,a ; result in a ; increment x0 by 5 move x0,a add #5,a move a,x0
|mpy, div||Multiply and divide. Note that these are fixed-point operations and won't do exactly what you expect with plain integers.|
mpy x0, x1, a ; a gets x0*x1
One last thing about the DSP code. The DSP processor can execute certain things in parallel. I don't have a good handle on this yet. It appears that moves involving different data busses can be parallelized. You'll see instructions that have more than one set of operands in the EQ example code; these are parallel operations. This detail can be ignored for the most part until you are hurting for cycles.
Starting with the example code (the EQ example from Line6) is the best thing to do. Read it over and then read Getting Started for an explanation of the major sections. The even RX ISR (esai_rxeven_isr) is where the samples are received from the ADC and sent out to the DAC.
Delay is an easy effect to implement and it will famliarize you with the external memory interface and DMA engine. Below is a diagram of a simple delay effect. Input samples are saved into the circular buffer and summed with a previous sample from N samples in the past. Usually the past sample is attenuated. Both the attenuation and the delay length (N) are typically controlled by the user (knobs).
More complicated delay effects may have many delayed copies (N, 2N, 3N, etc) and may do some amount of processing on the delayed copies to emulate a particular analog delay effect.
TODO show how to modify the EQ example to be a delay pedal.