Friday, May 22, 2015

XMOS Parallel DAC, version 2

Here is a revised version of the parallel DAC code for the XMOS StartKit. It uses the timer and timed ports. Originally I though I would need the more complex variant they give in the manual with a timing producer + buffer + timing consumer/signal generator, but it isn't needed for this simple case. It uses the 32 bit port on pins 7-12 and 17-19 (since these are brought out to one of the GPIO headers).



/*
 * ParaDAC2.xc
 *
 *  Created on: May 21, 2015
 *      Author: David
 *  Drawing on chapter 11 of the programming guide.
 *  Limit for square waves around 3MHz (with lots of signal degradation).
 *  Limit for others around 200kHz.
 */

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

// 32 bit port, using lines 7-12 and 17-19.
port p32 = XS1_PORT_32A;

unsigned max_value = 511;
double freq = 4000000; // Approximate

#define NSAMPLES 64
unsigned samples[NSAMPLES];
#define PI 3.14156
unsigned max_samples = NSAMPLES;

enum {
    TRIANGLE, SINE, SQUARE
} signal_type = SQUARE;

void set(port p, unsigned value) {
    unsigned v = ((value & 0x1c0) << 11) | ((value & 0x3f) << 7);
    p <: v;
}

[[combinable]]
void siggen(port p, int delay_ticks) {  // ticks are 100Mhz.
    timer tmr;
    unsigned t;
    unsigned val = 0;
    unsigned sample = 0;
    tmr :> t;
    while (1) {
        select {
            // This case will event when the timer moves past (t + delay_ticks ) i.e
            // delay_ticks after when we took the timestamp t
            case tmr when timerafter (t + delay_ticks ) :> void :
                    t += delay_ticks;
                    set(p, val);
                    val = samples[sample++];
                    if (sample >= max_samples) sample = 0;
                    break;
        }
    }
}

int main () {
    // Ticks are at 100MHz, freq is in hz.
    if (signal_type == TRIANGLE) {
        for (unsigned i = 0; i < NSAMPLES; ++i) {
            samples[i] = (max_value * i + 0.5)/NSAMPLES;
        }
    } else if (signal_type == SINE) {
        for (unsigned i = 0; i < NSAMPLES; ++i) {
            samples[i] = (unsigned)(max_value * (1 + sin((float)i * 2 * PI / NSAMPLES))/2);
        }
    } else {
        max_samples = 2;
        samples[0] = 0;
        samples[1] = max_value;
    }
    unsigned delay_ticks = 100000000 / freq / max_samples;

    siggen(p32, delay_ticks);
    return 0;
}

No comments: