Sign in to follow this  
Followers 0
frohro

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

1 post 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

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