5. Code Overview

This section provides the code blocks needed to successfully execute this tutorial.

5.1. Header Files

In main.c file, add the following header files:

#include "ad_gpadc.h"
#include "platform_devices.h"

5.2. Function Prototype

In main.c file, add the following function prototype:

static void user_gpadc_reader(const ad_gpadc_controller_conf_t *dev);

#if USER_GPADC_SYNC_EN==0
    static void gpadc_user_cb(void *user_data, int value);
#endif

5.3. Macro Definitions

In config/custom_config_xxx.h file, add the following macro definitions to enable the GPADC related API:

/*******************************************************
 * Peripheral specific config
 */
#define dg_configGPADC_ADAPTER                  (1)

In main.c file, add the gpadc operation mode macro and os event parameter:

#define USER_GPADC_SYNC_EN 1
#if USER_GPADC_SYNC_EN == 0
__RETAINED static OS_EVENT signal_adc_async;
#endif

5.4. Hardware Initialization

In main.c file, replace the prvSetupHardware() routine with the following codes.

static void prvSetupHardware( void )
{

     /* Init hardware */
     pm_system_init(periph_init);
     /* Initialize gpadc IO configuration*/
     ad_gpadc_io_config(dev_GPADC.id, dev_GPADC.io, AD_IO_CONF_OFF);

}

In platform_devices.c file, add IO bus as well as driver configurations for the GPADC device(s) used. These settings will be applied when an application task attempts to interact with the target analog device.

#include <ad_gpadc.h>
#include "platform_devices.h"

/*
* PLATFORM PERIPHERALS GPIO CONFIGURATION
*****************************************************************************************
*/

#if dg_configGPADC_ADAPTER || dg_configUSE_HW_GPADC


/* GPADC IO */
const ad_gpadc_io_conf_t bus_GPADC = {
        .input0 = {
                .port = HW_GPIO_PORT_1,
                .pin  = HW_GPIO_PIN_0,
                .on   = {HW_GPIO_MODE_INPUT, HW_GPIO_FUNC_ADC,  true},
                .off  = {HW_GPIO_MODE_INPUT, HW_GPIO_FUNC_GPIO, true}
        },
        .input1 = {
                .port = HW_GPIO_PORT_NONE,
                .pin  = HW_GPIO_PIN_NONE,
                .on   = {HW_GPIO_MODE_INPUT, HW_GPIO_FUNC_GPIO, true},
                .off  = {HW_GPIO_MODE_INPUT, HW_GPIO_FUNC_GPIO, true}
        },
};

/* GPADC driver configurations */
const ad_gpadc_driver_conf_t drv_GPADC = {
        .input_mode             = HW_GPADC_INPUT_MODE_SINGLE_ENDED,
        .positive               = HW_GPADC_INP_P1_0,
//      .negative               = HW_GPADC_INP_VSSA,
        .sample_time            = 5,
        .continuous             = false,
        .interval               = 0,
        .input_attenuator       = HW_GPADC_INPUT_VOLTAGE_UP_TO_3V6,
        .chopping               = false, /* Useful for DC and slowly changing signals */
        .oversampling           = HW_GPADC_OVERSAMPLING_1_SAMPLE,
};


/*  External device/module configurations */
const ad_gpadc_controller_conf_t dev_GPADC = {
        .id  = HW_GPADC_1, /* GPADC controller instance */
        .io  = &bus_GPADC,
        .drv = &drv_GPADC
};

#endif /* dg_configGPADC_ADAPTER || dg_configUSE_HW_GPADC */

In platform_devices.h file, add the following definitions:

#include <ad_gpadc.h>

#ifdef __cplusplus
extern "C" {
#endif

#if dg_configGPADC_ADAPTER || dg_configUSE_HW_GPADC

/**
* \brief GPADC device handle
*/
/* List of devices */
extern const ad_gpadc_controller_conf_t dev_GPADC;

#endif /* dg_configGPADC_ADAPTER || dg_configUSE_HW_GPADC */

#ifdef __cplusplus
}
#endif

5.5. Task configuration

In static OS_TASK_FUNCTION(system_init, pvParameters), modify the stack size of the Template task to 1024 . And create the signal_adc_async os signal OS_EVENT_CREATE(signal_adc_async); .

static OS_TASK_FUNCTION(system_init, pvParameters)
{
        OS_TASK task_h = NULL;

#if defined CONFIG_RETARGET
        extern void retarget_init(void);
#endif

        cm_sys_clk_init(sysclk_XTAL32M);

        cm_apb_set_clock_divider(apb_div1);
        cm_ahb_set_clock_divider(ahb_div1);
        cm_lp_clk_init();

        /* Prepare the hardware to run this demo. */
        prvSetupHardware();

#if defined CONFIG_RETARGET
        retarget_init();
#endif

#if USER_GPADC_SYNC_EN == 0
        OS_EVENT_CREATE(signal_adc_async);
#endif

        pm_set_wakeup_mode(true);
        /* Set the desired sleep mode. */
        pm_sleep_mode_set(pm_mode_extended_sleep);


        /* Start main task here (text menu available via UART1 to control application) */
        OS_TASK_CREATE( "Template",            /* The text name assigned to the task, for
                                                        debug only; not used by the kernel. */
                        prvTemplateTask,                /* The function that implements the task. */
                        NULL,                           /* The parameter passed to the task. */
                        1024,                                                   /* The number of bytes to allocate to the
                                                        stack of the task. */
                        mainTEMPLATE_TASK_PRIORITY,     /* The priority assigned to the task. */
                        task_h );                       /* The task handle */
        OS_ASSERT(task_h);

        /* the work of the SysInit task is done */
        OS_TASK_DELETE( xHandle );
}

5.6. Operation Code for GPADC Measurements

After main(), add the following code used for performing GPADC measurements from an analog pin.

#if USER_GPADC_SYNC_EN==0

static void gpadc_user_cb(void *user_data, int value)
{
        /* Signal the [prvGPADCTask_POT] task that time for resuming has elapsed. */
        OS_EVENT_SIGNAL_FROM_ISR(signal_adc_async);
}
#endif

/* Perform a GPADC read operation */
static void user_gpadc_reader(const ad_gpadc_controller_conf_t *dev)
{
        printf("\n\r***GPADC Demonstration Example***\n\r");
        int error_code;
        uint16_t adc_raw_val;

        /* Open the GPADC device */
        ad_gpadc_handle_t dev_h = ad_gpadc_open(dev);

#if USER_GPADC_SYNC_EN == 1
/*
        * Perform a synchronous GPADC read operation, that is, the task
        * is blocking waiting for the operation to finish.
        */
        error_code = ad_gpadc_read_nof_conv(dev_h, 1, &adc_raw_val);

#else
/*
        * Perform an asynchronous GPADC read operation, that is, the task does not
        * block waiting for the transaction to finish. Upon operation completion
        * callback function is triggered indicating the completion of the GPADC operation
        */
        error_code = ad_gpadc_read_nof_conv_async(dev_h, 1, &adc_raw_val, gpadc_user_cb, &dev_h);
        /*
        * In the meantime and while GPADC operations are performed in the background,
        * application task can proceed to other operations/calculation. It is essential
        * that the new operations do not involve GPADC operations on the already
        * occupied block!!!
        */

        /*
        * Make sure that the current GPADC operation has finished,
        * blocking here forever.
        */
        OS_EVENT_WAIT(signal_adc_async, OS_EVENT_FOREVER);

#endif
        if(error_code){
                printf("\n\rUnsuccessful GPADC read operation with error code: %d \n\r",error_code);
        }

        /* Close the GPADC device */
        ad_gpadc_close(dev_h, true);

        /* Convert the raw ADC value to mV */
        uint16_t max_value = ad_gpadc_get_source_max(dev_GPADC.drv);
        uint16_t corrected = (int32_t) hw_gpadc_apply_correction(dev_GPADC.drv, adc_raw_val);
        // 10bits result left aligned converted to raw data right aligned
        corrected = (corrected>>6)&max_value;

        printf("\n\rADC value (raw): %d \n\r",corrected);
        printf("\n\rDetected voltage: %d mV\n\r",(corrected*3600/max_value));

        fflush(stdout);
}

In static OS_TASK_FUNCTION(prvTemplateTask, pvParameters) function, add user_gpadc_reader() function.

/**
* @brief Template task increases a counter every mainCOUNTER_FREQUENCY_MS ms
*/
static OS_TASK_FUNCTION(prvTemplateTask, pvParameters)
{
        OS_TICK_TIME xNextWakeTime;
        static uint32_t test_counter=0;

        /* Initialise xNextWakeTime - this only needs to be done once. */
        xNextWakeTime = OS_GET_TICK_COUNT();


        for ( ;; ) {
                /* Place this task in the blocked state until it is time to run again.
                The block time is specified in ticks, the constant used converts ticks
                to ms.  While in the Blocked state this task will not consume any CPU
                time. */
                xNextWakeTime += mainCOUNTER_FREQUENCY_MS;
                OS_DELAY_UNTIL(xNextWakeTime);
                test_counter++;

                if (test_counter % (1000 / OS_TICKS_2_MS(mainCOUNTER_FREQUENCY_MS)) == 0) {
                        printf("#");
                        fflush(stdout);
                        // start gpadc conversion
                        user_gpadc_reader(&dev_GPADC);
                }
        }
}