annotate projects/cape_test/render.cpp @ 189:7144c5594d16

Added loopback digital/analog test. This (randomly) fails for the first loopback sample received when -p2. Maybe some stale memory somewhere?
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 26 Jan 2016 00:02:15 +0000
parents 3c3a1357657d
children 8d80eda512cd
rev   line source
andrewm@55 1 /*
andrewm@55 2 * render.cpp
andrewm@55 3 *
andrewm@55 4 * Created on: Oct 24, 2014
andrewm@55 5 * Author: parallels
andrewm@55 6 */
andrewm@55 7
andrewm@55 8
andrewm@56 9 #include <BeagleRT.h>
andrewm@55 10 #include <cmath>
andrewm@55 11
andrewm@55 12 #define ANALOG_LOW (2048.0 / 65536.0)
andrewm@55 13 #define ANALOG_HIGH (50000.0 / 65536.0)
andrewm@55 14
andrewm@55 15 const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7};
andrewm@55 16
andrewm@55 17 uint64_t gLastErrorFrame = 0;
andrewm@55 18 uint32_t gEnvelopeSampleCount = 0;
andrewm@55 19 float gEnvelopeValue = 0.5;
andrewm@55 20 float gEnvelopeDecayRate = 0.9995;
andrewm@55 21
andrewm@56 22 // setup() is called once before the audio rendering starts.
andrewm@55 23 // Use it to perform any initialisation and allocation which is dependent
andrewm@55 24 // on the period size or sample rate.
andrewm@55 25 //
andrewm@55 26 // userData holds an opaque pointer to a data structure that was passed
andrewm@55 27 // in from the call to initAudio().
andrewm@55 28 //
andrewm@55 29 // Return true on success; returning false halts the program.
andrewm@55 30
andrewm@56 31 bool setup(BeagleRTContext *context, void *userData)
andrewm@55 32 {
andrewm@55 33 return true;
andrewm@55 34 }
andrewm@55 35
andrewm@55 36 // render() is called regularly at the highest priority by the audio engine.
andrewm@55 37 // Input and output are given from the audio hardware and the other
andrewm@55 38 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
andrewm@55 39 // will be 0.
andrewm@55 40
andrewm@55 41 void render(BeagleRTContext *context, void *userData)
andrewm@55 42 {
andrewm@55 43 static float phase = 0.0;
andrewm@55 44 static int sampleCounter = 0;
andrewm@55 45 static int invertChannel = 0;
andrewm@55 46 float frequency = 0;
andrewm@55 47
andrewm@55 48 // Play a sine wave on the audio output
andrewm@55 49 for(unsigned int n = 0; n < context->audioFrames; n++) {
andrewm@55 50 context->audioOut[2*n] = context->audioOut[2*n + 1] = gEnvelopeValue * sinf(phase);
andrewm@55 51
andrewm@55 52 // If one second has gone by with no error, play one sound, else
andrewm@55 53 // play another
andrewm@55 54 if(context->audioSampleCount + n - gLastErrorFrame > 44100) {
andrewm@55 55 gEnvelopeValue *= gEnvelopeDecayRate;
andrewm@55 56 gEnvelopeSampleCount++;
andrewm@55 57 if(gEnvelopeSampleCount > 22050) {
andrewm@55 58 gEnvelopeValue = 0.5;
andrewm@55 59 gEnvelopeSampleCount = 0;
andrewm@55 60 }
andrewm@55 61 frequency = 880.0;
andrewm@55 62 }
andrewm@55 63 else {
andrewm@55 64 gEnvelopeValue = 0.5;
andrewm@55 65 frequency = 220.0;
andrewm@55 66 }
andrewm@55 67
andrewm@55 68 phase += 2.0 * M_PI * frequency / 44100.0;
andrewm@55 69 if(phase >= 2.0 * M_PI)
andrewm@55 70 phase -= 2.0 * M_PI;
andrewm@55 71 }
andrewm@55 72
andrewm@55 73 for(unsigned int n = 0; n < context->analogFrames; n++) {
andrewm@55 74 // Change outputs every 512 samples
andrewm@55 75 if(sampleCounter < 512) {
andrewm@55 76 for(int k = 0; k < 8; k++) {
andrewm@55 77 if(k == invertChannel)
andrewm@55 78 context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH;
andrewm@55 79 else
andrewm@55 80 context->analogOut[n*8 + gDACPinOrder[k]] = 0;
andrewm@55 81 }
andrewm@55 82 }
andrewm@55 83 else {
andrewm@55 84 for(int k = 0; k < 8; k++) {
andrewm@55 85 if(k == invertChannel)
andrewm@55 86 context->analogOut[n*8 + gDACPinOrder[k]] = 0;
andrewm@55 87 else
andrewm@55 88 context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH;
andrewm@55 89 }
andrewm@55 90 }
andrewm@55 91
andrewm@55 92 // Read after 256 samples: input should be low
andrewm@55 93 if(sampleCounter == 256) {
andrewm@55 94 for(int k = 0; k < 8; k++) {
andrewm@55 95 if(k == invertChannel) {
andrewm@55 96 if(context->analogIn[n*8 + k] < ANALOG_HIGH) {
andrewm@55 97 rt_printf("FAIL [output %d, input %d] -- output HIGH input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
andrewm@55 98 gLastErrorFrame = context->audioSampleCount + n;
andrewm@55 99 }
andrewm@55 100 }
andrewm@55 101 else {
andrewm@55 102 if(context->analogIn[n*8 + k] > ANALOG_LOW) {
andrewm@55 103 rt_printf("FAIL [output %d, input %d] -- output LOW --> input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
andrewm@55 104 gLastErrorFrame = context->audioSampleCount + n;
andrewm@55 105 }
andrewm@55 106 }
andrewm@55 107 }
andrewm@55 108 }
andrewm@55 109 else if(sampleCounter == 768) {
andrewm@55 110 for(int k = 0; k < 8; k++) {
andrewm@55 111 if(k == invertChannel) {
andrewm@55 112 if(context->analogIn[n*8 + k] > ANALOG_LOW) {
andrewm@55 113 rt_printf("FAIL [output %d, input %d] -- output LOW input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
andrewm@55 114 gLastErrorFrame = context->audioSampleCount + n;
andrewm@55 115 }
andrewm@55 116 }
andrewm@55 117 else {
andrewm@55 118 if(context->analogIn[n*8 + k] < ANALOG_HIGH) {
andrewm@55 119 rt_printf("FAIL [output %d, input %d] -- output HIGH input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
andrewm@55 120 gLastErrorFrame = context->audioSampleCount + n;
andrewm@55 121 }
andrewm@55 122 }
andrewm@55 123 }
andrewm@55 124 }
andrewm@55 125
andrewm@55 126 if(++sampleCounter >= 1024) {
andrewm@55 127 sampleCounter = 0;
andrewm@55 128 invertChannel++;
andrewm@55 129 if(invertChannel >= 8)
andrewm@55 130 invertChannel = 0;
andrewm@55 131 }
andrewm@55 132 }
andrewm@55 133 }
andrewm@55 134
andrewm@56 135 // cleanup() is called once at the end, after the audio has stopped.
andrewm@56 136 // Release any resources that were allocated in setup().
andrewm@55 137
andrewm@56 138 void cleanup(BeagleRTContext *context, void *userData)
andrewm@55 139 {
andrewm@55 140
andrewm@55 141 }