Issue with analog.c

Status
Not open for further replies.

WMXZ

Well-known member
I try to modify resolution and averaging of ADC object but it fails

Code:
/*
 * Simple ADC test
 */
#include "input_adc.h"
#include "record_queue.h"

#define STEP 0

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;         //xy=165,237
AudioRecordQueue         queue1;       //xy=348,308
AudioConnection          patchCord1(adc1, queue1);
// GUItool: end automatically generated code

void setup() {
  // put your setup code here, to run once:

  AudioMemory (4);
  while(!Serial);
  Serial.println("Start");

#if (STEP ==1)
  Serial.println("change1");
  analogReadRes(10);
  analogReference(INTERNAL); // range 0 to 1.2 volts
  analogReadAveraging(1);
#endif
  queue1.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  static uint32_t count=0;
 if(queue1.available())
 {  // fetch data from queue
    int16_t * data =queue1.readBuffer();
    queue1.freeBuffer(); 
    count++;
 }
 
 static uint32_t t0;
 if(millis()>t0+1000)
 {  Serial.printf("loop: ");
    Serial.printf("%d %d %d\n",count, PDB0_CNT, PDB0_MOD);
    t0=millis();
    count=0;
 }
}

compiled as is generates:
Code:
Start
loop: 199 163 1359
loop: 345 1119 1359
loop: 345 801 1359
loop: 345 476 1359
loop: 345 149 1359
loop: 345 1184 1359
loop: 345 895 1359
loop: 345 563 1359
loop: 345 220 1359
which is OK
first number after loop is number of blocks retrieved from queue, the other two numbers are from PDB

However, compiled with #define STEP 1, that is with the additional code in setup() to modify ADC setup, the result becomes:
Code:
Start
change1
loop: 0 1342 1359
loop: 0 906 1359
loop: 0 570 1359
loop: 0 252 1359
loop: 0 1282 1359
loop: 0 980 1359
loop: 0 636 1359
loop: 0 304 1359
that is, no buffers are found on queue.

It seems that the call to the analog.c functions are not always handled correctly and crashed ADC operation.

Note, I have no problem with generating my own ADC object or use Pelvide's ADC library, but here I wanted to use Audio Library without modifications to the library.
 
Printing out PDC0_CH0S after the calls to analog.c indicates a sequence error
(according to Manual: )
Sequence error detected on PDB channel's corresponding pre-trigger. ADCn block can be triggered
for a conversion by one pre-trigger from PDB channel n. When one conversion, which is triggered by
one of the pre-triggers from PDB channel n, is in progress, new trigger from PDB channel's
corresponding pre-trigger m cannot be accepted by ADCn, and ERR[m] is set. Writing 0’s to clear the
sequence error flags.

commenting the "analogReadRes(10);" line or equivalently setting resolution to 16 (function in analog.c will skip)
PDB sequence error will not show up and results are as expected.

Edit, but not always :(
 
Last edited:
Since you use the ADC object from the audio library, I think it is not a good idea to try to modify it with external or standard functions since at a first glance, one doesn’t know how the ADC parameters are handled and set inside that object.
If I were you, I’d clone the ADC input object first and then add the needed additional member vars and functions directly to that object to get a clean code and clean functioning.
 
Since you use the ADC object from the audio library, I think it is not a good idea to try to modify it with external or standard functions since at a first glance, one doesn’t know how the ADC parameters are handled and set inside that object.
If I were you, I’d clone the ADC input object first and then add the needed additional member vars and functions directly to that object to get a clean code and clean functioning.

Well,
I know and I have my own set of libraries, that are tuned to the application I'm interested in.
Custom software has, unfortunately, the drawback of not to being very usable outside the original context.

Meanwhile, I found a work around of the problem (reading some threads on the NXP forum)

it does not solve the problem with the calls to the functions in analog.c but it is a possible solution.

The code is nearly identical to the code in analog.c, with the exception that after setting ADC0 there is no calibration.
I do not know if this is needed, but I wanted first I code that seems to work.

Obviously, this mods are part of a larger program, which I will present shortly.

Anyhow, here comes the work around.


Code:
/*
 * Simple ADC test modified
 */
#include "input_adc.h"
#include "record_queue.h"

#define STEP 1

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;         //xy=165,237
AudioRecordQueue         queue1;       //xy=348,308
AudioConnection          patchCord1(adc1, queue1);
// GUItool: end automatically generated code

/*
 * ---------------------------------------------------------------------- 
 * following Mark Butcher: https://community.nxp.com/thread/434148
 * code does not do calibration, so improvements are possible
 */
 void modifyADC(int16_t res, uint16_t avg)
 {
#if (F_BUS==60000000)
  #define ADC_CFG1_16BIT  ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7.5 MHz
  #define ADC_CFG1_12BIT  ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
  #define ADC_CFG1_10BIT  ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
  #define ADC_CFG1_8BIT   ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
#else
  #error "F_BUS must be 60 MHz, please adjust"
#endif

// stop PDB
  PDB0_CH0C1 = 0;   // disable ADC triggering
  PDB0_SC &= ~PDB_SC_PDBEN;
  //
  if(res==16)
  {
//  analogReadRes(16);
    ADC0_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
    ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  }
  else if(res==12)
  {
//  analogReadRes(12);
    ADC0_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
    ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  }
  else if(res==10)
  {
//  analogReadRes(10);
    ADC0_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
    ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  }
  else if(res==8)
  {
//  analogReadRes(8);
    ADC0_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0);
    ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  }

//  analogReference(INTERNAL); // range 0 to 1.2 volts
    ADC0_SC2 = ADC_SC2_REFSEL(1);

//  analogReadAveraging(4);
  if (avg <= 1) {
    ADC0_SC3 = 0;  // begin cal
  } else if (avg <= 4) {
    ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
  } else if (avg <= 8) {
    ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
  } else if (avg <= 16) {
    ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
  } else {
    ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
  }
//
    ADC0_SC2 |= ADC_SC2_ADTRG | ADC_SC2_DMAEN;  // reassert HW trigger

// restart PDB
  (void)ADC0_RA;
  PDB0_CH0C1 = 0x0101;
  PDB0_SC |= PDB_SC_PDBEN ;
  PDB0_SC |= PDB_SC_SWTRIG ;  // kick off the PDB* - just once  
 }

void setup() {
  // put your setup code here, to run once:

  AudioMemory (10);
  while(!Serial);
  Serial.println("Start");

#if (STEP ==1)
  Serial.println("change1");
  modifyADC(10,1);
#endif

  queue1.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  static uint32_t count=0;
 if(queue1.available())
 {  // fetch data from queue
    int16_t * data =queue1.readBuffer();
    queue1.freeBuffer(); 
    count++;
 }
 
 static uint32_t t0;
 if(millis()>t0+1000)
 {  Serial.printf("loop: ");
    Serial.printf("%d %d %d %d\n",AudioMemoryUsageMax(),count, PDB0_CNT, PDB0_MOD);
    t0=millis();
    count=0;
    AudioMemoryUsageMaxReset();
 }
}
result:
Code:
Start
change1
loop: 2 199 1170 1359
loop: 2 345 795 1359
loop: 2 345 489 1359
loop: 2 345 115 1359
loop: 2 345 1146 1359
loop: 2 345 831 1359
 
Status
Not open for further replies.
Back
Top