Hackaday demo: Signal generator

Dependencies:   SDFileSystem mbed

output.cpp

Committer:
wd5gnr
Date:
2015-09-15
Revision:
1:c229c3ceb909
Parent:
0:8baa10bd07de

File content as of revision 1:c229c3ceb909:

#include "mbed.h"
#define _EXTERN_ extern
#include "main.h"
#include "output.h"


// Output "engines"

// Mbed timers are not reliable below a few dozen uS
// At one point I did this table but it is better to do a iinear regression
// for the whole range not just the ones that suffer from the timer jitters
// You would need to refigure the linear regression any time you change the loop but
// for the current setup (http://mycurvefit.com/ is handy for that)
#define M 23.79f
#define B -8.9878f

// If you want to set the M and B (see above) you can set CALIBRATE to 1
// and set M and B to 1.0 and 0. Then enter some different timebase
// values (t command) and measure the timing
// Then fit the curve using M and B
#define CALIBRATE  0


AnalogOut aout(DAC0_OUT);   // Analog output


// inline assembly for nop (plus function call overhead)
void nop(void)
{
    __ASM volatile("nop\n");
}


// Execution engines

static void exec0()  // timebase == 0.0, go as fast as possible
{
    while (1) {
        aout.write_u16(buffer[bp]);
        bp=(bp+1)&BUFSIZEMASK;
    }
}

void exec()  // All other time bases
{
    unsigned i, newbase;
    if (timebaseus==0) exec0();  // go as fast as possible -- never returns
#if CALIBRATE==1 
    float m=1.0f,b=0.0f;
    pc.printf("Using M=%f B=%f\r\n",m,b);
    newbase=(unsigned int)((m*timebaseus-b)+0.5f);
#else
    newbase=(unsigned int)((M*timebaseus-B)+0.5f);
#endif
    while (1) {
        aout.write_u16(buffer[bp]);
        bp=(bp+1)&BUFSIZEMASK;
        for (i=0; i<newbase; i++) {
            nop();  // could shave a little off maybe by moving inline here
        }
    }
}