This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADC DMA data occasionally has errors

Other Parts Discussed in Thread: CC3220SF, CC3200

square wave waveform, sampled DMA data occasionally has an error part (1K data per sample)

  • Hello,

    Would you confirm which product you're using?

  • Hi,

    Are you using the built-in ADC of the CC32xx, or are you using a separate ADC device?

    For the CC32xx, the ADC has a fixed sampling rate of 62.5K Samples/sec. When you mention (1K data per sample), are you trying to sample at 1K samples/sec, or are you indicating that there is 1 error per 1K samples?

    The CC32xx ADC appnote might be useful for reference as well: https://www.ti.com/lit/an/swra679

    Regards,

    Michael

  • hi Michael:

    I use the built-in ADC of the CC3220SF, and the SDK version is simplelink_cc32xx_sdk_4_20_00_07

    the ADC has a fixed sampling rate of 62.5K Samples/sec, and I will sampling once every 6 data(1K data per sample), Data errors are irregular, not a fixed 1K error. For example, a square wave will suddenly appear 0x3EF, and it will automatically return to normal after a period of time.

    I don’t know what caused the data error for a while, please help analyze the reason, thank you!!

    Regards,

    Ken lai

  • Hi Ken,

    Are you performing any processing other than collecting the raw ADC values? If so, you might be encountering a bottleneck where the MCU cannot fetch the next set of samples quick enough, causing artifacts in your sampling.

    Also, how is your sampling code constructed? Are you using a hardware timer to time the samples, or are you using some other mechanism to sample? Attached is some code I wrote for the CC3220 to sample analog audio, which might be of use to you as a reference for sampling technique. Do note that the code has options for UART and I2S audio sampling, use the USE_ANALOG_AUDIO_IN define to only enable/highlight the relevant analog audio code./cfs-file/__key/communityserver-discussions-components-files/968/audio_5F00_collect.c

    Regards,

    Michael

  • hi Michael:

          In your example, the USE_ANALOG_AUDIO_IN macro uses the hardware timer 8K/16K frequency to sample the ADC, which will take up MCU resources. I did not do this
         I use the DMA method to sample the ADC, that is, in the ADC interrupt, when the ADC FIFO is full, turn on DMA (ping-pong mode) to copy the data to the buffer, and then I will process the buffered data, some of the code is as follows :


    //1.adc fifo is full
    if(status & ADC_FIFO_FULL)
    {
    ReloadDma();
    }

    //2.Use DMA to save data in the cache
    void ReloadDma(void)
    {
         static uint8_t sw = 0;
         unsigned short *p = mallocGADCDMABuffer();
         unsigned int key;

    /* A lock is needed because we are accessing shared uDMA registers.*/
    key = HwiP_disable();

    if((sw++ & 0x01) == 0)
    {
    MAP_uDMAChannelControlSet(UDMA_CH15_ADC_CH1, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1 | UDMA_MODE_PINGPONG);
    MAP_uDMAChannelTransferSet(UDMA_CH15_ADC_CH1, UDMA_MODE_PINGPONG, (void*)(ADC_BASE + ADC_O_channel2FIFODATA),
    &p[2], ADC_DMA_BUFFERSIZE-3); //ping
    MAP_uDMAChannelEnable(UDMA_CH15_ADC_CH1);
    }
    else
    {
    MAP_uDMAChannelControlSet(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1 | UDMA_MODE_PINGPONG);
    MAP_uDMAChannelTransferSet(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void*)(ADC_BASE + ADC_O_channel2FIFODATA),
    &p[2], ADC_DMA_BUFFERSIZE-3); //pong
    MAP_uDMAChannelEnable(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT);
    }
    //MAP_uDMAChannelEnable(UDMA_CH15_ADC_CH1);
    //MAP_uDMAEnable();

    if(uShADCDMABufferNull != p)
       writeGADCDMABufferDone();

      HwiP_restore(key);
    }

  • Hi Ken,

    Yes, my method does take up some MCU resources, while the DMA approach you are using offloads the memory writes to the DMA peripheral.

    I'm curious, how is the ADC FIFO reaching the full state if you are using DMA ping pong to copy the data from the FIFOs to memory? Assuming you are reloading the DMA buffers in time, it should not allow the FIFO to get filled. Have you tried performing the DMA reload based off of the DMA transfer complete interrupt, rather than the ADC FIFO getting full?

    Regards,

    Michael

  • hi Michael:

    How to perform DMA reload according to the interrupt of DMA transfer completion? I can't find the relevant information. Could you provide an example?

    thank you

  • Hi Ken,

    Please take a look at this thread here, where I explain the code needed, and how you can use the CC3200 smartplug TI design metrology ADC code as a base:

    https://e2e.ti.com/support/wireless-connectivity/wifi/f/968/t/702668?CCS-CC3220-Configuring-Timer-DMA-ADC-for-continuous-sampling

    While it is designed for the CC3200, as the peripheral code is the same the raw driverlib can be reused for the CC3220.

    Please take a look at the smartplug ADC code and try adapting that for your application. The file of interest within the smartplug project is metrology.c

    Regards,

    Michael

  • Hi Michael:

    Thank you. According to the configuration of the smartplug-gen1 project, set the DMA completion interrupt

          At least encountered the following problems:
    1. It has never been detected that the ADC_DMA_DONE bit is 1
    2. The ADC data sampled regularly appears in a segment of 0
    3. After sampling for a few minutes, the system will get stuck

    Part of the code is as follows:

    1.Configure DMA

        //ping
        UDMASetupTransfer(UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
                          ADC_DMA_BUFFERSIZE - 3,
                          UDMA_SIZE_16, UDMA_ARB_1,
                          (void *)(ADC_BASE + ADC_O_channel2FIFODATA), UDMA_SRC_INC_NONE,
                          (void *) & (uShADCDMABufferPing[0]), UDMA_DST_INC_16);
        //pong
        UDMASetupTransfer(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG,
                          ADC_DMA_BUFFERSIZE - 3,
                          UDMA_SIZE_16, UDMA_ARB_1,
                          (void *)(ADC_BASE + ADC_O_channel2FIFODATA), UDMA_SRC_INC_NONE,
                          (void *) & (uShADCDMABufferPong[0]), UDMA_DST_INC_16);

        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_OVERFLOW);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_UNDERFLOW);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_EMPTY);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_FULL);

        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_OVERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_UNDERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_EMPTY);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_FULL);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);

        //enable
        ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCChannelEnable(ADC_BASE, ADC_CH_1);

        // Set the priority
        IntPrioritySet(ADC_CH_1, INT_PRIORITY_LVL_2);
        IntPendClear(ADC_CH_1);
        ADCIntRegister(ADC_BASE, ADC_CH_1, ADCIntHandler);
        ADCDMAEnable(ADC_BASE, ADC_CH_1);

        // Enable ADC
        //ADCTimerConfig(ADC_BASE, 2 ^ 17);
        //ADCTimerEnable(ADC_BASE);
        ADCEnable(ADC_BASE);

    2.Interrupt handler

    void ADCIntHandler(void)
    {
        unsigned long status = 0;

    #if 0
        while( ADCFIFOLvlGet(ADC_BASE, ADC_CH_1) )
        {
            das = ADCFIFORead(ADC_BASE, ADC_CH_1);
            i++;
        }
    #endif

        status = ADCIntStatus(ADC_BASE, ADC_CH_1);
        UART_PRINT("ADCIntStatus=[%d]-%d,%d\n\r", status, status & ADC_FIFO_FULL, status & ADC_DMA_DONE);
        if(status & ADC_FIFO_FULL) //ADC_FIFO_FULL
        {
            //copyDma();
            //ReloadDma();
        }
        copyDma();

        //uShADCDMABuffer[3] =0;s
        //Report("Irq 3st - %lx \n",ADCIntStatus(ADC_BASE,ADC_CH_1));
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    #if 0
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_OVERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_UNDERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_EMPTY);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_FULL);
    #endif
    }

    3.DMA data copy to buffer

    void copyDma(void)
    {
        unsigned short *pDataDumpBuff = NULL;
        unsigned short *p = mallocGADCDMABuffer();
        unsigned int key;
        unsigned int ulChannelStructIndex, ulMode, ulControl;
        tDMAControlTable *pControlTable;

        //
        // Check the DMA control table to see if the ping-pong "A" transfer is
        // complete.  The "A" transfer uses receive buffer "A", and the primary
        // control structure.
        //
        ulMode = MAP_uDMAChannelModeGet(UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT);
        //
        // If the primary control structure indicates stop, that means the "A"
        // receive buffer is done.  The uDMA controller should still be receiving
        // data into the "B" buffer.
        //
        if(ulMode == UDMA_MODE_STOP)
        {
            ulChannelStructIndex = UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT;
            pDataDumpBuff = &(uShADCDMABufferPing[0]);
        }
        else
        {
            //
            // Check the DMA control table to see if the ping-pong "A" transfer is
            // complete.  The "A" transfer uses receive buffer "A", and the primary
            // control structure.
            //
            ulMode = MAP_uDMAChannelModeGet(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT);
            //
            // If the primary control structure indicates stop, that means the "A"
            // receive buffer is done.  The uDMA controller should still be receiving
            // data into the "B" buffer.
            //
            if(ulMode == UDMA_MODE_STOP)
            {
                ulChannelStructIndex = UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT;
                pDataDumpBuff = &(uShADCDMABufferPong[0]);
            }
        }

        if(pDataDumpBuff != NULL)
        {
            /* A lock is needed because we are accessing shared uDMA registers.*/
            key = HwiP_disable();

            memcpy(p, pDataDumpBuff, ADC_DMA_BUFFERSIZE - 3);

            if(uShADCDMABufferNull != p)
                writeGADCDMABufferDone();

            HwiP_restore(key);

            // Set up the next transfer for the "A" buffer, using the primary
            // control structure.  When the ongoing receive into the "B" buffer is
            // done, the uDMA controller will switch back to this one.
            //
            ulChannelStructIndex &= 0x3f;
            //
            // Get the base address of the control table.
            //
            pControlTable = (tDMAControlTable *)HWREG(UDMA_BASE + UDMA_O_CTLBASE);
            //
            // Get the current control word value and mask off the mode and size
            // fields.
            //
            ulControl = (pControlTable[ulChannelStructIndex].ulControl &
                         ~(UDMA_CHCTL_XFERSIZE_M | UDMA_CHCTL_XFERMODE_M));

            //
            // Set the transfer size and mode in the control word (but don't write the
            // control word yet as it could kick off a transfer).
            //
            ulControl |= UDMA_MODE_PINGPONG | ((ADC_DMA_BUFFERSIZE - 3 - 1) << 4);

            //
            // Write the new control word value.
            //
            pControlTable[ulChannelStructIndex].ulControl = ulControl;
        }
    }

  • Hi Ken,

    It doesn't look like you clear the ADC_DMA_DONE interrupt before enabling that interrupt source + the ADC. Can you try clearing it, like you clear the other interrupt sources, before you enable the ADC?

    Also, if you never get that interrupt, then which interrupt are you getting in the ADC int handler?

    Regards,

    Michael

  • Hi Michael:

           In the previous reply code, before enabling the interrupt source and ADC, the ADC_DMA_DONE interrupt has been cleared, and then the ADC_DMA_DONE interrupt is turned on, and the ADC_DMA_DONE interrupt is cleared every time in the interrupt function

      In the interrupt function, you can see that the ADC_FIFO_FULL interrupt is generated, and the place of printing is

        status = ADCIntStatus(ADC_BASE, ADC_CH_1);
        UART_PRINT("ADCIntStatus=[%d]-%d,%d\n\r", status, status & ADC_FIFO_FULL, status & ADC_DMA_DONE);

  • Hi Ken,

    If the ADC_FIFO_FULL interrupt is not generated and the ADC_FIFO_FULL interrupt is generated instead, perhaps the DMA is not setup correctly. Do you observe any specific irregularities with the DMA during this process? If you read the DMA control registers for the channels servicing the ADC, do you see the number of remaining words decrement correctly, and that the addresses use seem valid?

    Regards,

    Michael

  • hi Michael:

           The DMA address should be available, because normal data can be sampled from the ADC.

           Just like my previous reply, after sampling a piece of correct data from the ADC, it will sample a piece of data with all 0s, and then another piece of data. is normal data, such a loop, this is where DMA looks abnormal

  • Hi Ken,

    If you're copying the metrology.c ADC + DMA code, as you appear to be doing from the code snippet provided, it should result in the DMA fetching data constantly. If I understand your latest post, it appears that after each successful DMA buffer read, there is an unsuccessful data read. So 50% of the data is not received, is that correct? In such a case the ping-pong mechanism doesn't appear to work correctly.

    Could you please provide me the full code source file for your ADC + DMA code? Having the full context of your code snippet, as well as being able to format it for easier readability would be good.

    Regards,

    Michael

  • hi Michael:

              It seems that after successfully reading the DMA buffer every time, the data cannot be read? Not every time, but after reading the data several times, the data is abnormal several times (all 0x0)


    vMyOwnADCInit, initialize DMA
    ADCIntHandler, DMA interrupt function
    copyDma, copy ping-pong data to buffer

    /*
     * dma.c
     *
     *  Created on: 2019楠烇拷2閺堬拷25閺冿拷
     *      Author: hxq
     */
    #include <stdint.h>
    #include <stddef.h>
    #include <string.h>
    /* POSIX Header files */
    //#include <pthread.h>
    
    /* Driver Header files */
    #include <ti/drivers/ADC.h>
    #include <ti/display/Display.h>
    #include <ti/drivers/UART.h>
    
    //#include <C:/ti/xdctools_3_50_08_24_core/packages/xdc/std.h>
    //#include <ti/sysbios/knl/Clock.h>
    //#include <ti/sysbios/knl/Task.h>
    
    #include <ti/devices/cc32xx/inc/hw_ints.h>
    #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
    #include <ti/devices/cc32xx/inc/hw_memmap.h>
    #include <ti/devices/cc32xx/inc/hw_adc.h>
    #include <ti/devices/cc32xx/inc/hw_types.h>
    #include <ti/devices/cc32xx/driverlib/rom.h>
    #include <ti/devices/cc32xx/driverlib/rom_map.h>
    #include <ti/devices/cc32xx/driverlib/adc.h>
    #include <ti/devices/cc32xx/driverlib/gpio.h>
    #include <ti/devices/cc32xx/driverlib/pin.h>
    #include <ti/devices/cc32xx/driverlib/prcm.h>
    #include <ti/devices/cc32xx/driverlib/spi.h>
    #include <ti/devices/cc32xx/driverlib/sdhost.h>
    #include <ti/devices/cc32xx/driverlib/timer.h>
    #include <ti/devices/cc32xx/driverlib/uart.h>
    #include <ti/devices/cc32xx/driverlib/udma.h>
    #include <ti/devices/cc32xx/driverlib/wdt.h>
    
    
    #include <ti/devices/cc32xx/inc/hw_memmap.h>
    #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
    #include <ti/devices/cc32xx/inc/hw_ints.h>
    #include <ti/devices/cc32xx/inc/hw_types.h>
    #include <ti/devices/cc32xx/inc/hw_adc.h>
    #include <ti/devices/cc32xx/inc/hw_udma.h>
    
    /* Driverlib Header Files */
    #include <ti/devices/cc32xx/driverlib/rom.h>
    #include <ti/devices/cc32xx/driverlib/rom_map.h>
    #include <ti/devices/cc32xx/driverlib/udma.h>
    #include <ti/devices/cc32xx/driverlib/adc.h>
    #include <ti/devices/cc32xx/driverlib/interrupt.h>
    
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <UDMACC32XX.h>
    #include <ti/drivers/ADC.h>
    #include <ti/drivers/adc/ADCCC32XX.h>
    #include <ti/drivers/dpl/swip.h>
    
    
    /* Example/Board Header files */
    //#include "Board.h"
    #include "uart_term.h"
    #include "network_terminal.h"
    #include "timeConfig.h"
    
    
    void TempADC(uint16_t *temp);
    void tempADCopen(void);
    void tempADCclose(void);
    
    void vMyOwnDMAInit(void);
    void vMyOwnADCInit(void);
    void vMyOwnDmaAdcInit(void);
    void ADCIntHandler(void);
    //UART_Handle uart;
    uint16_t   sample;
    UDMACC32XX_Handle udma;
    ADC_Handle adc_ch2;
    int dma_flag = 1; //0
    int dmaDropCount = 0;
    bool ADCDMABufFull = FALSE;
    
    #define ADC_LEN 1024   //閺佺増宓侀梹鍨
    #ifndef ADC_DMA_BUFFERSIZE
    #define ADC_DMA_BUFFERSIZE 1027
    #endif
    unsigned short uShADCDMABufferPing[ADC_DMA_BUFFERSIZE + 5] = {0xFEFF};
    unsigned short uShADCDMABufferPong[ADC_DMA_BUFFERSIZE + 5] = {0xFEFF};
    unsigned short uShADCDMABufferNull[ADC_DMA_BUFFERSIZE] = {0xFEFF};
    static ADCDMABuffer_t gADCDMABuffer[MAX_ADC_DMA_LEN + 1];
    static int readADCDMAIdx = 0;
    static int writeADCDMAIdx = 0;
    
    #ifdef DMABUFFER2
    static ADCDMABuffer_t gADCDMABufferSend[MAX_ADC_DMA_LEN + 1];
    static int readADCDMASendIdx = 0;
    static int writeADCDMASendIdx = 0;
    static int remainCnt = 1, start = 2;
    static int gBufIdx = 0;
    int dmaDropSendCount = 0;
    #endif
    
    extern unsigned char checkdma;
    
    
    ADC_Handle   adc;
    ADC_Params   params;
    
    SwiP_Handle swi0;
    
    void swiFunc(uintptr_t arg0, uintptr_t arg1)
    {
        //int key1;
        //key1 = SwiP_disable();
    
        UART_PRINT("swiFunc:%d,in ISR:%d........\n\r", SwiP_getTrigger(), SwiP_inISR());
    
        //SwiP_restore(key1);
    }
    
    void swi_create(void)
    {
        SwiP_Params swiParams;
    
        SwiP_Params_init(&swiParams);
        swi0 = SwiP_create(swiFunc, &swiParams);
        if (swi0 ==  NULL)
        {
            UART_PRINT( "Swi create failed");
        }
        //SwiP_setPriority(swi0, 6);
    }
    
    //闁插洦淇惔锟?
    void TempADC(uint16_t *temp)
    {
    
        /* Blocking mode conversion */
        ADC_convert(adc, temp);
    
    //    ADC_close(adc);
    }
    
    void tempADCopen(void)
    {
        ADC_Params_init(&params);
        adc = ADC_open(0, &params); //pin59
    
    }
    
    void tempADCclose(void)
    {
        if(adc == ADC_STATUS_SUCCESS)
        {
            ADC_close(adc);
        }
    }
    
    /*****************adc pin58888888888***************/
    
    
    void vMyOwnDmaAdcInit()
    {
        //vMyOwnDMAInit();
        vMyOwnADCInit();
    }
    
    void addReadADCDMAIdx(void)
    {
        readADCDMAIdx = (readADCDMAIdx + 1) % MAX_ADC_DMA_LEN;
    }
    
    void addWriteADCDMAIdx(void)
    {
        writeADCDMAIdx = (writeADCDMAIdx + 1) % MAX_ADC_DMA_LEN;
    }
    
    void resetRWADCDMAIdx(void)
    {
        readADCDMAIdx = 0;
        writeADCDMAIdx = 0;
    }
    
    void initGADCDMABuffer(void)
    {
        int i;
    
        /*init global adc dma buffer*/
        for(i = 0; i < MAX_ADC_DMA_LEN; i++)
        {
            gADCDMABuffer[i].used = FALSE;
            gADCDMABuffer[i].buf[0] = 0xFEFF;
            gADCDMABuffer[i].buf[ADC_DMA_BUFFERSIZE - 1] = 0xFCFB;
        }
    
    #ifdef DMABUFFER2
        for(i = 0; i < MAX_ADC_DMA_LEN; i++)
        {
            gADCDMABufferSend[i].used = FALSE;
            gADCDMABufferSend[i].buf[0] = 0xFEFF;
            gADCDMABufferSend[i].buf[ADC_DMA_BUFFERSIZE - 1] = 0xFCFB;
        }
    #endif
    
        uShADCDMABufferNull[0] = 0xFEFF;
        uShADCDMABufferNull[ADC_DMA_BUFFERSIZE - 1] = 0xFCFB;
    }
    
    bool sampleIsFinish(int idx)
    {
        bool ret = FALSE;
        int vibrationRate = gRxTime.vibrationRate;
    
        if(vibrationRate == 62500 && idx == 62) //62.5K
        {
            ret = TRUE;
        }
        else if(vibrationRate == 10000 && idx == 10) //10K
        {
            ret = TRUE;
        }
        else if(vibrationRate == 1000 && idx == 1) //1K
        {
            ret = TRUE;
        }
    
    #if 0
        if(ret)
            UART_PRINT("%s:%d-rate:%d,ret,%d\n\r", __FUNCTION__, __LINE__, vibrationRate, ret);
    #endif
        return ret;
    }
    
    unsigned short *mallocGADCDMABuffer(void)
    {
        unsigned short *p = uShADCDMABufferNull; //default write into drop buffer
        int idx;
    
        idx = writeADCDMAIdx;
        if(dma_flag == 0)
        {
            p = uShADCDMABufferNull;
        }
        else if(
    #ifdef SAMPLE_INTERVAL
            !sampleIsFinish(idx) &&
    #endif
            gADCDMABuffer[idx].used == FALSE)
        {
            UART_PRINT("writeADCDMAIdx=[%d]\n\r", idx);
            p = gADCDMABuffer[idx].buf;
    #if 0
            gADCDMABuffer[idx].used = TRUE;
            addWriteADCDMAIdx();
    #endif
        }
        else
        {
    #ifdef SAMPLE_INTERVAL
            ADCDMABufFull = TRUE;
    #endif
            //UART_PRINT("DMABuffer full=[%d] error!\n",idx);
            dmaDropCount++;
        }
    
        return p;
    }
    
    bool canReadDMABuffer(void)
    {
        int diff;
    
        if(readADCDMAIdx < writeADCDMAIdx)
        {
            diff = writeADCDMAIdx - readADCDMAIdx;
        }
        else
        {
            diff = writeADCDMAIdx + MAX_ADC_DMA_LEN - readADCDMAIdx;
        }
    
        //UART_PRINT("diff=[%d]\n\r", diff);
        if(diff >= 2)
            return TRUE;
    
        return FALSE;
    }
    
    unsigned short *readGADCDMABuffer(void)
    {
        unsigned short *p = NULL; //default
        int idx;
    
        idx = readADCDMAIdx;
        if(gADCDMABuffer[idx].used == TRUE && canReadDMABuffer())
        {
            //UART_PRINT("readADCDMAIdx=[%d]\n\r", idx);
            p = gADCDMABuffer[idx].buf;
        }
    
        return p;
    }
    
    void writeGADCDMABufferDone(void)
    {
        int idx;
    
        idx = writeADCDMAIdx;
        gADCDMABuffer[idx].used = TRUE;
        addWriteADCDMAIdx();
    
    }
    
    void readGADCDMABufferDone(void)
    {
        int idx;
    
        idx = readADCDMAIdx;
        gADCDMABuffer[idx].used = FALSE;
        addReadADCDMAIdx();
    }
    
    #ifdef DMABUFFER2
    void addReadADCDMASendIdx(void)
    {
        readADCDMASendIdx = (readADCDMASendIdx + 1) % MAX_ADC_DMA_LEN;
    }
    
    void addWriteADCDMASendIdx(void)
    {
        writeADCDMASendIdx = (writeADCDMASendIdx + 1) % MAX_ADC_DMA_LEN;
    }
    
    bool addBufIdx(int add)
    {
        int diff;
        bool ret = FALSE;
    
        diff = (gBufIdx + add) - ADC_LEN;
        if(diff >= 0)
            ret = TRUE;
    
        gBufIdx = (gBufIdx + add) % ADC_LEN;
    
        return ret;
    }
    
    unsigned short *mallocGADCDMABufferSend(void)
    {
        unsigned short *p = NULL; //default write into drop buffer
        int idx;
    
        idx = writeADCDMASendIdx;
        if(gADCDMABufferSend[idx].used == FALSE)
        {
            //UART_PRINT("writeADCDMASendIdx=[%d]\n\r", idx);
            p = gADCDMABufferSend[idx].buf;
        }
        else
        {
            //UART_PRINT("gADCDMABufferSend full=[%d] error!\n",idx);
            dmaDropSendCount++;
        }
    
        return p;
    }
    
    unsigned short *readGADCDMABufferSend(void)
    {
        unsigned short *p = NULL; //default
        int idx;
    
        idx = readADCDMASendIdx;
        if(gADCDMABufferSend[idx].used == TRUE)
        {
            //UART_PRINT("readADCDMASendIdx=[%d]\n\r", idx);
            p = gADCDMABufferSend[idx].buf;
        }
    
        return p;
    }
    
    void writeGADCDMABufferSendDone(void)
    {
        int idx;
    
        idx = writeADCDMASendIdx;
        gADCDMABufferSend[idx].used = TRUE;
        addWriteADCDMASendIdx();
    
    }
    
    void readGADCDMABufferSendDone(void)
    {
        int idx;
    
        idx = readADCDMASendIdx;
        gADCDMABufferSend[idx].used = FALSE;
        addReadADCDMASendIdx();
    }
    
    void ADCDataCopy(void)
    {
        int i = 0, totalCnt, skipCnt = 0, pkg, oneCnt;
        unsigned short *p, *pBuf;
    
        totalCnt = skipCnt = 62500 / gRxTime.vibrationRate;
        if(skipCnt == 0)
        {
            UART_PRINT("totalCnt=0 error,vibrationRate:%d\n\r", gRxTime.vibrationRate);
            totalCnt = skipCnt = 1;
        }
        pkg = totalCnt;
    
        while(pkg > 0)
        {
            if((p = readGADCDMABuffer()) != NULL) //取一包数据
            {
                pBuf = mallocGADCDMABufferSend(); //分配目标缓存
                if(pBuf == NULL)
                {
                    UART_PRINT("pBuf is NULL 11, break\n\r");
                    break;
                }
    
                if(totalCnt == 1) //复制一整包数据,for 62.5K
                {
    
                    memcpy((char *)(pBuf + 2), (char *)(p + 2), ADC_LEN * 2);
                    UART_PRINT("total copy:[%d,%d]\n\r", totalCnt, gRxTime.vibrationRate);
                    start = 2;
                    gBufIdx = 0;
                    remainCnt = 0;
                    writeGADCDMABufferSendDone();
                }
                else
                {
    #if 0
                    start = totalCnt - remainCnt + 2; //开始位置
                    if(start < 2)
                    {
                        UART_PRINT("start error:[%d,%d,%d]\n\r", start, totalCnt, remainCnt);
                        start = 2;
                    }
    #endif
                    oneCnt = 0;
                    for(i = start; i < (ADC_LEN + 2); i += totalCnt)
                    {
                        pBuf[gBufIdx + 2] = p[i]; //取数
                        oneCnt++;
                        if(addBufIdx(1))
                        {
                            UART_PRINT("gBufIdx is reset, remainCnt=[%d,%d,%d]-[%d,%d]\n\r", remainCnt, start, totalCnt, gRxTime.vibrationRate, i);
                            writeGADCDMABufferSendDone(); //目标缓存已满
                            if((i + totalCnt) < (ADC_LEN + 2)) //源缓存还有数据可取
                            {
                                pBuf = mallocGADCDMABufferSend();   //取下一个目标缓存
                                if(pBuf == NULL)
                                {
                                    UART_PRINT("pBuf is NULL 22, break\n\r");
                                    break;
                                }
                            }
                        }
                    }
                    remainCnt = ADC_LEN + 1 - (i - totalCnt); //剩余点数
                    start = (i - 2) % ADC_LEN + 2; //开始位置
                    UART_PRINT("pkg info=%d,[%d,%d,%d],%d-[%d,%d]-%d\n\r", totalCnt - pkg + 1, start, i - totalCnt, remainCnt, totalCnt, gRxTime.vibrationRate, i, oneCnt);
                }
                readGADCDMABufferDone();
            }
            pkg--;
        }
    }
    #endif
    
    //*****************************************************************************
    //
    //! Setup a uDMA transfer.
    //!
    //! This function will perform all the steps necessary to set up a DMA transfer.
    //! in burst mode.
    //! \return None.
    //
    //*****************************************************************************
    void
    UDMASetupTransfer(unsigned long ulChannel, unsigned long ulMode,
                      unsigned long ulItemCount,
                      unsigned long ulItemSize, unsigned long ulArbSize,
                      void *pvSrcBuf, unsigned long ulSrcInc,
                      void *pvDstBuf, unsigned long ulDstInc)
    {
        MAP_uDMAChannelAssign(ulChannel);
    
        //
        // Set up the transfer.
        //
        MAP_uDMAChannelControlSet(ulChannel,
                                  ulItemSize | ulSrcInc | ulDstInc | ulArbSize);
    
        MAP_uDMAChannelTransferSet(ulChannel, ulMode,
                                   pvSrcBuf, pvDstBuf, ulItemCount);
    
        //
        // Set burst mode
        //
        //MAP_uDMAChannelAttributeEnable(ulChannel, UDMA_ATTR_USEBURST);
    
        //
        // Enable the udma channel.
        //
        MAP_uDMAChannelEnable(ulChannel);
    
    }
    
    void copyDma(void)
    {
        unsigned short *pDataDumpBuff = NULL;
        unsigned short *p = mallocGADCDMABuffer();
        unsigned int key;
        unsigned int ulChannelStructIndex, ulMode, ulControl;
        tDMAControlTable *pControlTable;
    
        //
        // Check the DMA control table to see if the ping-pong "A" transfer is
        // complete.  The "A" transfer uses receive buffer "A", and the primary
        // control structure.
        //
        ulMode = MAP_uDMAChannelModeGet(UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT);
        //
        // If the primary control structure indicates stop, that means the "A"
        // receive buffer is done.  The uDMA controller should still be receiving
        // data into the "B" buffer.
        //
        if(ulMode == UDMA_MODE_STOP)
        {
            ulChannelStructIndex = UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT;
            pDataDumpBuff = &(uShADCDMABufferPing[0]);
        }
        else
        {
            //
            // Check the DMA control table to see if the ping-pong "A" transfer is
            // complete.  The "A" transfer uses receive buffer "A", and the primary
            // control structure.
            //
            ulMode = MAP_uDMAChannelModeGet(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT);
            //
            // If the primary control structure indicates stop, that means the "A"
            // receive buffer is done.  The uDMA controller should still be receiving
            // data into the "B" buffer.
            //
            if(ulMode == UDMA_MODE_STOP)
            {
                ulChannelStructIndex = UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT;
                pDataDumpBuff = &(uShADCDMABufferPong[0]);
            }
        }
    
        if(pDataDumpBuff != NULL)
        {
            /* A lock is needed because we are accessing shared uDMA registers.*/
            key = HwiP_disable();
    
            memcpy(p, pDataDumpBuff, ADC_DMA_BUFFERSIZE - 3);
    
            if(uShADCDMABufferNull != p)
                writeGADCDMABufferDone();
    
            HwiP_restore(key);
    
            // Set up the next transfer for the "A" buffer, using the primary
            // control structure.  When the ongoing receive into the "B" buffer is
            // done, the uDMA controller will switch back to this one.
            //
            ulChannelStructIndex &= 0x3f;
            //
            // Get the base address of the control table.
            //
            pControlTable = (tDMAControlTable *)HWREG(UDMA_BASE + UDMA_O_CTLBASE);
            //
            // Get the current control word value and mask off the mode and size
            // fields.
            //
            ulControl = (pControlTable[ulChannelStructIndex].ulControl &
                         ~(UDMA_CHCTL_XFERSIZE_M | UDMA_CHCTL_XFERMODE_M));
    
            //
            // Set the transfer size and mode in the control word (but don't write the
            // control word yet as it could kick off a transfer).
            //
            ulControl |= UDMA_MODE_PINGPONG | ((ADC_DMA_BUFFERSIZE - 3 - 1) << 4);
    
            //
            // Write the new control word value.
            //
            pControlTable[ulChannelStructIndex].ulControl = ulControl;
        }
    }
    
    void ReloadDma(void)
    {
        static uint8_t sw = 0;
        unsigned short *p = mallocGADCDMABuffer();
        unsigned int               key;
    
        /* Clear ALT SELECT Attribute */
        //MAP_uDMAChannelAttributeDisable(UDMA_CH15_ADC_CH1,UDMA_ATTR_ALTSELECT);
    
        /* A lock is needed because we are accessing shared uDMA registers.*/
        key = HwiP_disable();
    
        if((sw++ & 0x01) == 0)
        {
    #if 0
            MAP_uDMAChannelControlSet(UDMA_CH15_ADC_CH1, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1 | UDMA_MODE_PINGPONG);
            //MAP_uDMAChannelAttributeEnable(UDMA_CH15_ADC_CH1,UDMA_ATTR_USEBURST);
            MAP_uDMAChannelTransferSet(UDMA_CH15_ADC_CH1, UDMA_MODE_PINGPONG, (void*)(ADC_BASE + ADC_O_channel2FIFODATA),
                                       &p[2], ADC_DMA_BUFFERSIZE - 3); //ping
            MAP_uDMAChannelEnable(UDMA_CH15_ADC_CH1);
    #else
            UDMASetupTransfer(UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
                              ADC_DMA_BUFFERSIZE - 3,
                              UDMA_SIZE_16, UDMA_ARB_1,
                              (void *)(ADC_BASE + ADC_O_channel2FIFODATA), UDMA_SRC_INC_NONE,
                              (void *) & (p[0]), UDMA_DST_INC_16);
    #endif
        }
        else
        {
    #if 0
            MAP_uDMAChannelControlSet(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1 | UDMA_MODE_PINGPONG);
            //MAP_uDMAChannelAttributeEnable(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_ATTR_USEBURST);
            MAP_uDMAChannelTransferSet(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void*)(ADC_BASE + ADC_O_channel2FIFODATA),
                                       &p[2], ADC_DMA_BUFFERSIZE - 3); //pong
            MAP_uDMAChannelEnable(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT);
    #else
            UDMASetupTransfer(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG,
                              ADC_DMA_BUFFERSIZE - 3,
                              UDMA_SIZE_16, UDMA_ARB_1,
                              (void *)(ADC_BASE + ADC_O_channel2FIFODATA), UDMA_SRC_INC_NONE,
                              (void *) & (p[0]), UDMA_DST_INC_16);
    #endif
    
        }
        //MAP_uDMAChannelEnable(UDMA_CH15_ADC_CH1);
        //MAP_uDMAEnable();
    
        if(uShADCDMABufferNull != p)
            writeGADCDMABufferDone();
    
        HwiP_restore(key);
    
    #if 0
        if(!SwiP_inISR())
            SwiP_post(swi0);
    #endif
    }
    
    void vMyOwnDMAInit(void)
    {
    //    UDMACC32XX_init();
    //    udma = UDMACC32XX_open();
    
        //uDMADisable();
        //uDMAChannelAssign(UDMA_CH15_ADC_CH1);
    #if 1
        //ping
        UDMASetupTransfer(UDMA_CH15_ADC_CH1 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG,
                          ADC_DMA_BUFFERSIZE - 3,
                          UDMA_SIZE_16, UDMA_ARB_1,
                          (void *)(ADC_BASE + ADC_O_channel2FIFODATA), UDMA_SRC_INC_NONE,
                          (void *) & (uShADCDMABufferPing[0]), UDMA_DST_INC_16);
        //pong
        UDMASetupTransfer(UDMA_CH15_ADC_CH1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG,
                          ADC_DMA_BUFFERSIZE - 3,
                          UDMA_SIZE_16, UDMA_ARB_1,
                          (void *)(ADC_BASE + ADC_O_channel2FIFODATA), UDMA_SRC_INC_NONE,
                          (void *) & (uShADCDMABufferPong[0]), UDMA_DST_INC_16);
    #else
    	ReloadDma();
    #endif
        //uDMAChannelEnable(UDMA_CH15_ADC_CH1);
        //uDMAEnable();
    }
    
    void vMyOwnADCInit(void)
    {
        //unsigned long das=0;
        //ADC_Params adcParams;
    //    ADC_Params_init(&adcParams);
    //    adc_ch2=ADC_open(2,&adcParams);//P58
        initGADCDMABuffer();
        //swi_create();
    
        ADCDisable(ADC_BASE);
        //disable     //clear
        vMyOwnDMAInit();
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_OVERFLOW);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_UNDERFLOW);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_EMPTY);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_FIFO_FULL);
    
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_OVERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_UNDERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_EMPTY);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_FULL);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    
        //enable
        ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCChannelEnable(ADC_BASE, ADC_CH_1);
    
        // Set the priority
        IntPrioritySet(ADC_CH_1, INT_PRIORITY_LVL_2);
        IntPendClear(ADC_CH_1);
        ADCIntRegister(ADC_BASE, ADC_CH_1, ADCIntHandler);
        ADCDMAEnable(ADC_BASE, ADC_CH_1);
    
        // Enable ADC
        //ADCTimerConfig(ADC_BASE, 2 ^ 17);
        //ADCTimerEnable(ADC_BASE);
        ADCEnable(ADC_BASE);
    
    //    Report("Irq 1st - %lx \n",ADCIntStatus(ADC_BASE,ADC_CH_1));
    //    //while((ADC_FIFO_OVERFLOW&ADCIntStatus(ADC_BASE,ADC_CH_1)) != ADC_FIFO_OVERFLOW)
    //    {
    //        Report("Irq2 st - %lx \n",ADCIntStatus(ADC_BASE,ADC_CH_1));
    //    }
    //    Report("Irq 3st - %lx \n",ADCIntStatus(ADC_BASE,ADC_CH_1));
    
    #if 0
        Report("Network Terminal - %ld \n", das);
        if( ADCFIFOLvlGet(ADC_BASE, ADC_CH_1) )
        {
            das = ADCFIFORead(ADC_BASE, ADC_CH_1);
        }
        Report("Network Terminal - %ld \n", das);
        if( ADCFIFOLvlGet(ADC_BASE, ADC_CH_1) )
        {
            das = ADCFIFORead(ADC_BASE, ADC_CH_1);
        }
        Report("Network Terminal - %ld \n", das);
    #endif
    }
    
    void ADCIntHandler(void)
    {
        unsigned long status = 0;
        
    #if 0
        while( ADCFIFOLvlGet(ADC_BASE, ADC_CH_1) )
        {
            das = ADCFIFORead(ADC_BASE, ADC_CH_1);
            i++;
        }
    #endif
    
        status = ADCIntStatus(ADC_BASE, ADC_CH_1);
        UART_PRINT("ADCIntStatus=[%d]-%d,%d\n\r", status, status & ADC_FIFO_FULL, status & ADC_DMA_DONE);
    	#if 0
        if(status & ADC_FIFO_FULL) //ADC_FIFO_FULL
        {
    		//copyDma();
            ReloadDma();
        }
    	#endif
    	copyDma();
    
        //uShADCDMABuffer[3] =0;s
        //Report("Irq 3st - %lx \n",ADCIntStatus(ADC_BASE,ADC_CH_1));
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    #if 1
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_OVERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_UNDERFLOW);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_EMPTY);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_FIFO_FULL);
    #endif
    }
    
    void restart_dma(void)
    {
        ADCEnable(ADC_BASE);
        ADCIntEnable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    }
    
    void stop_dma(void)
    {
        ADCDisable(ADC_BASE);
        ADCIntDisable(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
        ADCIntClear(ADC_BASE, ADC_CH_1, ADC_DMA_DONE);
    }
    
    void adc_dma()
    {
        vMyOwnDmaAdcInit();
    }
    
    ///*****************adc pin59999999999***************/
    
    //
    //void vMyOwnDmaAdcInit()
    //{
    //   vMyOwnDMAInit();
    //   vMyOwnADCInit();
    //}
    //
    //void vMyOwnDMAInit(void)
    //{
    //    UDMACC32XX_init();
    //    udma = UDMACC32XX_open();
    //    uDMAChannelAssign(UDMA_CH16_ADC_CH2);
    //    uDMAChannelControlSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT, UDMA_SIZE_16|UDMA_SRC_INC_NONE|UDMA_DST_INC_16|UDMA_ARB_1);
    //    uDMAChannelTransferSet(UDMA_CH16_ADC_CH2|UDMA_PRI_SELECT,UDMA_MODE_BASIC,(void*)(ADC_BASE+ADC_O_channel4FIFODATA),(void *) &uShADCDMABuffer[2], ADC_DMA_BUFFERSIZE-3);
    //
    //    uDMAChannelEnable(UDMA_CH16_ADC_CH2);
    //}
    //
    //void vMyOwnADCInit(void)
    //{
    //    ADC_Params adcParams;
    //    ADC_Params_init(&adcParams);
    //    adc_ch2=ADC_open(0,&adcParams);//P59
    //
    //    ADCDMAEnable(ADC_BASE, ADC_CH_2);
    //    ADCIntRegister(ADC_BASE, ADC_CH_2,ADCIntHandler);
    //    ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
    //    ADCIntEnable(ADC_BASE, ADC_CH_2,ADC_DMA_DONE);
    //    ADCChannelEnable(ADC_BASE, ADC_CH_2);
    //    ADCEnable(ADC_BASE);
    //}
    //
    //void ADCIntHandler(void)
    //{
    //  unsigned int i;
    //  // Turn off ADC and clear IRQ-Bit
    //  ADCDisable(ADC_BASE);
    //  ADCIntDisable(ADC_BASE, ADC_CH_2,ADC_DMA_DONE);
    //  ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
    //
    //  UDMACC32XX_close(udma);
    //
    //  for (i=2; i< (ADC_LEN + 2); i++)//鎼村繐褰挎禒锟?瀵拷婵绱濋崜宥勮⒈娑擃亜銇囩€涙濡稉鍝勬姎婢跺瓨鐖g拋鏉挎嫲閸栧懎绨崣锟?
    //  {
    //      uShADCDMABuffer[i] >>= 2;
    //      uShADCDMABuffer[i] &= 0x0FFF;
    //  }
    //
    //    dma_flag = 1;
    //}
    //
    //void restart_dma(void)
    //{
    //    ADCEnable(ADC_BASE);
    //    ADCIntEnable(ADC_BASE, ADC_CH_2,ADC_DMA_DONE);
    //}
    //
    //void stop_dma(void)
    //{
    //    ADCDisable(ADC_BASE);
    //    ADCIntDisable(ADC_BASE, ADC_CH_2,ADC_DMA_DONE);
    //    ADCIntClear(ADC_BASE, ADC_CH_2, ADC_DMA_DONE);
    //}
    //
    //void adc_dma()
    //{
    //
    //vMyOwnDmaAdcInit();
    //
    //}
    
    
    
    

  • Hi Ken,

    Thanks for providing your code. I'm still reviewing it, but I have a couple of questions about your setup. Are you using a launchpad EVM, or are you using your own hardware? Also, have you tried using another ADC input, instead of the one you're currently using? I see you have some commented-out code that suggests you may have, but I wanted to confirm that you saw the same results with the other ADC input.

    Regards,

    Michael

  • Hi Michael:

    I am using my own hardware instead of launchpad EVM.

    The other two ADCs are already in use. One is to sample battery voltage and the other is to sample temperature data. Both of them are directly sampled by ADC instead of DMA, so the two samples are sampled. The data is right.

    This should be the same as the result obtained by which ADC sampling is used

  • Hi Ken,

    It's interesting that the other two ADC function fine. If I recall correctly, at the start of the thread you were not using DMA, but still encountered glitches in the data from time to time. Was this behavior that you saw with the other ADCs?

    I wonder if checking those ADCs and seeing if they also demonstrate the same behavior might help our debug. Is it possible to use one of those other ADCs, and check to see if they encounter the same glitching if they were used to sample the square wave?

    Regards,

    Michael