giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: #include giuliomoro@189: // setup() is called once before the audio rendering starts. giuliomoro@189: // Use it to perform any initialisation and allocation which is dependent giuliomoro@189: // on the period size or sample rate. giuliomoro@189: // giuliomoro@189: // userData holds an opaque pointer to a data structure that was passed giuliomoro@189: // in from the call to initAudio(). giuliomoro@189: // giuliomoro@189: // Return true on success; returning false halts the program. giuliomoro@189: giuliomoro@189: giuliomoro@189: // digital inputs can be changed at will (as they are all being processed at the same time) giuliomoro@189: // analog channels must be as per below giuliomoro@189: int gAnalogOutCh = 1; giuliomoro@189: int gDigitalOutCh = 2; giuliomoro@189: int gDigitalInACh = 0; giuliomoro@189: int gDigitalInDCh = 3; giuliomoro@189: int gAnalogOutLoopDelay; giuliomoro@189: int gDigitalOutLoopDelay; giuliomoro@189: bool setup(BeagleRTContext *context, void *userData) giuliomoro@189: { giuliomoro@189: rt_printf("For this test you need the following connections:\n" giuliomoro@189: "analog%d out->digital%d in, analog%d out->analog%d in, " giuliomoro@189: "digital%d out -> digital%d in, digital%d out-> analog%d in\n", giuliomoro@189: gAnalogOutCh, gDigitalInACh, gAnalogOutCh, 0, gDigitalOutCh, gDigitalInDCh, gDigitalOutCh, 0); giuliomoro@189: rt_printf("Running test with %d analog channels and a buffer size of %d\n", giuliomoro@189: context->analogChannels, context->audioFrames); giuliomoro@189: giuliomoro@189: for(unsigned int n = 0; n < context->digitalFrames; n++){ giuliomoro@189: pinModeFrame(context, n, gDigitalInACh, INPUT); giuliomoro@189: pinModeFrame(context, n, gDigitalInDCh, INPUT); giuliomoro@189: pinModeFrame(context, n, gDigitalOutCh, OUTPUT); giuliomoro@189: } giuliomoro@189: switch (context->analogChannels){ giuliomoro@189: case 2: giuliomoro@189: gAnalogOutLoopDelay = context->audioFrames*2 + 3; giuliomoro@189: gDigitalOutLoopDelay = context->audioFrames*2 + 2; giuliomoro@189: break; giuliomoro@189: case 4: giuliomoro@189: gAnalogOutLoopDelay = context->audioFrames*2 + 3; giuliomoro@189: gDigitalOutLoopDelay = context->audioFrames*2 + 2; giuliomoro@189: break; giuliomoro@189: case 8: giuliomoro@189: gAnalogOutLoopDelay = context->audioFrames + 3; giuliomoro@189: gDigitalOutLoopDelay = context->audioFrames + 1; giuliomoro@189: break; giuliomoro@189: default: giuliomoro@189: exit(2); giuliomoro@189: } giuliomoro@189: giuliomoro@189: return true; giuliomoro@189: } giuliomoro@189: giuliomoro@189: // render() is called regularly at the highest priority by the audio engine. giuliomoro@189: // Input and output are given from the audio hardware and the other giuliomoro@189: // ADCs and DACs (if available). If only audio is available, numAnalogFrames giuliomoro@189: // will be 0. giuliomoro@189: giuliomoro@189: const int patternLength = 31; giuliomoro@189: static int anaErrorCount = 0; giuliomoro@189: static int digErrorCount = 0; giuliomoro@189: void render(BeagleRTContext *context, void *userData) giuliomoro@189: { giuliomoro@189: static bool writePattern[patternLength] = { giuliomoro@189: 0,1,0,1,0,0,1,1, giuliomoro@189: 0,0,0,1,1,1,0,0, giuliomoro@189: 1,1,1,1,0,0,0,0, giuliomoro@189: 1,1,1,1,1,0,0}; giuliomoro@189: // for(int n = 0; n < patternLength; n++){ giuliomoro@189: // writePattern[n]=1; giuliomoro@189: // } giuliomoro@189: static int inPointer = 0; giuliomoro@189: static int outPointer = 0; giuliomoro@189: static int digitalOutPointer = 0; giuliomoro@189: static int digitalInPointer = 0; giuliomoro@189: static int analogOut = 1; giuliomoro@189: /** Checking offset between analog and digital giuliomoro@189: * how it should be : giuliomoro@189: * The PRU loop does the following (the loop runs at 88.2kHz): giuliomoro@189: * - Read/write audio sample (once for the left channel, once for the right channel) giuliomoro@189: * - Write DAC 0 or 0/2 or 0/2/4/6 giuliomoro@189: * - Read ADC 0 or 0/2 or 0/2/4/6, 2 samples (@176.4) older than NOW giuliomoro@189: * - /During/ the line above, every two loops we also Read/Write GPIO, giuliomoro@189: * therefore reading on ADC 0/2/4/6 a value that is being output from GPIO will lead to undefined results giuliomoro@189: * - Write DAC 1 or 1/3 or 1/3/5/7 giuliomoro@189: * - Read ADC 1 or 1/3 or 1/3/5/7, 2 samples (@176.4) older than NOW giuliomoro@189: */ giuliomoro@189: if(1) giuliomoro@189: for(unsigned int n = 0; n < context->audioFrames; n++){ giuliomoro@189: static bool analog0In = false; giuliomoro@189: static bool digitalAIn = false; giuliomoro@189: static int count = 0; giuliomoro@189: bool doReadWrite = context->analogChannels<=4 ? true : ((context->analogChannels == 8) && (n&1)==0); giuliomoro@189: if(doReadWrite){ giuliomoro@189: digitalAIn = digitalReadFrame(context, n, gDigitalInACh); giuliomoro@189: switch(context->analogChannels){ giuliomoro@189: case 8: giuliomoro@189: analog0In = analogReadFrame(context, n/2, 0) > 0.5; giuliomoro@189: analogWriteFrame(context, n/2, analogOut, writePattern[outPointer]); giuliomoro@189: break; giuliomoro@189: case 4: giuliomoro@189: analog0In = analogReadFrame(context, n, 0) > 0.5; giuliomoro@189: analogWriteFrame(context, n, analogOut, writePattern[outPointer]); giuliomoro@189: break; giuliomoro@189: case 2: giuliomoro@189: analog0In = analogReadFrame(context, n * 2 + 1, 0) > 0.5; giuliomoro@189: analogWriteFrame(context, 2 * n, analogOut, writePattern[outPointer]); giuliomoro@189: analogWriteFrame(context, 2 * n + 1, analogOut, writePattern[outPointer]); giuliomoro@189: break; giuliomoro@189: } giuliomoro@189: gAnalogOutLoopDelay--; giuliomoro@189: outPointer++; giuliomoro@189: if(gAnalogOutLoopDelay <= 0){ giuliomoro@189: if(++inPointer == patternLength){ giuliomoro@189: inPointer = 0; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: } giuliomoro@189: bool expectedIn = writePattern[inPointer]; giuliomoro@189: if(gAnalogOutLoopDelay <= 0 && doReadWrite == true){ giuliomoro@189: if(analog0In != expectedIn || digitalAIn != expectedIn){ giuliomoro@189: rt_printf("expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n", giuliomoro@189: expectedIn, analog0In, digitalAIn, inPointer, gAnalogOutLoopDelay, count); giuliomoro@189: anaErrorCount++; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: count++; giuliomoro@189: if(analog0In != digitalAIn){ // at any time the analog and digital in should be the same giuliomoro@189: rt_printf("ana %d_%d %d,\n", analog0In, digitalAIn, n); giuliomoro@189: } giuliomoro@189: if(outPointer == patternLength){ giuliomoro@189: outPointer = 0; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: if(1) giuliomoro@189: for(unsigned int n = 0; n < context->audioFrames; n++){ giuliomoro@189: static int count = 0; giuliomoro@189: static bool analog1In = false; giuliomoro@189: static bool digitalDIn = false; giuliomoro@189: /* we need to remember the pastAnalog1In because giuliomoro@189: * reading GPIO takes place before writing to it, therefore giuliomoro@189: * when reading a GPIOout, the GPIOin samples will always be one sample late giuliomoro@189: */ giuliomoro@189: bool doReadWrite = false; giuliomoro@189: static bool pastAnalog1In = false; giuliomoro@189: digitalWriteFrameOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]); giuliomoro@189: if(context->analogChannels == 8){ giuliomoro@189: if((n&1) == 0){ //do it every other sample giuliomoro@189: pastAnalog1In = analogReadFrame(context, n/2, 1) > 0.5; giuliomoro@189: digitalDIn = digitalReadFrame(context, n, gDigitalInDCh); giuliomoro@189: doReadWrite = true; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: if(context->analogChannels == 4){ giuliomoro@189: pastAnalog1In = analogReadFrame(context, n, 1) > 0.5; giuliomoro@189: digitalDIn = digitalReadFrame(context, n, gDigitalInDCh); giuliomoro@189: digitalWriteFrameOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]); giuliomoro@189: doReadWrite = true; giuliomoro@189: } giuliomoro@189: if(context->analogChannels == 2){ giuliomoro@189: pastAnalog1In = analogReadFrame(context, n * 2, 1) > 0.5; giuliomoro@189: digitalDIn = digitalReadFrame(context, n, gDigitalInDCh); giuliomoro@189: digitalWriteFrameOnce(context, n, gDigitalOutCh, writePattern[digitalOutPointer]); giuliomoro@189: doReadWrite = true; giuliomoro@189: } giuliomoro@189: bool expectedDigitalIn = writePattern[digitalInPointer]; giuliomoro@189: if(doReadWrite == true){ giuliomoro@189: gDigitalOutLoopDelay--; giuliomoro@189: if(gDigitalOutLoopDelay <= 0){ giuliomoro@189: if(expectedDigitalIn != pastAnalog1In || expectedDigitalIn != digitalDIn){ giuliomoro@189: rt_printf("D expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n", giuliomoro@189: expectedDigitalIn, pastAnalog1In, digitalDIn, inPointer, gDigitalOutLoopDelay, count); giuliomoro@189: digErrorCount++; giuliomoro@189: } giuliomoro@189: if(++digitalInPointer == patternLength){ giuliomoro@189: digitalInPointer = 0; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: pastAnalog1In = analog1In; giuliomoro@189: if(++digitalOutPointer == patternLength){ giuliomoro@189: digitalOutPointer = 0; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: count++; giuliomoro@189: } giuliomoro@189: if(context->audioSampleCount > 30000){ giuliomoro@189: gShouldStop = true; giuliomoro@189: } giuliomoro@189: } giuliomoro@189: giuliomoro@189: giuliomoro@189: void cleanup(BeagleRTContext *context, void *userData) giuliomoro@189: { giuliomoro@189: if(anaErrorCount == 0 && digErrorCount == 0){ giuliomoro@189: rt_printf("Test was succesful with %d analog channels and a buffer size of %d\n", context->analogChannels, context->audioFrames); giuliomoro@189: } else { giuliomoro@189: rt_printf("------------------------\n%danalog %ddigital errors over %dsamples while running test with ", giuliomoro@189: anaErrorCount, digErrorCount, context->audioSampleCount); giuliomoro@189: rt_printf("%d analog channels and a buffer size of %d \n\n\n", giuliomoro@189: context->analogChannels, context->audioFrames); giuliomoro@189: exit(1); giuliomoro@189: } giuliomoro@189: }