Analog Devices / Mbed OS EVAL-AD5592R

Dependencies:   adi_console_menu platform_drivers

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ad5592r_console_app.c Source File

ad5592r_console_app.c

Go to the documentation of this file.
00001 /*!
00002  *****************************************************************************
00003  *   @file    ad5592r_console_app.c
00004  *   @brief   AD5592R console application interfaces
00005  *   @details This file is specific to ad5592r and ad5593r console menu application handle.
00006  *            The functions defined in this file performs the action
00007  *            based on user selected console menu.
00008  *
00009  -----------------------------------------------------------------------------
00010  Copyright (c) 2020-2021 Analog Devices, Inc.
00011  All rights reserved.
00012 
00013  This software is proprietary to Analog Devices, Inc. and its licensors.
00014  By using this software you agree to the terms of the associated
00015  Analog Devices Software License Agreement.
00016 *****************************************************************************/
00017 
00018 /******************************************************************************/
00019 /***************************** Include Files **********************************/
00020 /******************************************************************************/
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <stdbool.h>
00024 
00025 #include "app_config.h"
00026 #include "ad5592r_configs.h"
00027 
00028 #include "platform_support.h"
00029 #include "error.h"
00030 #include "gpio.h"
00031 #include "i2c.h"
00032 #include "spi.h"
00033 #include "spi_extra.h"
00034 #include "i2c_extra.h"
00035 
00036 #include "ad5592r-base.h"
00037 #include "ad5592r.h"
00038 #include "ad5593r.h"
00039 
00040 #include "ad5592r_console_app.h"
00041 
00042 /******************************************************************************/
00043 /************************* Macros & Constant Definitions **********************/
00044 /******************************************************************************/
00045 // vref_voltage can be defined as EXTERNAL_VREF_VOLTAGE or INTERNAL_VREF_VOLTAGE
00046 // Change EXTERNAL_VREF_VOLTAGE if using supply other than 2.5V
00047 #define EXTERNAL_VREF_VOLTAGE           2.5
00048 float vref_voltage = EXTERNAL_VREF_VOLTAGE;
00049 
00050 #define AD5592R_CHANNEL(N)          (N)
00051 #define AD5592R_REG_ADC_SEQ_INCL(x)     BIT(x)
00052 #define AD5592R_REG_PD_CHANNEL(x)       BIT(x)
00053 #define AD5592R_GPIO(x)             BIT(x)
00054 
00055 #define TEMP_SAMPLE_SIZE            5
00056 #define CLEAR_CHANNEL_SELECTION         1000
00057 #define MDELAY_TO_DISPLAY_INSTRUCTION       1000
00058 #define TEMPERATURE_READBACK_CHANNEL        8
00059 
00060 #define MAX_ADC_CODE                4095.0
00061 #define ADC_GAIN_LOW_CONVERSION_VALUE       2.654
00062 #define ADC_GAIN_HIGH_CONVERSION_VALUE      1.327
00063 
00064 /* Private Variables */
00065 static struct ad5592r_dev sAd5592r_dev;
00066 
00067 static const char *mode_names[] = {
00068     "Unused",
00069     "ADC\t",
00070     "DAC\t",
00071     "ADC+DAC",
00072     "GPI\t",
00073     "GPO\t",
00074 };
00075 static const char *offstate_names[] = {
00076     "Pulldown",
00077     "Low\t",
00078     "High\t",
00079     "Tristate"
00080 };
00081 static bool active_channel_selections[NUM_CHANNELS] = {
00082     false,
00083     false,
00084     false,
00085     false,
00086     false,
00087     false,
00088     false,
00089     false
00090 };
00091 
00092 static uint16_t adc_channels_in_seq = AD5592R_REG_ADC_SEQ_TEMP_READBACK;
00093 
00094 /******************************************************************************/
00095 /***************************** Function Declarations **************************/
00096 /******************************************************************************/
00097 static int32_t do_software_reset(uint32_t id);
00098 static int32_t do_read_die_temp(uint32_t id);
00099 static float die_temp_calculation(uint16_t adc_temp_code, bool adc_gain);
00100 static void do_set_channel_modes(void);
00101 static int32_t do_toggle_channel_selection(uint32_t channel);
00102 static int32_t do_mode_selection(uint32_t mode);
00103 static int32_t do_reset_channel_modes(uint32_t id);
00104 static int32_t do_offstate_selection(uint32_t mode);
00105 static int32_t do_channel_7_adc_indicator(uint32_t id);
00106 static int32_t do_general_settings_toggle(uint32_t reg_bit_id);
00107 static int32_t do_write_dac_value(uint32_t id);
00108 static int32_t do_dac_input_reg_to_output(uint32_t id);
00109 static int32_t do_toggle_ldac_mode(uint32_t id);
00110 static int32_t do_toggle_dac_powerdown(uint32_t id);
00111 static int32_t do_toggle_incl_in_seq(uint32_t id);
00112 static int32_t do_read_adc_sequence(uint32_t id);
00113 
00114 extern console_menu power_down_pin_select_menu;
00115 extern console_menu config_channels_menu;
00116 extern console_menu general_settings_menu;
00117 extern console_menu dac_menu;
00118 extern console_menu gpio_menu;
00119 extern console_menu adc_menu;
00120 
00121 /******************************************************************************/
00122 /***************************** Function Definitions ***************************/
00123 /******************************************************************************/
00124 
00125 /*!
00126  * @brief       Initialize AD5592/3R. ACTIVE_DEVICE defined in app_config.h
00127  *@details      The device initialization varies depending on what ACTIVE_DEVICE is defined.
00128  *          Device is reset and default register map values written.
00129  *          SPI or I2C initialization occurs.
00130  * @return      SUCCESS (0), FAILURE (negative)
00131  */
00132 int32_t ad5592r_app_initalization(void)
00133 {
00134     memcpy(&sAd5592r_dev, &ad5592r_dev_user, sizeof(ad5592r_dev_user));
00135     int32_t status;
00136     if (ACTIVE_DEVICE == ID_AD5593R) {
00137         sAd5592r_dev.i2c = &i2c_user_descr;
00138         i2c_init(&sAd5592r_dev.i2c, &i2c_user_params);
00139         status = ad5593r_init(&sAd5592r_dev, &ad5592r_user_param);
00140     } else {
00141         sAd5592r_dev.spi = &spi_user_descr;
00142         spi_init(&sAd5592r_dev.spi, &spi_user_params);
00143         status = ad5592r_init(&sAd5592r_dev, &ad5592r_user_param);
00144     }
00145     return status;
00146 }
00147 
00148 /*!
00149  * @brief        Performs software reset
00150  * @details Writes to the reset register. Resets sAd5592r_dev configuration using
00151  *          configuration from ad5592r_reset_config.c SPI, I2C and ops are stored
00152  *          and restored after the reset.
00153  * @return      MENU_CONTINUE
00154  */
00155 static int32_t do_software_reset(uint32_t id)
00156 {
00157     int32_t status;
00158 
00159     if ((status = ad5592r_software_reset(&sAd5592r_dev)) == SUCCESS) {
00160         // Save spi_desc field, i2c_desc and device ops settings as it is not reset
00161         spi_desc *spi_interface = sAd5592r_dev.spi;
00162         i2c_desc *i2c_interface = sAd5592r_dev.i2c;
00163         const struct ad5592r_rw_ops *dev_ops = sAd5592r_dev.ops;
00164         // Copy over the reset state of the device
00165         memcpy(&sAd5592r_dev, &ad5592r_dev_reset, sizeof(ad5592r_dev_reset));
00166 
00167         // Restore device ops
00168         sAd5592r_dev.ops = dev_ops;
00169         if (ACTIVE_DEVICE == ID_AD5592R) {
00170             // Restore the spi_desc pointer field
00171             sAd5592r_dev.spi = spi_interface;
00172             printf(EOL " --- AD5592R Software Reset Successful---" EOL);
00173         } else {
00174             // Restore the i2c_desc pointer field
00175             sAd5592r_dev.i2c = i2c_interface;
00176             printf(EOL " --- AD5593R Reset Request Successful---" EOL);
00177         }
00178     } else {
00179         printf(EOL " *** Software Reset Failure: %d ***" EOL, status);
00180         adi_press_any_key_to_continue();
00181     }
00182 
00183     adi_press_any_key_to_continue();
00184     return (MENU_CONTINUE);
00185 }
00186 
00187 /*!
00188  * @brief       Prints the temperature of the die
00189  * @details Sets the devices to perform a temperature readback.
00190  *          Performs a number of samples based on TEMP_SAMPLE_SIZE
00191  * @return      MENU_CONTINUE
00192  */
00193 static int32_t do_read_die_temp(uint32_t id)
00194 {
00195     uint16_t readback_reg[1] = { 0 };
00196     int32_t status = 0, ch_state = 0;
00197     float result = 0;
00198 
00199     ch_state = sAd5592r_dev.channel_modes[7];
00200     sAd5592r_dev.channel_modes[7] = CH_MODE_ADC;
00201     do_set_channel_modes();
00202 
00203     do {
00204 
00205         for (int8_t i = 0; i < TEMP_SAMPLE_SIZE; i++) {
00206             do {
00207                 status = sAd5592r_dev.ops->read_adc(&sAd5592r_dev,
00208                                     AD5592R_CHANNEL(8),
00209                                     readback_reg);
00210             } while (0);
00211             if (status != SUCCESS) {
00212                 // Break out of for loop if not successful
00213                 break;
00214             }
00215             result += die_temp_calculation(readback_reg[0],
00216                                (AD5592R_REG_CTRL_ADC_RANGE & sAd5592r_dev.cached_gp_ctrl));
00217         }
00218 
00219         result /= TEMP_SAMPLE_SIZE;
00220 
00221         if (status == SUCCESS) {
00222             // Print average of samples
00223             printf(EOL " --- Temperature: %.1f*C --- " EOL, result);
00224         } else {
00225             printf(EOL " *** Error reading die temperature: %d **" EOL, status);
00226             break;
00227         }
00228     } while (0);
00229 
00230     sAd5592r_dev.channel_modes[7] = ch_state;
00231     do_set_channel_modes();
00232 
00233     adi_press_any_key_to_continue();
00234     return (MENU_CONTINUE);
00235 }
00236 
00237 /*!
00238  * @brief       Calculates the die temperature
00239  * @details Based on conversion equation, die temperature is estimated
00240  * @param   adc_temp_code - data read from ADC readback frame
00241  *          adc_gain - status of adc_gain
00242  * @return      result
00243  */
00244 static float die_temp_calculation(uint16_t adc_temp_code, bool adc_gain)
00245 {
00246     float result = 0;
00247 
00248     // use different equation depending on gain
00249     if(adc_gain) {
00250         result = 25 + ((AD5592R_REG_ADC_SEQ_CODE_MSK(adc_temp_code) -
00251                 ((0.5 / (2 * vref_voltage)) * MAX_ADC_CODE)) /
00252                    (ADC_GAIN_HIGH_CONVERSION_VALUE * (2.5 / vref_voltage)));
00253     } else {
00254         result = 25 + ((AD5592R_REG_ADC_SEQ_CODE_MSK(adc_temp_code) -
00255                 ((0.5 / vref_voltage) * MAX_ADC_CODE)) /
00256                    (ADC_GAIN_LOW_CONVERSION_VALUE * (2.5 / vref_voltage)));
00257     }
00258     return result;
00259 }
00260 
00261 /*!
00262  * @brief       Set channel modes
00263  *
00264  *@details      The channels modes are set by passing the altered device
00265  *          struct into the ad5592r_set_channel_modes function. There the channels are
00266  *          set to desired modes.
00267  */
00268 static void do_set_channel_modes(void)
00269 {
00270     int32_t status;
00271     if ((status =  ad5592r_set_channel_modes(&sAd5592r_dev)) != SUCCESS) {
00272         printf(EOL "Error configuring Channels (%d)" EOL, status);
00273         adi_press_any_key_to_continue();
00274     }
00275 }
00276 
00277 /*!
00278  * @brief       Toggle channels currently selected
00279  * @details The channels the user has currently selected are set here.
00280  *          These are the channels that will be altered by mode or offstate selection
00281  * @param   channel - A channel that the user wants to add to the currently selected channels
00282  * @return      (MENU_CONTINUE)
00283  */
00284 static int32_t do_toggle_channel_selection(uint32_t channel)
00285 {
00286     if (channel == CLEAR_CHANNEL_SELECTION) {
00287         for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) {
00288 
00289             active_channel_selections[i] = false;
00290         }
00291     } else {
00292         active_channel_selections[channel] = !active_channel_selections[channel];
00293     }
00294 
00295     return (MENU_CONTINUE);
00296 }
00297 
00298 /*!
00299  * @brief       Mode selection
00300  * @details The mode the users wishes to apply to the currently selected channels
00301  *          are selected here. do_set_channel_modes is called which sets the channels
00302  *          on the device.
00303  * @param   mode -The mode that the user wishes to apply to the selected channels
00304  * @return      (MENU_CONTINUE)
00305  */
00306 static int32_t do_mode_selection(uint32_t mode)
00307 {
00308     for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) {
00309         if (active_channel_selections[i] == true) {
00310             sAd5592r_dev.channel_modes[i]   = mode;
00311         }
00312     }
00313     do_set_channel_modes();
00314     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00315     return (MENU_CONTINUE);
00316 }
00317 
00318 /*!
00319  * @brief       Offstate selection
00320  * @details The offstate the users wishes to apply to the currently selected channels
00321  *      are selected here. do_set_channel_modes is called which sets the channels
00322  *      on the device.
00323  * @param   The offstate that the user wishes to apply to the selected channels
00324  * @return      (MENU_CONTINUE)
00325  */
00326 static int32_t do_offstate_selection(uint32_t mode)
00327 {
00328     for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) {
00329         if (active_channel_selections[i] == true) {
00330             sAd5592r_dev.channel_offstate[i]    = mode;
00331         }
00332     }
00333     do_set_channel_modes();
00334     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00335     return (MENU_CONTINUE);
00336 }
00337 
00338 /*!
00339  * @brief       Reset Channel Modes
00340  * @details This resets all channel modes to unused.
00341  * @return      (MENU_CONTINUE)
00342  *
00343  */
00344 static int32_t do_reset_channel_modes(uint32_t id)
00345 {
00346     ad5592r_reset_channel_modes(&sAd5592r_dev);
00347     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00348     return (MENU_CONTINUE);
00349 }
00350 
00351 /*!
00352  * @brief       Sets Channel 7 as ADC conversion indicator
00353  * @details Channel 7 is set as a GPIO and the NOT BUSY bit is set in the GPIO
00354  *          write configuration register enabling channel 7 to be used as an indicator
00355  *          when ADC conversion are occurring. Channel 7 will go LOW when a conversion
00356  *          is occurring.
00357  *          ***NOTE*** After selecting this Channel 7 will appear as GPO.
00358  *          ***NOTE*** Ensure this is the last channel to be configured in order to
00359  *                       ensure preference will no be overwritten
00360  * @return      (MENU_CONTINUE)
00361  */
00362 static int32_t do_channel_7_adc_indicator(uint32_t id)
00363 {
00364     sAd5592r_dev.channel_modes[AD5592R_CHANNEL(7)] =
00365         ((sAd5592r_dev.channel_modes[AD5592R_CHANNEL(7)] == CH_MODE_UNUSED)
00366          ? CH_MODE_GPO : CH_MODE_UNUSED);
00367     do_set_channel_modes();
00368     do_general_settings_toggle(((AD5592R_REG_GPIO_OUT_EN << 12)
00369                     | AD5592R_REG_GPIO_OUT_EN_ADC_NOT_BUSY));
00370     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00371     return (MENU_CONTINUE);
00372 }
00373 
00374 /*!
00375  * @brief       Toggle general setting
00376  * @details Setting (reg_bit) in register (reg) is toggled
00377  * @param   reg_bit_id - Combined value containing register address and bit to toggle
00378  * @return      (MENU_CONTINUE)
00379  */
00380 static int32_t do_general_settings_toggle(uint32_t reg_bit_id)
00381 {
00382     uint8_t reg = (reg_bit_id >> 12);
00383     uint16_t reg_bit = (reg_bit_id & 0xFFF), readback_reg;
00384     int32_t status;
00385 
00386     if ((status = ad5592r_base_reg_read(&sAd5592r_dev, reg,
00387                         &readback_reg)) != SUCCESS) {
00388         printf(" *** Error Reading Setting Status (%x) *** " EOL, reg);
00389         adi_press_any_key_to_continue();
00390     } else if ((status = ad5592r_base_reg_write(&sAd5592r_dev, reg,
00391                  (reg_bit ^ readback_reg))) != SUCCESS) {
00392         printf(" *** Error  Toggling Setting (%x) *** " EOL, reg);
00393         adi_press_any_key_to_continue();
00394     }
00395 
00396     if (reg == AD5592R_REG_PD && reg_bit == AD5592R_REG_PD_EN_REF) {
00397         if ((AD5592R_REG_PD_EN_REF & (reg_bit ^ readback_reg))) {
00398             vref_voltage = INTERNAL_VREF_VOLTAGE;
00399         } else {
00400             vref_voltage = EXTERNAL_VREF_VOLTAGE;
00401         }
00402     }
00403     return (MENU_CONTINUE);
00404 }
00405 
00406 /*!
00407  * @brief      displays the general settings header
00408  */
00409 static void display_general_setting_header(void)
00410 {
00411 
00412     int32_t status = 0;
00413     uint16_t ctrl_reg_data = 0, pd_reg_data = 0;
00414 
00415     do {
00416         if ((status = ad5592r_base_reg_read(&sAd5592r_dev, AD5592R_REG_CTRL,
00417                             &ctrl_reg_data)) == SUCCESS) {
00418             sAd5592r_dev.cached_gp_ctrl = ctrl_reg_data;
00419         } else {
00420             printf(" *** Error reading register (%x) *** " EOL, AD5592R_REG_CTRL);
00421             adi_press_any_key_to_continue();
00422             break;
00423         }
00424 
00425         if ((status = ad5592r_base_reg_read(&sAd5592r_dev, AD5592R_REG_PD,
00426                             &pd_reg_data)) == SUCCESS) {
00427         } else {
00428             printf(" *** Error reading register (%x) *** " EOL, AD5592R_REG_PD);
00429             adi_press_any_key_to_continue();
00430             break;
00431         }
00432     } while(0);
00433 
00434     printf("\tSetting \tEnabled\t\tSetting \tEnabled"EOL);
00435     printf("\tEn Ref\t\t%s\t\tADC Gain\t%s"EOL,
00436            (AD5592R_REG_PD_EN_REF & pd_reg_data)?"X":"\00",
00437            (AD5592R_REG_CTRL_ADC_RANGE & ctrl_reg_data)?"X":"\00");
00438     printf("\tPC Buff\t\t%s\t\tPD All\t\t%s"EOL,
00439            (AD5592R_REG_CTRL_ADC_PC_BUFF & ctrl_reg_data)?"X":"\00",
00440            (AD5592R_REG_PD_PD_ALL & pd_reg_data) ? "X" : "\00");
00441     printf("\tBuff\t\t%s\t\tDAC Gain\t%s"EOL,
00442            (AD5592R_REG_CTRL_ADC_BUFF_EN & ctrl_reg_data)?"X":"\00",
00443            (AD5592R_REG_CTRL_DAC_RANGE & ctrl_reg_data)?"X":"\00");
00444     printf("\tLock Config\t%s\t\tWr All\t\t%s"EOL,
00445            (AD5592R_REG_CTRL_CONFIG_LOCK & ctrl_reg_data)?"X":"\00",
00446            (AD5592R_REG_CTRL_W_ALL_DACS & ctrl_reg_data)?"X":"\00");
00447 
00448 }
00449 
00450 /*!
00451  * @brief       DAC input register to DAC output
00452  * @details Writes the data from the DAC input register to the DAC output.
00453  *          The LDAC mode is returned to write data to the input register only.
00454  * @return      (MENU_CONTINUE)
00455  */
00456 static int32_t do_dac_input_reg_to_output(uint32_t id)
00457 {
00458     int32_t status;
00459     if ((status = ad5592r_base_reg_write(&sAd5592r_dev, AD5592R_REG_LDAC,
00460                          AD5592R_REG_LDAC_INPUT_REG_OUT)) != SUCCESS) {
00461         printf("*** Error setting LDAC to write to output (%d) *** ", status);
00462         adi_press_any_key_to_continue();
00463     }
00464     sAd5592r_dev.ldac_mode = AD5592R_REG_LDAC_INPUT_REG_ONLY;
00465     return (MENU_CONTINUE);
00466 }
00467 
00468 /*!
00469  * @brief       User dac code
00470  * @details Generate dac code that can be written to device from voltage provided by user
00471  * @param   user_voltage - float value provided by user for voltage value to be set
00472  * @return      dac code value
00473  */
00474 static uint16_t user_dac_code(float user_voltage)
00475 {
00476     return (uint16_t) (((user_voltage) * MAX_ADC_CODE) / vref_voltage);
00477 }
00478 
00479 /*!
00480  * @brief       Code values to voltage
00481  * @details Generate voltage based on code value
00482  * @param   code - integer value used to generate voltage value
00483  * @return      float voltage value
00484  */
00485 static float code_to_volts(int16_t code)
00486 {
00487     return ((code / MAX_ADC_CODE) * vref_voltage);
00488 }
00489 
00490 /*!
00491  * @brief       Write DAC Values
00492  * @details Write value specified by user to Channels selected by user in the DAC menu
00493  * @return      (MENU_CONTINUE)
00494  */
00495 static int32_t do_write_dac_value(uint32_t id)
00496 {
00497     int32_t status;
00498     uint16_t user_code = 0;
00499     float user_voltage = 2.5;
00500 
00501     printf(EOL "\tEnter voltage to write to selected DACs (0 - Vref) : " EOL);
00502     user_voltage = adi_get_decimal_float(5);
00503     user_code = user_dac_code(user_voltage);
00504 
00505     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00506         if (active_channel_selections[i]) {
00507             if ((status = sAd5592r_dev.ops->write_dac(&sAd5592r_dev, i,
00508                     user_code)) != SUCCESS) {
00509                 printf("*** Error writing DAC value to channel %d (%d) ***" EOL, i, status);
00510                 adi_press_any_key_to_continue();
00511             }
00512             sAd5592r_dev.cached_dac[i] = user_code;
00513         }
00514     }
00515     return (MENU_CONTINUE);
00516 }
00517 
00518 /*!
00519  * @brief       Toggle LDAC Modes
00520  * @details Toggles the LDAC mode variable between Immediate write to output
00521  *          and write values to input register
00522  * @return      (MENU_CONTINUE)
00523  */
00524 static int32_t do_toggle_ldac_mode(uint32_t id)
00525 {
00526     if (sAd5592r_dev.ldac_mode == AD5592R_REG_LDAC_INPUT_REG_ONLY) {
00527         sAd5592r_dev.ldac_mode = AD5592R_REG_LDAC_IMMEDIATE_OUT;
00528     } else {
00529         sAd5592r_dev.ldac_mode = AD5592R_REG_LDAC_INPUT_REG_ONLY;
00530     }
00531     return (MENU_CONTINUE);
00532 }
00533 
00534 /*!
00535  * @brief       Toggle DAC channels to power-down
00536  * @details Toggles DAC channels that are powered down based on user selection
00537  * @return      (MENU_CONTINUE)
00538  */
00539 static int32_t do_toggle_dac_powerdown(uint32_t id)
00540 {
00541     int32_t status;
00542     uint16_t powerdown = 0;
00543 
00544     if ((status = ad5592r_base_reg_read(&sAd5592r_dev, AD5592R_REG_PD,
00545                         &powerdown)) != SUCCESS) {
00546         printf("*** Error Reading Power Down Config (%d)***" EOL, status);
00547         adi_press_any_key_to_continue();
00548     }
00549 
00550     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00551         if (active_channel_selections[i]) {
00552             powerdown ^= AD5592R_REG_PD_CHANNEL(i);
00553         }
00554     }
00555 
00556     if ((status = ad5592r_base_reg_write(&sAd5592r_dev, AD5592R_REG_PD,
00557                          powerdown)) != SUCCESS) {
00558         printf("*** Error writing Power Down Config (%d)***" EOL, status);
00559         adi_press_any_key_to_continue();
00560     }
00561 
00562     return (MENU_CONTINUE);
00563 }
00564 
00565 /*!
00566  * @brief       Toggle Channels to include in ADC Sequence
00567  * @details Toggles channels that are included in the ADC conversion sequence
00568  * @return      MENU_CONTINUE
00569  */
00570 static int32_t do_toggle_incl_in_seq(uint32_t id)
00571 {
00572     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00573         if (active_channel_selections[i]) {
00574             adc_channels_in_seq ^= AD5592R_REG_ADC_SEQ_INCL(i);
00575         }
00576     }
00577     return (MENU_CONTINUE);
00578 }
00579 
00580 /*!
00581  * @brief       Read ADC Sequence
00582  * @details The channels that are included in an ADC conversion sequence are read.
00583  *          For the number of channels in the sequence, the data is parsed, converted
00584  *          and printed.
00585  * @return      SUCCESS OR FAILURE
00586  */
00587 int32_t do_read_adc_sequence(uint32_t id)
00588 {
00589     int32_t status;
00590     uint16_t adc_seq_data[9] = {0,0,0,0,0,0,0,0,0}, adc_code;
00591     uint8_t chan;
00592     float temperature = 0, voltage = 0;
00593     size_t samples;
00594 
00595     samples = hweight8(adc_channels_in_seq);
00596 
00597     if ((status = sAd5592r_dev.ops->multi_read_adc(&sAd5592r_dev,
00598             adc_channels_in_seq, adc_seq_data)) != SUCCESS) {
00599         printf("*** Error reading adc_sequencer (%d)***" EOL, status);
00600         adi_press_any_key_to_continue();
00601         return FAILURE;
00602     }
00603     
00604     printf("\tCh \tCode \tVoltage \tTemp" EOL);
00605     
00606     for (uint8_t i = 0; i < samples; i++) {
00607         temperature = 0;
00608 
00609         adc_code = AD5592R_REG_ADC_SEQ_CODE_MSK(adc_seq_data[i]);
00610         chan = ((adc_seq_data[i] & 0xF000) >> 12);
00611 
00612         voltage = code_to_volts(adc_code);
00613 
00614         if (chan == TEMPERATURE_READBACK_CHANNEL) {
00615             temperature = die_temp_calculation(adc_code,
00616                                (AD5592R_REG_CTRL_ADC_RANGE &
00617                                 sAd5592r_dev.cached_gp_ctrl));
00618             // Invalid data on temperature read back frame
00619             voltage = 0;
00620             adc_code = 0;
00621         }
00622         printf("\t%d \t%x \t%.2f \t\t%.1f" EOL,
00623                chan,
00624                adc_code,
00625                voltage,
00626                temperature
00627               );
00628     }
00629     adi_press_any_key_to_continue();
00630     return SUCCESS;
00631 }
00632 
00633 /*!
00634  * @brief       Set GPI
00635  * @details GPIO channels that are selected, with the selection being stored in
00636  *          active_channel_selections array are set to GPIO Inputs. The selection is then cleared.
00637  * @return      (MENU_CONTINUE)
00638  */
00639 static int32_t do_set_gpio_input(uint32_t id)
00640 {
00641     int32_t status;
00642 
00643     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00644         if (active_channel_selections[i] == true) {
00645             sAd5592r_dev.channel_modes[i] = CH_MODE_GPI;
00646             if ((status = ad5592r_gpio_direction_input
00647                       (&sAd5592r_dev, AD5592R_CHANNEL(i) )) != SUCCESS) {
00648                 printf(" *** Error Setting GPIO Input on Channel %d (%d) ***" EOL, i, status);
00649                 adi_press_any_key_to_continue();
00650             }
00651         }
00652     }
00653     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00654     return (MENU_CONTINUE);
00655 }
00656 
00657 /*!
00658  * @brief       Set GPO
00659  * @details GPIO channels that are selected, with the selection being stored in
00660  *          active_channel_selections array are set to GPIO Outputs with their
00661  *          output set LOW. The selection is then cleared.
00662  * @return      (MENU_CONTINUE)
00663  */
00664 static int32_t do_set_gpio_output(uint32_t value)
00665 {
00666     int32_t status;
00667 
00668     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00669         if (active_channel_selections[i] == true) {
00670             sAd5592r_dev.channel_modes[i] = CH_MODE_GPO;
00671             if ((status = ad5592r_gpio_direction_output
00672                       (&sAd5592r_dev, AD5592R_CHANNEL(i), GPIO_LOW)) != SUCCESS) {
00673                 printf(" *** Error Setting GPIO Output on channel %d (%d) ***" EOL, i,status);
00674                 adi_press_any_key_to_continue();
00675             }
00676         }
00677     }
00678     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00679     return (MENU_CONTINUE);
00680 }
00681 
00682 /*!
00683  * @brief       Toggle GPO
00684  * @details GPIO channels that are selected, with the selection being stored in
00685  *          active_channel_selections array are set to GPIO Outputs with their
00686  *          output set toggled HIGH and LOW. The selection is then cleared.
00687  * @return      (MENU_CONTINUE)
00688  */
00689 static int32_t do_toggle_gpio_output(uint32_t id)
00690 {
00691     int32_t status;
00692 
00693     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00694         if (active_channel_selections[i] == true) {
00695             if ((status = ad5592r_gpio_set(&sAd5592r_dev,
00696                                AD5592R_CHANNEL(i),
00697                                !ad5592r_gpio_get(&sAd5592r_dev, AD5592R_CHANNEL(i))) != SUCCESS)) {
00698                 printf(" *** Error Toggling GPIO Output on Channel %d (%d) ***", i, status);
00699                 adi_press_any_key_to_continue();
00700             }
00701         }
00702     }
00703     do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION);
00704     return (MENU_CONTINUE);
00705 }
00706 
00707 
00708 /*!
00709  * @brief      calls the general configuration menu
00710  */
00711 static int32_t menu_general_settings(uint32_t id)
00712 {
00713     return adi_do_console_menu(&general_settings_menu);
00714 }
00715 
00716 /*!
00717  * @brief      calls the DAC configuration menu
00718  */
00719 static int32_t menu_dac(uint32_t id)
00720 {
00721     return adi_do_console_menu(&dac_menu);
00722 }
00723 
00724 /*!
00725  * @brief      calls the channel configuration menu
00726  */
00727 static int32_t menu_config_channels(uint32_t id)
00728 {
00729     return adi_do_console_menu(&config_channels_menu);
00730 }
00731 
00732 /*!
00733  * @brief      calls the ADC configuration menu
00734  */
00735 static int32_t menu_adc(uint32_t id)
00736 {
00737     return adi_do_console_menu(&adc_menu);
00738 }
00739 
00740 /*!
00741  * @brief      calls the menu to select GPIO pins to toggle
00742  */
00743 static int32_t menu_gpio(uint32_t id)
00744 {
00745     return adi_do_console_menu(&gpio_menu);
00746 }
00747 
00748 /*!
00749  * @brief      displays the channel configuration header
00750  */
00751 static void display_channel_selection_header(void)
00752 {
00753     printf(" Configuration Lock: %s" EOL,
00754            (AD5592R_REG_CTRL_CONFIG_LOCK & sAd5592r_dev.cached_gp_ctrl)
00755            ?"Enabled":"Disabled");
00756 
00757     printf("\tCh\tMode\t\tOffstate\tSelected" EOL);
00758     for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) {
00759         printf("\t%d \t%s  \t%s \t\t%s" EOL,
00760                i,
00761                mode_names[sAd5592r_dev.channel_modes[i]],
00762                offstate_names[sAd5592r_dev.channel_offstate[i]],
00763                active_channel_selections[i]?"X":"\00" );
00764     }
00765 }
00766 
00767 /*!
00768  * @brief      displays the gpio menu header
00769  */
00770 static void display_gpio_menu_header(void)
00771 {
00772     printf("\tCh\tDir \tValue\tSelected" EOL);
00773 
00774     for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) {
00775 
00776         printf("\t%d \t%s%s \t%s \t%s" EOL,
00777                i,
00778                (sAd5592r_dev.gpio_in &  AD5592R_GPIO(i)) ? "In " : "",
00779                (sAd5592r_dev.gpio_out & AD5592R_GPIO(i)) ? "Out " : "",
00780                ad5592r_gpio_get(&sAd5592r_dev, AD5592R_CHANNEL(i)) ? "High" : "Low",
00781                active_channel_selections[i] ? "X" : "\00"
00782               );
00783     }
00784 }
00785 
00786 /*!
00787  * @brief      displays the DAC menu header
00788  */
00789 static void display_dac_menu_header(void)
00790 {
00791     int32_t status;
00792     float voltage;
00793     uint16_t powerdown_read;
00794     char *dac_channel_state = "";
00795 
00796     printf("\tLDAC mode: %s" EOL EOL,
00797            sAd5592r_dev.ldac_mode ? "Write to Input Register": "Immediate Output");
00798 
00799     printf("\tCH \tConfig \tCode \tVoltage \tSelected" EOL);
00800 
00801     if ((status = ad5592r_base_reg_read(&sAd5592r_dev,
00802                         AD5592R_REG_PD,
00803                         &powerdown_read))  != SUCCESS) {
00804         printf("*** Error checking Power Down status (%d) ***" EOL, status);
00805         adi_press_any_key_to_continue();
00806     }
00807 
00808     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00809         voltage = 0;
00810         switch (sAd5592r_dev.channel_modes[i]) {
00811         case CH_MODE_DAC:
00812         case CH_MODE_DAC_AND_ADC:
00813             if (powerdown_read &  AD5592R_REG_PD_CHANNEL(i)) {
00814                 dac_channel_state = "PD";
00815             } else {
00816                 dac_channel_state = "DAC";
00817                 voltage = code_to_volts(sAd5592r_dev.cached_dac[i]);
00818             }
00819             break;
00820         default:
00821             dac_channel_state = "-";
00822             // Channel no longer set as DAC - Clear cached value
00823             sAd5592r_dev.cached_dac[i] = 0;
00824             break;
00825         }
00826 
00827         printf("\t%d \t%s \t%x  \t%.2fV \t\t%s" EOL,
00828                i,
00829                dac_channel_state,
00830                sAd5592r_dev.cached_dac[i],
00831                voltage,
00832                active_channel_selections[i]?"X":"\00");
00833     }
00834 }
00835 
00836 /*!
00837  * @brief      displays the Main menu header
00838  */
00839 static void display_main_menu_header(void)
00840 {
00841     printf("\tCurrent Channel Configuration:" EOL);
00842     printf("\tCH \tMode " EOL);
00843     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00844         printf("\t%d \t%s" EOL,
00845                i,
00846                mode_names[sAd5592r_dev.channel_modes[i]]);
00847     }
00848 }
00849 
00850 /*!
00851  * @brief      displays the ADC menu header
00852  */
00853 static void display_adc_menu_header(void)
00854 {
00855     char *adc_channel_state = "";
00856 
00857     printf("\tCh \tMode \tIncl \tSelected" EOL);
00858 
00859     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00860         switch (sAd5592r_dev.channel_modes[i]) {
00861         case CH_MODE_ADC:
00862         case CH_MODE_DAC_AND_ADC:
00863             adc_channel_state = "ADC";
00864 
00865             break;
00866         default:
00867             adc_channel_state = "-";
00868             break;
00869         }
00870 
00871         printf("\t%d \t%s \t%s \t%s" EOL,
00872                i,
00873                adc_channel_state,
00874                (adc_channels_in_seq & AD5592R_REG_ADC_SEQ_INCL(i)) ?"X":"",
00875                active_channel_selections[i]?"X":""
00876               );
00877     }
00878 }
00879 
00880 /*
00881  * Definition of the menu of pins to include in adc sequence and menu itself
00882  */
00883 console_menu_item gpio_menu_items[] = {
00884     { "Select Channel", '\00', NULL },
00885     { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) },
00886     { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) },
00887     { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) },
00888     { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) },
00889     { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) },
00890     { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) },
00891     { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) },
00892     { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) },
00893     { "", '\00', NULL },
00894     { "Set as GPIO Input", 'Z', do_set_gpio_input },
00895     { "Set as GPIO Output", 'X', do_set_gpio_output },
00896     { "Toggle Output Value", 'C', do_toggle_gpio_output},
00897 };
00898 
00899 console_menu gpio_menu = {
00900     .title = "GPIO Menu" EOL,
00901     .items = gpio_menu_items,
00902     .itemCount = ARRAY_SIZE(gpio_menu_items),
00903     .headerItem = display_gpio_menu_header,
00904     .footerItem = NULL,
00905     .enableEscapeKey = true
00906 };
00907 
00908 /*
00909  * Definition of the ADC config menu and menu itself
00910  */
00911 console_menu_item adc_menu_items[] = {
00912     { "Select channels:" },
00913     { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) },
00914     { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) },
00915     { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) },
00916     { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) },
00917     { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) },
00918     { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) },
00919     { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) },
00920     { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) },
00921     { "", '\00', NULL },
00922     { "Toggle Channels in Sequence", 'Q', do_toggle_incl_in_seq },
00923     { "Read ADC Sequence", 'W', do_read_adc_sequence},
00924 };
00925 
00926 console_menu adc_menu = {
00927     .title = "ADC Configuration Settings",
00928     .items = adc_menu_items,
00929     .itemCount = ARRAY_SIZE(adc_menu_items),
00930     .headerItem = display_adc_menu_header,
00931     .footerItem = NULL,
00932     .enableEscapeKey = true
00933 };
00934 
00935 
00936 /*
00937  * Definition of the DAC menu and menu itself
00938  */
00939 console_menu_item dac_menu_items[] = {
00940     { "Select Channels:"},
00941     { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) },
00942     { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) },
00943     { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) },
00944     { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) },
00945     { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) },
00946     { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) },
00947     { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) },
00948     { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) },
00949     { "", '\00', NULL },
00950     { "Write voltage to selected DAC channels", 'Q', do_write_dac_value },
00951     { "Toggle Power Down selected DAC channels", 'W', do_toggle_dac_powerdown },
00952     { "Write Input Reg to DAC output", 'E', do_dac_input_reg_to_output },
00953     { "Toggle LDAC mode", 'R', do_toggle_ldac_mode },
00954 };
00955 
00956 console_menu dac_menu = {
00957     .title = "DAC Menu",
00958     .items = dac_menu_items,
00959     .itemCount = ARRAY_SIZE(dac_menu_items),
00960     .headerItem = display_dac_menu_header,
00961     .footerItem = NULL,
00962     .enableEscapeKey = true
00963 };
00964 
00965 /*
00966  * Definition of the General Settings menu and menu itself
00967  */
00968 console_menu_item general_settings_menu_items[] = {
00969     {
00970         "Toggle Internal Voltage Ref (En Ref)",     'A', do_general_settings_toggle,
00971         ((AD5592R_REG_PD << 12) | AD5592R_REG_PD_EN_REF)
00972     },
00973     {
00974         "Toggle ADC PreCharge Buffer  (PC Buff)",   'S', do_general_settings_toggle,
00975         ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_ADC_PC_BUFF)
00976     },
00977     {
00978         "Toggle ADC Buffer (Buff)",                 'D', do_general_settings_toggle,
00979         ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_ADC_BUFF_EN)
00980     },
00981     {
00982         "Toggle Lock Channel Config (Lock Config)", 'F', do_general_settings_toggle,
00983         ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_CONFIG_LOCK)
00984     },
00985     {
00986         "Toggle PD All DACs and Internal Ref",      'G', do_general_settings_toggle,
00987         ((AD5592R_REG_PD << 12) | AD5592R_REG_PD_PD_ALL)
00988     },
00989     {
00990         "Toggle ADC Gain Range (ADC Gain)",         'H', do_general_settings_toggle,
00991         ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_ADC_RANGE)
00992     },
00993     {
00994         "Toggle DAC Gain Range (DAC Gain)",         'J', do_general_settings_toggle,
00995         ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_DAC_RANGE)
00996     },
00997     {
00998         "Toggle Write All DACS (Wr All)",           'K', do_general_settings_toggle,
00999         ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_W_ALL_DACS)
01000     },
01001 };
01002 
01003 console_menu general_settings_menu = {
01004     .title = "General Configuration Settings",
01005     .items = general_settings_menu_items,
01006     .itemCount = ARRAY_SIZE(general_settings_menu_items),
01007     .headerItem = display_general_setting_header,
01008     .footerItem = NULL,
01009     .enableEscapeKey = true
01010 };
01011 
01012 /*
01013  * Definition of the Channel  mode selection menu and menu itself
01014  */
01015 console_menu_item config_channels_menu_items[] = {
01016     { "Select Channels:"},
01017     { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) },
01018     { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) },
01019     { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) },
01020     { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) },
01021     { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) },
01022     { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) },
01023     { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) },
01024     { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) },
01025     { "", '\00', NULL },
01026     { "DAC",        'Q', do_mode_selection, CH_MODE_DAC },
01027     { "ADC",        'W', do_mode_selection, CH_MODE_ADC },
01028     { "ADC + DAC",  'E', do_mode_selection, CH_MODE_DAC_AND_ADC },
01029     { "GPI",        'R', do_mode_selection, CH_MODE_GPI },
01030     { "GPO",        'T', do_mode_selection, CH_MODE_GPO },
01031     { "Unused",     'Y', do_mode_selection, CH_MODE_UNUSED },
01032     { "Restore Default Modes",  'U', do_reset_channel_modes },
01033     { "", '\00', NULL },
01034     { "Pulldown",   'Z', do_offstate_selection, CH_OFFSTATE_PULLDOWN },
01035     { "Output Low", 'X', do_offstate_selection, CH_OFFSTATE_OUT_LOW },
01036     { "Output High",'C', do_offstate_selection, CH_OFFSTATE_OUT_HIGH },
01037     { "Tristate",   'V', do_offstate_selection, CH_OFFSTATE_OUT_TRISTATE },
01038     { "", '\00', NULL },
01039     { "Channel 7 as ADC conversion indicator (AD5592R)", 'M', do_channel_7_adc_indicator },
01040 };
01041 
01042 console_menu config_channels_menu = {
01043     .title = "Configure IO Channels",
01044     .items = config_channels_menu_items,
01045     .itemCount = ARRAY_SIZE(config_channels_menu_items),
01046     .headerItem = display_channel_selection_header,
01047     .footerItem = NULL,
01048     .enableEscapeKey = true
01049 };
01050 
01051 /*
01052  * Definition of the Main Menu Items and menu itself
01053  */
01054 console_menu_item main_menu_items[] = {
01055     { "Software Reset", 'Q', do_software_reset },
01056     { "Read ADC die temp", 'W', do_read_die_temp},
01057     { "", '\00', NULL },
01058     { "Configure Channels", 'A', menu_config_channels},
01059     { "General Settings", 'S', menu_general_settings },
01060     { "DAC Menu", 'D', menu_dac },
01061     { "ADC Menu", 'F', menu_adc },
01062     { "GPIO Menu", 'G', menu_gpio},
01063 };
01064 
01065 console_menu ad5592r_main_menu = {
01066     .title = "AD5592R/AD5593R Main Menu",
01067     .items = main_menu_items,
01068     .itemCount = ARRAY_SIZE(main_menu_items),
01069     .headerItem = display_main_menu_header,
01070     .footerItem = NULL,
01071     .enableEscapeKey = NULL
01072 };