Tuesday, May 19, 2015

XMOS Parallel DAC, version 1

I adapted the Arduino version of the parallel DAC described in the last blog post to work with the XMOS StartKit. This has a faster processor, so we should be able to crank up the rate a bit more. The resistor ladder gives us a 9 bit DAC, so I used two 4 bits ports and a 1 bit port. There is a 32 bit port, and I may use that in the next step.

Again, some sample waveforms. First, a sine wave at 10kHz. Because of how I implemented it, using delay_microseconds, the fastest sine wave I could get with a non-zero delay was 32kHz. Removing the delay statement altogether got it to 153kHz.

Next, a triangle wave at 100kHz:

Square wave at 100kHz:
You can see it is starting to round off, presumably due to capacitance. At 300kHz, this is more pronounced:
Finally, I took out all the delays and output only the top 3 bits, to see how fast I could drive it. The waveform is pretty nasty...
... but it is at around 25MHz.

For the next step, I want to use the 32 bit port, but more especially to use the real power of the XMOS chip, but setting precise times for setting the values on the ports.

The code:

#include <math.h>
#include <xs1.h>

// Ports for top 4, middle 4 and lowest bits.
port top4 = XS1_PORT_4C;
port mid4 = XS1_PORT_4D;
port bot1 = XS1_PORT_4E;

int max_value = 511;
double freq = 300000; // Approximate

#define NSAMPLES 64
int samples[NSAMPLES];
#define PI 3.14156

void set(int value) {
    top4 <: ((value >> 5) & 0x0f);
    //mid4 <: ((value >> 1) & 0x0f);
    //bot1 <: (value & 0x01);
}

int main(void) {
#if 0
    // Sampled waveform
    for (int i = 0; i < NSAMPLES; ++i) {
        // Triangle
        // samples[i] = (max_value * i)/NSAMPLES;
        // Sine
        samples[i] = (short)(max_value * (1 + sin((float)i * 2 * PI / NSAMPLES))/2);
    }
    int delay_us = (int)((1000000.0/freq)/NSAMPLES);
#else
    // Square wave
    //int delay_us = (int)((1000000.0/freq)/2);
#endif

    while (1) {
#if 0
        // Sampled waveforms
        for (int i = 0; i < NSAMPLES; ++i) {
            set(samples[i]);
            delay_microseconds(delay_us);
        }
#else
        // Square wave
        //set(0);
        top4 <: 0;
        //delay_microseconds(delay_us);
        top4 <: 0xf;
        //set(511);
        //delay_microseconds(delay_us);
#endif
    }
    return 0;
}

No comments: