/*
* Copyright(C) Paul und Scherer (mct.de/mct.net)
*
* This example demonstrates how to...
*
* ... use an ADC channel to monitor the DAC output.
*
* ... reduce signal noise using low pass filtering.
*/
#include
#include
#include
/*
* Low pass (numerical simulation of an RC circuit)
*
* The behaviour of an RC circuit can be described with the formula
*
* (new)out := (1-K)*out+K*in, with 0<= K <=1, initial out =0
*
* In other words, the output is composed of a part of the previous
* output and a part of the current input. For K =0 the output will
* never change, and for K =1 it follows the input immediately. The
* choice for K is a trade-off: signal stability vs. response time.
*
* The above formula is rewritten as: (new)out := out-K*out+K*in or
*
* out += K*(in-out)
*
* To avoid using floats, this is transformed to integer arithmetic
* by replacing K with 1/F and multiplying both sides with factor F
*
* fout += in-fout/F, where fout = F*out, F >=1
*
* Return out.
*/
#define F 100
static int
lp(int in)
{
static long fout; // initial fout (=F*out) =0
return (fout += in-fout/F)/F; // return out (=fout/F)
}
/*
* Connect the DAC output (=Aout =P0.25) to AD0.0 (=P0.27). The DAC
* output can be changed by entering values between 0 and 1023. The
* output is sampled by AD0.0, filtered through a low pass and then
* displayed. DAC and ADC values should not differ significantly.
*/
int
main(void)
{
Intern_ad0cr = 0x210f01; // enable AD0.0, BURST on
Intern_pinsel1 |= 0x480000; // DAC
// and AD0.0 pins
while (1) {
char line[5]; // input buffer
unsigned dac; // DAC data
long adc; // ADC data
while ((adc = Intern_ad0dr) >= 0) ; // wait for DONE
printf("DAC ->ADC: %d\n", lp((adc>>6)&0x3ff));
if (!kbhit()) continue; // new DAC data?
do {
fputs("\nNew DAC data (0.. 1023): ", stdout);
fgets(line, sizeof(line), stdin);
} while (sscanf(line, "%u", &dac) != 1 || dac > 1023);
putchar('\n');
Intern_dacr = (unsigned short)(dac<<6);
}
}