Initial Commit
Dependencies: platform_drivers AD5592R adi_console_menu
Diff: app/ad5592r_console_app.c
- Revision:
- 1:e84d8d51cd51
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/ad5592r_console_app.c Mon Jun 15 14:34:32 2020 +0000 @@ -0,0 +1,1069 @@ +/*! + ***************************************************************************** + * @file ad5592r_console_app.c + * @brief AD5592R console application interfaces + * @details This file is specific to ad5592r and ad5593r console menu application handle. + * The functions defined in this file performs the action + * based on user selected console menu. + * + ----------------------------------------------------------------------------- + Copyright (c) 2020 Analog Devices, Inc. + All rights reserved. + + This software is proprietary to Analog Devices, Inc. and its licensors. + By using this software you agree to the terms of the associated + Analog Devices Software License Agreement. +*****************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <stdbool.h> + +#include "app_config.h" +#include "ad5592r_configs.h" + +#include "platform_support.h" +#include "platform_drivers.h" +#include "spi_extra.h" +#include "i2c_extra.h" + +#include "ad5592r-base.h" +#include "ad5592r.h" +#include "ad5593r.h" + +#include "ad5592r_console_app.h" + +/******************************************************************************/ +/************************* Macros & Constant Definitions **********************/ +/******************************************************************************/ +// vref_voltage can be defined as EXTERNAL_VREF_VOLTAGE or INTERNAL_VREF_VOLTAGE +// Change EXTERNAL_VREF_VOLTAGE if using supply other than 2.5V +#define EXTERNAL_VREF_VOLTAGE 2.5 +float vref_voltage = EXTERNAL_VREF_VOLTAGE; + +#define AD5592R_CHANNEL(N) (N) +#define AD5592R_REG_ADC_SEQ_INCL(x) BIT(x) +#define AD5592R_REG_PD_CHANNEL(x) BIT(x) +#define AD5592R_GPIO(x) BIT(x) + +#define TEMP_SAMPLE_SIZE 5 +#define CLEAR_CHANNEL_SELECTION 1000 +#define MDELAY_TO_DISPLAY_INSTRUCTION 1000 +#define TEMPERATURE_READBACK_CHANNEL 8 + +#define MAX_ADC_CODE 4095.0 +#define ADC_GAIN_LOW_CONVERSION_VALUE 2.654 +#define ADC_GAIN_HIGH_CONVERSION_VALUE 1.327 + +/* Private Variables */ +static struct ad5592r_dev sAd5592r_dev; + +static const char *mode_names[] = { + "Unused", + "ADC\t", + "DAC\t", + "ADC+DAC", + "GPI\t", + "GPO\t", +}; +static const char *offstate_names[] = { + "Pulldown", + "Low\t", + "High\t", + "Tristate" +}; +static bool active_channel_selections[NUM_CHANNELS] = { + false, + false, + false, + false, + false, + false, + false, + false +}; + +static uint16_t adc_channels_in_seq = AD5592R_REG_ADC_SEQ_TEMP_READBACK; + +/******************************************************************************/ +/***************************** Function Declarations **************************/ +/******************************************************************************/ +static int32_t do_software_reset(uint32_t id); +static int32_t do_read_die_temp(uint32_t id); +static float die_temp_calculation(uint16_t adc_temp_code, bool adc_gain); +static void do_set_channel_modes(void); +static int32_t do_toggle_channel_selection(uint32_t channel); +static int32_t do_mode_selection(uint32_t mode); +static int32_t do_reset_channel_modes(uint32_t id); +static int32_t do_offstate_selection(uint32_t mode); +static int32_t do_channel_7_adc_indicator(uint32_t id); +static int32_t do_general_settings_toggle(uint32_t reg_bit_id); +static int32_t do_write_dac_value(uint32_t id); +static int32_t do_dac_input_reg_to_output(uint32_t id); +static int32_t do_toggle_ldac_mode(uint32_t id); +static int32_t do_toggle_dac_powerdown(uint32_t id); +static int32_t do_toggle_incl_in_seq(uint32_t id); +static int32_t do_read_adc_sequence(uint32_t id); + +extern console_menu power_down_pin_select_menu; +extern console_menu config_channels_menu; +extern console_menu general_settings_menu; +extern console_menu dac_menu; +extern console_menu gpio_menu; +extern console_menu adc_menu; + +/******************************************************************************/ +/***************************** Function Definitions ***************************/ +/******************************************************************************/ + +/*! + * @brief Initialize AD5592/3R. ACTIVE_DEVICE defined in app_config.h + *@details The device initialization varies depending on what ACTIVE_DEVICE is defined. + * Device is reset and default register map values written. + * SPI or I2C initialization occurs. + * @return SUCCESS (0), FAILURE (negative) + */ +int32_t ad5592r_app_initalization(void) +{ + memcpy(&sAd5592r_dev, &ad5592r_dev_user, sizeof(ad5592r_dev_user)); + int32_t status; + if (ACTIVE_DEVICE == ID_AD5593R) { + sAd5592r_dev.i2c = &i2c_user_descr; + i2c_init(&sAd5592r_dev.i2c, &i2c_user_params); + status = ad5593r_init(&sAd5592r_dev, &ad5592r_user_param); + } else { + sAd5592r_dev.spi = &spi_user_descr; + spi_init(&sAd5592r_dev.spi, &spi_user_params); + status = ad5592r_init(&sAd5592r_dev, &ad5592r_user_param); + } + return status; +} + +/*! + * @brief Performs software reset + * @details Writes to the reset register. Resets sAd5592r_dev configuration using + * configuration from ad5592r_reset_config.c SPI, I2C and ops are stored + * and restored after the reset. + * @return MENU_CONTINUE + */ +static int32_t do_software_reset(uint32_t id) +{ + int32_t status; + + if ((status = ad5592r_software_reset(&sAd5592r_dev)) == SUCCESS) { + // Save spi_desc field, i2c_desc and device ops settings as it is not reset + spi_desc *spi_interface = sAd5592r_dev.spi; + i2c_desc *i2c_interface = sAd5592r_dev.i2c; + const struct ad5592r_rw_ops *dev_ops = sAd5592r_dev.ops; + // Copy over the reset state of the device + memcpy(&sAd5592r_dev, &ad5592r_dev_reset, sizeof(ad5592r_dev_reset)); + + // Restore device ops + sAd5592r_dev.ops = dev_ops; + if (ACTIVE_DEVICE == ID_AD5592R) { + // Restore the spi_desc pointer field + sAd5592r_dev.spi = spi_interface; + printf(EOL " --- AD5592R Software Reset Successful---" EOL); + } else { + // Restore the i2c_desc pointer field + sAd5592r_dev.i2c = i2c_interface; + printf(EOL " --- AD5593R Reset Request Successful---" EOL); + } + } else { + printf(EOL " *** Software Reset Failure: %d ***" EOL, status); + adi_press_any_key_to_continue(); + } + + adi_press_any_key_to_continue(); + return (MENU_CONTINUE); +} + +/*! + * @brief Prints the temperature of the die + * @details Sets the devices to perform a temperature readback. + * Performs a number of samples based on TEMP_SAMPLE_SIZE + * @return MENU_CONTINUE + */ +static int32_t do_read_die_temp(uint32_t id) +{ + uint16_t readback_reg[1] = { 0 }; + int32_t status = 0, ch_state = 0; + float result = 0; + + ch_state = sAd5592r_dev.channel_modes[7]; + sAd5592r_dev.channel_modes[7] = CH_MODE_ADC; + do_set_channel_modes(); + + do { + + for (int8_t i = 0; i < TEMP_SAMPLE_SIZE; i++) { + do { + status = sAd5592r_dev.ops->read_adc(&sAd5592r_dev, + AD5592R_CHANNEL(8), + readback_reg); + } while (0); + if (status != SUCCESS) { + // Break out of for loop if not successful + break; + } + result += die_temp_calculation(readback_reg[0], + (AD5592R_REG_CTRL_ADC_RANGE & sAd5592r_dev.cached_gp_ctrl)); + } + + result /= TEMP_SAMPLE_SIZE; + + if (status == SUCCESS) { + // Print average of samples + printf(EOL " --- Temperature: %.1f*C --- " EOL, result); + } else { + printf(EOL " *** Error reading die temperature: %d **" EOL, status); + break; + } + } while (0); + + sAd5592r_dev.channel_modes[7] = ch_state; + do_set_channel_modes(); + + adi_press_any_key_to_continue(); + return (MENU_CONTINUE); +} + +/*! + * @brief Calculates the die temperature + * @details Based on conversion equation, die temperature is estimated + * @param adc_temp_code - data read from ADC readback frame + * adc_gain - status of adc_gain + * @return result + */ +static float die_temp_calculation(uint16_t adc_temp_code, bool adc_gain) +{ + float result = 0; + + // use different equation depending on gain + if(adc_gain) { + result = 25 + ((AD5592R_REG_ADC_SEQ_CODE_MSK(adc_temp_code) - + ((0.5 / (2 * vref_voltage)) * MAX_ADC_CODE)) / + (ADC_GAIN_HIGH_CONVERSION_VALUE * (2.5 / vref_voltage))); + } else { + result = 25 + ((AD5592R_REG_ADC_SEQ_CODE_MSK(adc_temp_code) - + ((0.5 / vref_voltage) * MAX_ADC_CODE)) / + (ADC_GAIN_LOW_CONVERSION_VALUE * (2.5 / vref_voltage))); + } + return result; +} + +/*! + * @brief Set channel modes + * + *@details The channels modes are set by passing the altered device + * struct into the ad5592r_set_channel_modes function. There the channels are + * set to desired modes. + */ +static void do_set_channel_modes(void) +{ + int32_t status; + if ((status = ad5592r_set_channel_modes(&sAd5592r_dev)) != SUCCESS) { + printf(EOL "Error configuring Channels (%d)" EOL, status); + adi_press_any_key_to_continue(); + } +} + +/*! + * @brief Toggle channels currently selected + * @details The channels the user has currently selected are set here. + * These are the channels that will be altered by mode or offstate selection + * @param channel - A channel that the user wants to add to the currently selected channels + * @return (MENU_CONTINUE) + */ +static int32_t do_toggle_channel_selection(uint32_t channel) +{ + if (channel == CLEAR_CHANNEL_SELECTION) { + for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) { + + active_channel_selections[i] = false; + } + } else { + active_channel_selections[channel] = !active_channel_selections[channel]; + } + + return (MENU_CONTINUE); +} + +/*! + * @brief Mode selection + * @details The mode the users wishes to apply to the currently selected channels + * are selected here. do_set_channel_modes is called which sets the channels + * on the device. + * @param mode -The mode that the user wishes to apply to the selected channels + * @return (MENU_CONTINUE) + */ +static int32_t do_mode_selection(uint32_t mode) +{ + for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) { + if (active_channel_selections[i] == true) { + sAd5592r_dev.channel_modes[i] = mode; + } + } + do_set_channel_modes(); + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + +/*! + * @brief Offstate selection + * @details The offstate the users wishes to apply to the currently selected channels + * are selected here. do_set_channel_modes is called which sets the channels + * on the device. + * @param The offstate that the user wishes to apply to the selected channels + * @return (MENU_CONTINUE) + */ +static int32_t do_offstate_selection(uint32_t mode) +{ + for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) { + if (active_channel_selections[i] == true) { + sAd5592r_dev.channel_offstate[i] = mode; + } + } + do_set_channel_modes(); + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + +/*! + * @brief Reset Channel Modes + * @details This resets all channel modes to unused. + * @return (MENU_CONTINUE) + * + */ +static int32_t do_reset_channel_modes(uint32_t id) +{ + ad5592r_reset_channel_modes(&sAd5592r_dev); + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + +/*! + * @brief Sets Channel 7 as ADC conversion indicator + * @details Channel 7 is set as a GPIO and the NOT BUSY bit is set in the GPIO + * write configuration register enabling channel 7 to be used as an indicator + * when ADC conversion are occurring. Channel 7 will go LOW when a conversion + * is occurring. + * ***NOTE*** After selecting this Channel 7 will appear as GPO. + * ***NOTE*** Ensure this is the last channel to be configured in order to + * ensure preference will no be overwritten + * @return (MENU_CONTINUE) + */ +static int32_t do_channel_7_adc_indicator(uint32_t id) +{ + sAd5592r_dev.channel_modes[AD5592R_CHANNEL(7)] = + ((sAd5592r_dev.channel_modes[AD5592R_CHANNEL(7)] == CH_MODE_UNUSED) + ? CH_MODE_GPO : CH_MODE_UNUSED); + do_set_channel_modes(); + do_general_settings_toggle(((AD5592R_REG_GPIO_OUT_EN << 12) + | AD5592R_REG_GPIO_OUT_EN_ADC_NOT_BUSY)); + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + +/*! + * @brief Toggle general setting + * @details Setting (reg_bit) in register (reg) is toggled + * @param reg_bit_id - Combined value containing register address and bit to toggle + * @return (MENU_CONTINUE) + */ +static int32_t do_general_settings_toggle(uint32_t reg_bit_id) +{ + uint8_t reg = (reg_bit_id >> 12); + uint16_t reg_bit = (reg_bit_id & 0xFFF), readback_reg; + int32_t status; + + if ((status = ad5592r_base_reg_read(&sAd5592r_dev, reg, + &readback_reg)) != SUCCESS) { + printf(" *** Error Reading Setting Status (%x) *** " EOL, reg); + adi_press_any_key_to_continue(); + } else if ((status = ad5592r_base_reg_write(&sAd5592r_dev, reg, + (reg_bit ^ readback_reg))) != SUCCESS) { + printf(" *** Error Toggling Setting (%x) *** " EOL, reg); + adi_press_any_key_to_continue(); + } + + if (reg == AD5592R_REG_PD && reg_bit == AD5592R_REG_PD_EN_REF) { + if ((AD5592R_REG_PD_EN_REF & (reg_bit ^ readback_reg))) { + vref_voltage = INTERNAL_VREF_VOLTAGE; + } else { + vref_voltage = EXTERNAL_VREF_VOLTAGE; + } + } + return (MENU_CONTINUE); +} + +/*! + * @brief displays the general settings header + */ +static void display_general_setting_header(void) +{ + + int32_t status = 0; + uint16_t ctrl_reg_data = 0, pd_reg_data = 0; + + do { + if ((status = ad5592r_base_reg_read(&sAd5592r_dev, AD5592R_REG_CTRL, + &ctrl_reg_data)) == SUCCESS) { + sAd5592r_dev.cached_gp_ctrl = ctrl_reg_data; + } else { + printf(" *** Error reading register (%x) *** " EOL, AD5592R_REG_CTRL); + adi_press_any_key_to_continue(); + break; + } + + if ((status = ad5592r_base_reg_read(&sAd5592r_dev, AD5592R_REG_PD, + &pd_reg_data)) == SUCCESS) { + } else { + printf(" *** Error reading register (%x) *** " EOL, AD5592R_REG_PD); + adi_press_any_key_to_continue(); + break; + } + } while(0); + + printf("\tSetting \tEnabled\t\tSetting \tEnabled"EOL); + printf("\tEn Ref\t\t%s\t\tADC Gain\t%s"EOL, + (AD5592R_REG_PD_EN_REF & pd_reg_data)?"X":"\00", + (AD5592R_REG_CTRL_ADC_RANGE & ctrl_reg_data)?"X":"\00"); + printf("\tPC Buff\t\t%s\t\tPD All\t\t%s"EOL, + (AD5592R_REG_CTRL_ADC_PC_BUFF & ctrl_reg_data)?"X":"\00", + (AD5592R_REG_PD_PD_ALL & pd_reg_data) ? "X" : "\00"); + printf("\tBuff\t\t%s\t\tDAC Gain\t%s"EOL, + (AD5592R_REG_CTRL_ADC_BUFF_EN & ctrl_reg_data)?"X":"\00", + (AD5592R_REG_CTRL_DAC_RANGE & ctrl_reg_data)?"X":"\00"); + printf("\tLock Config\t%s\t\tWr All\t\t%s"EOL, + (AD5592R_REG_CTRL_CONFIG_LOCK & ctrl_reg_data)?"X":"\00", + (AD5592R_REG_CTRL_W_ALL_DACS & ctrl_reg_data)?"X":"\00"); + +} + +/*! + * @brief DAC input register to DAC output + * @details Writes the data from the DAC input register to the DAC output. + * The LDAC mode is returned to write data to the input register only. + * @return (MENU_CONTINUE) + */ +static int32_t do_dac_input_reg_to_output(uint32_t id) +{ + int32_t status; + if ((status = ad5592r_base_reg_write(&sAd5592r_dev, AD5592R_REG_LDAC, + AD5592R_REG_LDAC_INPUT_REG_OUT)) != SUCCESS) { + printf("*** Error setting LDAC to write to output (%d) *** ", status); + adi_press_any_key_to_continue(); + } + sAd5592r_dev.ldac_mode = AD5592R_REG_LDAC_INPUT_REG_ONLY; + return (MENU_CONTINUE); +} + +/*! + * @brief User dac code + * @details Generate dac code that can be written to device from voltage provided by user + * @param user_voltage - float value provided by user for voltage value to be set + * @return dac code value + */ +static uint16_t user_dac_code(float user_voltage) +{ + return (uint16_t) (((user_voltage) * MAX_ADC_CODE) / vref_voltage); +} + +/*! + * @brief Code values to voltage + * @details Generate voltage based on code value + * @param code - integer value used to generate voltage value + * @return float voltage value + */ +static float code_to_volts(int16_t code) +{ + return ((code / MAX_ADC_CODE) * vref_voltage); +} + +/*! + * @brief Write DAC Values + * @details Write value specified by user to Channels selected by user in the DAC menu + * @return (MENU_CONTINUE) + */ +static int32_t do_write_dac_value(uint32_t id) +{ + int32_t status; + uint16_t user_code = 0; + float user_voltage = 2.5; + + printf(EOL "\tEnter voltage to write to selected DACs (0 - Vref) : " EOL); + user_voltage = adi_get_decimal_float(5); + user_code = user_dac_code(user_voltage); + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + if (active_channel_selections[i]) { + if ((status = sAd5592r_dev.ops->write_dac(&sAd5592r_dev, i, + user_code)) != SUCCESS) { + printf("*** Error writing DAC value to channel %d (%d) ***" EOL, i, status); + adi_press_any_key_to_continue(); + } + sAd5592r_dev.cached_dac[i] = user_code; + } + } + return (MENU_CONTINUE); +} + +/*! + * @brief Toggle LDAC Modes + * @details Toggles the LDAC mode variable between Immediate write to output + * and write values to input register + * @return (MENU_CONTINUE) + */ +static int32_t do_toggle_ldac_mode(uint32_t id) +{ + if (sAd5592r_dev.ldac_mode == AD5592R_REG_LDAC_INPUT_REG_ONLY) { + sAd5592r_dev.ldac_mode = AD5592R_REG_LDAC_IMMEDIATE_OUT; + } else { + sAd5592r_dev.ldac_mode = AD5592R_REG_LDAC_INPUT_REG_ONLY; + } + return (MENU_CONTINUE); +} + +/*! + * @brief Toggle DAC channels to power-down + * @details Toggles DAC channels that are powered down based on user selection + * @return (MENU_CONTINUE) + */ +static int32_t do_toggle_dac_powerdown(uint32_t id) +{ + int32_t status; + uint16_t powerdown = 0; + + if ((status = ad5592r_base_reg_read(&sAd5592r_dev, AD5592R_REG_PD, + &powerdown)) != SUCCESS) { + printf("*** Error Reading Power Down Config (%d)***" EOL, status); + adi_press_any_key_to_continue(); + } + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + if (active_channel_selections[i]) { + powerdown ^= AD5592R_REG_PD_CHANNEL(i); + } + } + + if ((status = ad5592r_base_reg_write(&sAd5592r_dev, AD5592R_REG_PD, + powerdown)) != SUCCESS) { + printf("*** Error writing Power Down Config (%d)***" EOL, status); + adi_press_any_key_to_continue(); + } + + return (MENU_CONTINUE); +} + +/*! + * @brief Toggle Channels to include in ADC Sequence + * @details Toggles channels that are included in the ADC conversion sequence + * @return MENU_CONTINUE + */ +static int32_t do_toggle_incl_in_seq(uint32_t id) +{ + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + if (active_channel_selections[i]) { + adc_channels_in_seq ^= AD5592R_REG_ADC_SEQ_INCL(i); + } + } + return (MENU_CONTINUE); +} + +/*! + * @brief Read ADC Sequence + * @details The channels that are included in an ADC conversion sequence are read. + * For the number of channels in the sequence, the data is parsed, converted + * and printed. + * @return SUCCESS OR FAILURE + */ +int32_t do_read_adc_sequence(uint32_t id) +{ + int32_t status; + uint16_t adc_seq_data[9] = {0,0,0,0,0,0,0,0,0}, adc_code; + uint8_t chan; + float temperature = 0, voltage = 0; + size_t samples; + + samples = hweight8(adc_channels_in_seq); + + if ((status = sAd5592r_dev.ops->multi_read_adc(&sAd5592r_dev, + adc_channels_in_seq, adc_seq_data)) != SUCCESS) { + printf("*** Error reading adc_sequencer (%d)***" EOL, status); + adi_press_any_key_to_continue(); + return FAILURE; + } + + printf("\tCh \tCode \tVoltage \tTemp" EOL); + + for (uint8_t i = 0; i < samples; i++) { + temperature = 0; + + adc_code = AD5592R_REG_ADC_SEQ_CODE_MSK(adc_seq_data[i]); + chan = ((adc_seq_data[i] & 0xF000) >> 12); + + voltage = code_to_volts(adc_code); + + if (chan == TEMPERATURE_READBACK_CHANNEL) { + temperature = die_temp_calculation(adc_code, + (AD5592R_REG_CTRL_ADC_RANGE & + sAd5592r_dev.cached_gp_ctrl)); + // Invalid data on temperature read back frame + voltage = 0; + adc_code = 0; + } + printf("\t%d \t%x \t%.2f \t\t%.1f" EOL, + chan, + adc_code, + voltage, + temperature + ); + } + adi_press_any_key_to_continue(); + return SUCCESS; +} + +/*! + * @brief Set GPI + * @details GPIO channels that are selected, with the selection being stored in + * active_channel_selections array are set to GPIO Inputs. The selection is then cleared. + * @return (MENU_CONTINUE) + */ +static int32_t do_set_gpio_input(uint32_t id) +{ + int32_t status; + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + if (active_channel_selections[i] == true) { + sAd5592r_dev.channel_modes[i] = CH_MODE_GPI; + if ((status = ad5592r_gpio_direction_input + (&sAd5592r_dev, AD5592R_CHANNEL(i) )) != SUCCESS) { + printf(" *** Error Setting GPIO Input on Channel %d (%d) ***" EOL, i, status); + adi_press_any_key_to_continue(); + } + } + } + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + +/*! + * @brief Set GPO + * @details GPIO channels that are selected, with the selection being stored in + * active_channel_selections array are set to GPIO Outputs with their + * output set LOW. The selection is then cleared. + * @return (MENU_CONTINUE) + */ +static int32_t do_set_gpio_output(uint32_t value) +{ + int32_t status; + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + if (active_channel_selections[i] == true) { + sAd5592r_dev.channel_modes[i] = CH_MODE_GPO; + if ((status = ad5592r_gpio_direction_output + (&sAd5592r_dev, AD5592R_CHANNEL(i), GPIO_LOW)) != SUCCESS) { + printf(" *** Error Setting GPIO Output on channel %d (%d) ***" EOL, i,status); + adi_press_any_key_to_continue(); + } + } + } + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + +/*! + * @brief Toggle GPO + * @details GPIO channels that are selected, with the selection being stored in + * active_channel_selections array are set to GPIO Outputs with their + * output set toggled HIGH and LOW. The selection is then cleared. + * @return (MENU_CONTINUE) + */ +static int32_t do_toggle_gpio_output(uint32_t id) +{ + int32_t status; + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + if (active_channel_selections[i] == true) { + if ((status = ad5592r_gpio_set(&sAd5592r_dev, + AD5592R_CHANNEL(i), + !ad5592r_gpio_get(&sAd5592r_dev, AD5592R_CHANNEL(i))) != SUCCESS)) { + printf(" *** Error Toggling GPIO Output on Channel %d (%d) ***", i, status); + adi_press_any_key_to_continue(); + } + } + } + do_toggle_channel_selection(CLEAR_CHANNEL_SELECTION); + return (MENU_CONTINUE); +} + + +/*! + * @brief calls the general configuration menu + */ +static int32_t menu_general_settings(uint32_t id) +{ + return adi_do_console_menu(&general_settings_menu); +} + +/*! + * @brief calls the DAC configuration menu + */ +static int32_t menu_dac(uint32_t id) +{ + return adi_do_console_menu(&dac_menu); +} + +/*! + * @brief calls the channel configuration menu + */ +static int32_t menu_config_channels(uint32_t id) +{ + return adi_do_console_menu(&config_channels_menu); +} + +/*! + * @brief calls the ADC configuration menu + */ +static int32_t menu_adc(uint32_t id) +{ + return adi_do_console_menu(&adc_menu); +} + +/*! + * @brief calls the menu to select GPIO pins to toggle + */ +static int32_t menu_gpio(uint32_t id) +{ + return adi_do_console_menu(&gpio_menu); +} + +/*! + * @brief displays the channel configuration header + */ +static void display_channel_selection_header(void) +{ + printf(" Configuration Lock: %s" EOL, + (AD5592R_REG_CTRL_CONFIG_LOCK & sAd5592r_dev.cached_gp_ctrl) + ?"Enabled":"Disabled"); + + printf("\tCh\tMode\t\tOffstate\tSelected" EOL); + for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) { + printf("\t%d \t%s \t%s \t\t%s" EOL, + i, + mode_names[sAd5592r_dev.channel_modes[i]], + offstate_names[sAd5592r_dev.channel_offstate[i]], + active_channel_selections[i]?"X":"\00" ); + } +} + +/*! + * @brief displays the gpio menu header + */ +static void display_gpio_menu_header(void) +{ + printf("\tCh\tDir \tValue\tSelected" EOL); + + for (uint8_t i = 0; i < sAd5592r_dev.num_channels; i++) { + + printf("\t%d \t%s%s \t%s \t%s" EOL, + i, + (sAd5592r_dev.gpio_in & AD5592R_GPIO(i)) ? "In " : "", + (sAd5592r_dev.gpio_out & AD5592R_GPIO(i)) ? "Out " : "", + ad5592r_gpio_get(&sAd5592r_dev, AD5592R_CHANNEL(i)) ? "High" : "Low", + active_channel_selections[i] ? "X" : "\00" + ); + } +} + +/*! + * @brief displays the DAC menu header + */ +static void display_dac_menu_header(void) +{ + int32_t status; + float voltage; + uint16_t powerdown_read; + char *dac_channel_state = ""; + + printf("\tLDAC mode: %s" EOL EOL, + sAd5592r_dev.ldac_mode ? "Write to Input Register": "Immediate Output"); + + printf("\tCH \tConfig \tCode \tVoltage \tSelected" EOL); + + if ((status = ad5592r_base_reg_read(&sAd5592r_dev, + AD5592R_REG_PD, + &powerdown_read)) != SUCCESS) { + printf("*** Error checking Power Down status (%d) ***" EOL, status); + adi_press_any_key_to_continue(); + } + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + voltage = 0; + switch (sAd5592r_dev.channel_modes[i]) { + case CH_MODE_DAC: + case CH_MODE_DAC_AND_ADC: + if (powerdown_read & AD5592R_REG_PD_CHANNEL(i)) { + dac_channel_state = "PD"; + } else { + dac_channel_state = "DAC"; + voltage = code_to_volts(sAd5592r_dev.cached_dac[i]); + } + break; + default: + dac_channel_state = "-"; + // Channel no longer set as DAC - Clear cached value + sAd5592r_dev.cached_dac[i] = 0; + break; + } + + printf("\t%d \t%s \t%x \t%.2fV \t\t%s" EOL, + i, + dac_channel_state, + sAd5592r_dev.cached_dac[i], + voltage, + active_channel_selections[i]?"X":"\00"); + } +} + +/*! + * @brief displays the Main menu header + */ +static void display_main_menu_header(void) +{ + printf("\tCurrent Channel Configuration:" EOL); + printf("\tCH \tMode " EOL); + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + printf("\t%d \t%s" EOL, + i, + mode_names[sAd5592r_dev.channel_modes[i]]); + } +} + +/*! + * @brief displays the ADC menu header + */ +static void display_adc_menu_header(void) +{ + char *adc_channel_state = ""; + + printf("\tCh \tMode \tIncl \tSelected" EOL); + + for (uint8_t i = 0; i < NUM_CHANNELS; i++) { + switch (sAd5592r_dev.channel_modes[i]) { + case CH_MODE_ADC: + case CH_MODE_DAC_AND_ADC: + adc_channel_state = "ADC"; + + break; + default: + adc_channel_state = "-"; + break; + } + + printf("\t%d \t%s \t%s \t%s" EOL, + i, + adc_channel_state, + (adc_channels_in_seq & AD5592R_REG_ADC_SEQ_INCL(i)) ?"X":"", + active_channel_selections[i]?"X":"" + ); + } +} + +/* + * Definition of the menu of pins to include in adc sequence and menu itself + */ +console_menu_item gpio_menu_items[] = { + { "Select Channel", '\00', NULL }, + { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) }, + { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) }, + { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) }, + { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) }, + { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) }, + { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) }, + { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) }, + { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) }, + { "", '\00', NULL }, + { "Set as GPIO Input", 'Z', do_set_gpio_input }, + { "Set as GPIO Output", 'X', do_set_gpio_output }, + { "Toggle Output Value", 'C', do_toggle_gpio_output}, +}; + +console_menu gpio_menu = { + .title = "GPIO Menu" EOL, + .items = gpio_menu_items, + .itemCount = ARRAY_SIZE(gpio_menu_items), + .headerItem = display_gpio_menu_header, + .footerItem = NULL, + .enableEscapeKey = true +}; + +/* + * Definition of the ADC config menu and menu itself + */ +console_menu_item adc_menu_items[] = { + { "Select channels:" }, + { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) }, + { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) }, + { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) }, + { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) }, + { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) }, + { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) }, + { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) }, + { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) }, + { "", '\00', NULL }, + { "Toggle Channels in Sequence", 'Q', do_toggle_incl_in_seq }, + { "Read ADC Sequence", 'W', do_read_adc_sequence}, +}; + +console_menu adc_menu = { + .title = "ADC Configuration Settings", + .items = adc_menu_items, + .itemCount = ARRAY_SIZE(adc_menu_items), + .headerItem = display_adc_menu_header, + .footerItem = NULL, + .enableEscapeKey = true +}; + + +/* + * Definition of the DAC menu and menu itself + */ +console_menu_item dac_menu_items[] = { + { "Select Channels:"}, + { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) }, + { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) }, + { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) }, + { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) }, + { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) }, + { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) }, + { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) }, + { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) }, + { "", '\00', NULL }, + { "Write voltage to selected DAC channels", 'Q', do_write_dac_value }, + { "Toggle Power Down selected DAC channels", 'W', do_toggle_dac_powerdown }, + { "Write Input Reg to DAC output", 'E', do_dac_input_reg_to_output }, + { "Toggle LDAC mode", 'R', do_toggle_ldac_mode }, +}; + +console_menu dac_menu = { + .title = "DAC Menu", + .items = dac_menu_items, + .itemCount = ARRAY_SIZE(dac_menu_items), + .headerItem = display_dac_menu_header, + .footerItem = NULL, + .enableEscapeKey = true +}; + +/* + * Definition of the General Settings menu and menu itself + */ +console_menu_item general_settings_menu_items[] = { + { + "Toggle Internal Voltage Ref (En Ref)", 'A', do_general_settings_toggle, + ((AD5592R_REG_PD << 12) | AD5592R_REG_PD_EN_REF) + }, + { + "Toggle ADC PreCharge Buffer (PC Buff)", 'S', do_general_settings_toggle, + ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_ADC_PC_BUFF) + }, + { + "Toggle ADC Buffer (Buff)", 'D', do_general_settings_toggle, + ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_ADC_BUFF_EN) + }, + { + "Toggle Lock Channel Config (Lock Config)", 'F', do_general_settings_toggle, + ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_CONFIG_LOCK) + }, + { + "Toggle PD All DACs and Internal Ref", 'G', do_general_settings_toggle, + ((AD5592R_REG_PD << 12) | AD5592R_REG_PD_PD_ALL) + }, + { + "Toggle ADC Gain Range (ADC Gain)", 'H', do_general_settings_toggle, + ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_ADC_RANGE) + }, + { + "Toggle DAC Gain Range (DAC Gain)", 'J', do_general_settings_toggle, + ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_DAC_RANGE) + }, + { + "Toggle Write All DACS (Wr All)", 'K', do_general_settings_toggle, + ((AD5592R_REG_CTRL << 12) | AD5592R_REG_CTRL_W_ALL_DACS) + }, +}; + +console_menu general_settings_menu = { + .title = "General Configuration Settings", + .items = general_settings_menu_items, + .itemCount = ARRAY_SIZE(general_settings_menu_items), + .headerItem = display_general_setting_header, + .footerItem = NULL, + .enableEscapeKey = true +}; + +/* + * Definition of the Channel mode selection menu and menu itself + */ +console_menu_item config_channels_menu_items[] = { + { "Select Channels:"}, + { "Channel 0", 'A', do_toggle_channel_selection, AD5592R_CHANNEL(0) }, + { "Channel 1", 'S', do_toggle_channel_selection, AD5592R_CHANNEL(1) }, + { "Channel 2", 'D', do_toggle_channel_selection, AD5592R_CHANNEL(2) }, + { "Channel 3", 'F', do_toggle_channel_selection, AD5592R_CHANNEL(3) }, + { "Channel 4", 'G', do_toggle_channel_selection, AD5592R_CHANNEL(4) }, + { "Channel 5", 'H', do_toggle_channel_selection, AD5592R_CHANNEL(5) }, + { "Channel 6", 'J', do_toggle_channel_selection, AD5592R_CHANNEL(6) }, + { "Channel 7", 'K', do_toggle_channel_selection, AD5592R_CHANNEL(7) }, + { "", '\00', NULL }, + { "DAC", 'Q', do_mode_selection, CH_MODE_DAC }, + { "ADC", 'W', do_mode_selection, CH_MODE_ADC }, + { "ADC + DAC", 'E', do_mode_selection, CH_MODE_DAC_AND_ADC }, + { "GPI", 'R', do_mode_selection, CH_MODE_GPI }, + { "GPO", 'T', do_mode_selection, CH_MODE_GPO }, + { "Unused", 'Y', do_mode_selection, CH_MODE_UNUSED }, + { "Restore Default Modes", 'U', do_reset_channel_modes }, + { "", '\00', NULL }, + { "Pulldown", 'Z', do_offstate_selection, CH_OFFSTATE_PULLDOWN }, + { "Output Low", 'X', do_offstate_selection, CH_OFFSTATE_OUT_LOW }, + { "Output High",'C', do_offstate_selection, CH_OFFSTATE_OUT_HIGH }, + { "Tristate", 'V', do_offstate_selection, CH_OFFSTATE_OUT_TRISTATE }, + { "", '\00', NULL }, + { "Channel 7 as ADC conversion indicator (AD5592R)", 'M', do_channel_7_adc_indicator }, +}; + +console_menu config_channels_menu = { + .title = "Configure IO Channels", + .items = config_channels_menu_items, + .itemCount = ARRAY_SIZE(config_channels_menu_items), + .headerItem = display_channel_selection_header, + .footerItem = NULL, + .enableEscapeKey = true +}; + +/* + * Definition of the Main Menu Items and menu itself + */ +console_menu_item main_menu_items[] = { + { "Software Reset", 'Q', do_software_reset }, + { "Read ADC die temp", 'W', do_read_die_temp}, + { "", '\00', NULL }, + { "Configure Channels", 'A', menu_config_channels}, + { "General Settings", 'S', menu_general_settings }, + { "DAC Menu", 'D', menu_dac }, + { "ADC Menu", 'F', menu_adc }, + { "GPIO Menu", 'G', menu_gpio}, +}; + +console_menu ad5592r_main_menu = { + .title = "AD5592R/AD5593R Main Menu", + .items = main_menu_items, + .itemCount = ARRAY_SIZE(main_menu_items), + .headerItem = display_main_menu_header, + .footerItem = NULL, + .enableEscapeKey = NULL +};