Sign in to follow this  
Followers 0
frohro

How to do use ADC14 in Multi mode with TimerA0 and Energia?

2 posts in this topic

Hi All,

I need to make ADC14 measurements in the multi mode at a sample rate of 8 kHz, but would like to use Energia's Serial and I2C functions.  I have a stand alone driverlib routine that works fine, and Energia code that works fine with the Serial, and I2C, however, I am having difficulty integrating them.  I noticed that the ADC14CTL0 register is changed from what my routine called in setup() did.  I started reading the code in Energia/emt/src/ti/runtime/wiring/msp432/, and it appears that I may need to modify it to make this work, but before I go hacking, I want advice.  Is there a good way to get Energia to leave the ADC14 to me, or is there a way to use Energia's ADC14 routines to do multi conversions at  8 kHz?  I'm enclosing my code in case it is of use:


extern "C"{
#include <copy2_adc14.h>
};


// most launchpads have a red LED
#define LED RED_LED

//see pins_energia.h for more LED definitions
//#define LED GREEN_LED

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(115200);
  // initialize the digital pin as an output.
  //pinMode(LED, OUTPUT);
  adc14_();
  //delay(500);
  //MAP_ADC14_enableConversion();
  startSampling();
}

// the loop routine runs over and over again forever:
void loop() {
    static int i=0;
    Serial.print(i++);
  Serial.println("Hello!");
    //digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  //digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
 // delay(1000);               // wait for a second
}

And the header file:

/*
 * adc14_.h
 *
 *  Created on: May 12, 2017
 *      Author: frohro
 */

#ifndef COPY2_ADC14_H_
#define COPY2_ADC14_H_

/* DriverLib Includes */
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <ti/sysbios/family/arm/m3/Hwi.h>

/* Standard Includes */
#include <stdint.h>

#include <stdbool.h>
#define SMCLK_FREQ 24000000
#define SAMPLE_FREQ 8000
//Timer_A Continuous Mode Configuration Parameter
const Timer_A_UpModeConfig upModeConfig = // This DOES work
{
        TIMER_A_CLOCKSOURCE_SMCLK,           // SM Clock Source
        TIMER_A_CLOCKSOURCE_DIVIDER_1,       // SMCLK/1 = 24MHz
        (SMCLK_FREQ/SAMPLE_FREQ),
        TIMER_A_TAIE_INTERRUPT_DISABLE,      // Disable Timer ISR
        TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE, // Disable CCR0
        TIMER_A_DO_CLEAR                     // Clear Counter
};

/* Timer_A Compare Configuration Parameter */
const Timer_A_CompareModeConfig compareConfig =
{
        TIMER_A_CAPTURECOMPARE_REGISTER_1,          // Use CCR1
        TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   // Disable CCR interrupt
        TIMER_A_OUTPUTMODE_SET_RESET,               // Toggle output but
        (SMCLK_FREQ/SAMPLE_FREQ)                    // Should be 8 kHz sample rate
};

/* Statics */
static volatile uint_fast16_t resultsBuffer[UINT8_MAX];
static volatile uint8_t resPos;

int adc14_(void);
void ADC14_IRQHandler(void);
void startSampling(void);




#endif /* COPY2_ADC14_H_ */

and the C file to run the ADC14:

/*
 * -------------------------------------------
 *    MSP432 DriverLib - v4_00_00_11
 * -------------------------------------------
 *
 * --COPYRIGHT--,BSD,BSD
 * Copyright (c) 2017, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
 /* MSP432 ADC14 - Multiple Channel Sample without Repeat
 *
 * Description: In this code example, the feature of being able to scan multiple
 * ADC channels is demonstrated by the user a the DriverLib APIs.  Conversion
 * memory registers ADC_MEM0 - ADC_MEM3 are configured to read conversion
 * results from A6, A12, A10, A8 respectively. Conversion is enabled and then sampling is
 * toggled using a software toggle. Repeat mode is not enabled and sampling only
 * occurs once (and it is expected that the user pauses the debugger to observe
 * the results). Once the final sample has been taken, the interrupt for
 * ADC_MEM3 is triggered and the result is stored in the resultsBuffer buffer.
 *
 *                MSP432P401
 *             ------------------
 *         /|\|                  |
 *          | |                  |
 *          --|RST         P4.7  |<--- A6 (Analog Input, Measured, Real)
 *            |            P4.1  |<--- A12 (Analog Input, Measured, Imaginary)
 *            |            P4.3  |<--- A10 (Analog Input, Reference Real)
 *            |            P4.5  |<--- A8 (Analog Input, Reference Imaginary)
 *            |                  |
 *            |                  |
 *
 *            4.1, 4.3, 4.5, 4.7 are the eventual pins needed.
 *
 * Author: Timothy Logan
 * This was modified by Rob Frohne to do multiple ADC at 8 kHz sample rate.
 ******************************************************************************/
#include <copy2_adc14.h>
#define NUMBER_TIMER_CAPTURES       20
#define SAMPLE_LENGTH 128

/*
static volatile uint_fast16_t timerAcaptureValues[NUMBER_TIMER_CAPTURES];
static volatile uint32_t timerAcapturePointer = 0;
*/

uint16_t refRe[SAMPLE_LENGTH];
uint16_t refIm[SAMPLE_LENGTH];
uint16_t measRe[SAMPLE_LENGTH];
uint16_t measIm[SAMPLE_LENGTH];
extern volatile bool doneADC;
bool sendMeasurement = false;
int numberFrequenciestoMeasure, frequencyIndex;
float  refSum, measSum;
volatile bool doneADC = false;

int adc14_(void)
{
    /* Halting WDT  */
    WDT_A_holdTimer();
    Hwi_Params params;

    // Register interrupt
    Hwi_Params_init(&params);
    Hwi_create(INT_ADC14, ADC14_IRQHandler, &params, 0);
    //Hwi_create(INT_TA0_N, TA0_N_IRQHandler, &params, 0);
    //Interrupt_enableSleepOnIsrExit();
    resPos = 0;
    // Set to Vcore1
    PCM_setCoreVoltageLevel(PCM_VCORE1);

    // Set to use DCDC
    //PCM_setPowerState(PCM_AM_DCDC_VCORE1);

    // Initializes Clock System
    /*  These commented out because we need the Energia clock setup.  The
     *  data structures for the timer are adjusted accordingly.  The time
     *  between conversions may be four times as much as we had with these
     *  parameters below, but this seems like the easiest way to make everything
     *  play together for now. */
    //FlashCtl_setWaitState( FLASH_BANK0, 2);
    //FlashCtl_setWaitState( FLASH_BANK1, 2);
    PCM_setPowerState( PCM_AM_DCDC_VCORE1 );
    CS_setDCOCenteredFrequency( CS_DCO_FREQUENCY_24 );
    //CS_setDCOFrequency(24000000);
    CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );;
    CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );


    /* Initializing ADC (MCLK/1/1) */
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1,
                         0);

    // Configuring debugging pins as output for debugging...
    GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN5);
    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);

    //Configuring GPIOs for Analog In
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,
        GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION);

    // Configuring ADC Memory (ADC_MEM0 - ADC_MEM3 (A6, A12, A10, A8)  with no repeat)
    // with internal 2.5v reference
    ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM3, true); // No repeat mode.
    ADC14_configureConversionMemory(ADC_MEM0,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A6, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM1,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A12, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM2,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A10, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM3,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A8, ADC_NONDIFFERENTIAL_INPUTS);

    /* Configuring Timer_A*/
    Timer_A_configureUpMode(TIMER_A0_BASE, &upModeConfig);

    /* Configuring Timer_A0 in CCR1 */
    Timer_A_initCompare(TIMER_A0_BASE, &compareConfig);

    /* Configuring the sample trigger to be sourced from Timer_A0  and setting it
     * to automatic iteration after it is triggered*/
    ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);

    /* Enabling the interrupt when a conversion on channel 3 is complete*/
    ADC14_enableInterrupt(ADC_INT3);
    //ADC14_enableConversion(); // Not needed because we enable it in .ino.

    /* Enabling Interrupts */
    Interrupt_enableInterrupt(INT_ADC14);
    Interrupt_enableMaster();

    /* Starting the Timer */
    Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);

    /* Going to sleep */
  /*      while (1)
    {
        PCM_gotoLPM0();
    }*/
    return 1;
}


void ADC14_IRQHandler(void)
{
    uint64_t status;
    static int i = 0;
    //GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    status = ADC14_getEnabledInterruptStatus();
    ADC14_clearInterruptFlag(status);
    GPIO_toggleOutputOnPin(GPIO_PORT_P5, GPIO_PIN5);
    ADC14_disableConversion();

    if(status & ADC_INT3)
    {
        //ADC14_disableConversion();
        doneADC = false;
        ADC14_getMultiSequenceResult(resultsBuffer);
        measRe[i] = resultsBuffer[0];
        measIm[i] = resultsBuffer[1];
        refRe[i] = resultsBuffer[2];
        refIm[i] = resultsBuffer[3];
        //i=(i+1)%SAMPLE_LENGTH;

        if (i!=SAMPLE_LENGTH)
        {
            i++;
            //ADC14_enableConversion();
        }
        else
        {
            i=0;
            doneADC = true;
            //ADC14_enableConversion();
        }
    }
    ADC14_enableConversion();
}



void startSampling(void)
{
    ADC14_enableConversion();  // It is a mystery why I need to do this
    // instead of just calling ADC14_enableConversion()
    // from the .ino file!
}

Thanks,

Rob

Share this post


Link to post
Share on other sites

Hi All,

I got no replies, but thought I should put the answer here for anyone else who finds this and needs it.  It appears that setting the interrupt priority is important.  Here is some working (for me) code:

/*
 * -------------------------------------------
 *    MSP432 DriverLib - v4_00_00_11
 * -------------------------------------------
 *
 * --COPYRIGHT--,BSD,BSD
 * Copyright (c) 2017, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
 /* MSP432 ADC14 - Multiple Channel Sample without Repeat
 *
 * Description: In this code example, the feature of being able to scan multiple
 * ADC channels is demonstrated by the user a the DriverLib APIs.  Conversion
 * memory registers ADC_MEM0 - ADC_MEM3 are configured to read conversion
 * results from A6, A12, A10, A8 respectively. Conversion is enabled and then sampling is
 * toggled using a software toggle. Repeat mode is not enabled and sampling only
 * occurs once (and it is expected that the user pauses the debugger to observe
 * the results). Once the final sample has been taken, the interrupt for
 * ADC_MEM3 is triggered and the result is stored in the resultsBuffer buffer.
 *
 *                MSP432P401
 *             ------------------
 *         /|\|                  |
 *          | |                  |
 *          --|RST         P4.7  |<--- A6 (Analog Input, Measured, Real)
 *            |            P4.1  |<--- A12 (Analog Input, Measured, Imaginary)
 *            |            P4.3  |<--- A10 (Analog Input, Reference Real)
 *            |            P4.5  |<--- A8 (Analog Input, Reference Imaginary)
 *            |                  |
 *            |                  |
 *
 *            4.1, 4.3, 4.5, 4.7 are the eventual pins needed.
 *
 * Author: Timothy Logan
 * This was modified by Rob Frohne to do multiple ADC at 8 kHz sample rate.
 ******************************************************************************/
#include <copy2_adc14.h>
#define SAMPLE_LENGTH 128

uint16_t refRe[SAMPLE_LENGTH];
uint16_t refIm[SAMPLE_LENGTH];
uint16_t measRe[SAMPLE_LENGTH];
uint16_t measIm[SAMPLE_LENGTH];
extern volatile bool doneADC;
bool sendMeasurement = false;
int numberFrequenciestoMeasure, frequencyIndex;
float  refSum, measSum;
volatile bool doneADC = false;

void ADC14_IRQHandler(void);

int adc14_(void)
{

    // Register interrupt
    Hwi_Params params;
    Hwi_Params_init(&params);
    Hwi_create(INT_ADC14, ADC14_IRQHandler, &params, 0);
    Hwi_setPriority(INT_ADC14, 60);

    //Interrupt_enableSleepOnIsrExit();
    resPos = 0;

    /* Initializing ADC (MCLK/1/1) */
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1,
                         0);

    // Configuring debugging pins as output for debugging...
    GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN5);
    GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);

    //Configuring GPIOs for Analog In
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4,
        GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION);

    // Configuring ADC Memory (ADC_MEM0 - ADC_MEM3 (A6, A12, A10, A8)  with no repeat)
    // with internal 2.5v reference
    ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM3, false); // No repeat mode.
    ADC14_configureConversionMemory(ADC_MEM0,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A6, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM1,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A12, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM2,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A10, ADC_NONDIFFERENTIAL_INPUTS);
    ADC14_configureConversionMemory(ADC_MEM3,
                                        ADC_VREFPOS_INTBUF_VREFNEG_VSS,
                                        ADC_INPUT_A8, ADC_NONDIFFERENTIAL_INPUTS);

    /* Configuring Timer_A*/
    Timer_A_configureUpMode(TIMER_A0_BASE, &upModeConfig);

    /* Configuring TIMER_A3 in CCR1 */
    Timer_A_initCompare(TIMER_A0_BASE, &compareConfig);

    /* Configuring the sample trigger to be sourced from TIMER_A3  and setting it
     * to automatic iteration after it is triggered*/
    ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);

    /* Setting up the sample timer to automatically step through the sequence
     * convert.
     */
    ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);

    /* Enabling the interrupt when a conversion on channel 3 is complete*/
    ADC14_enableInterrupt(ADC_INT3);
    //ADC14_enableConversion(); // Not needed because we enable it in .ino.

    /* Enabling Interrupts */
    Interrupt_enableInterrupt(INT_ADC14);
    Interrupt_enableMaster();

    /* Starting the Timer */
    Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);
    //Hwi_enable();

    return 1;
}


void ADC14_IRQHandler(void)
{
    uint64_t status;
    static int i = 0;
    status = ADC14_getEnabledInterruptStatus();
    ADC14_clearInterruptFlag(status);

    if(status & ADC_INT3)
    {
        ADC14_disableConversion();
        doneADC = false;
        ADC14_getMultiSequenceResult(resultsBuffer);
        measRe[i] = resultsBuffer[0];
        measIm[i] = resultsBuffer[1];
        refRe[i] = resultsBuffer[2];
        refIm[i] = resultsBuffer[3];
        GPIO_toggleOutputOnPin(GPIO_PORT_P5, GPIO_PIN5);
        if (i!=SAMPLE_LENGTH)
        {
            i++;
            ADC14_enableConversion();
        }
        else
        {
            i=0;
            doneADC = true;
            ADC14_enableConversion();
        }
    }
}

The header and .ino are similar to the above.

Rob

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0