Initial Commit

Dependencies:   AD5686

Revision:
1:384a1737b0df
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue May 28 19:37:12 2019 +0000
@@ -0,0 +1,848 @@
+/*************************************************************************//**
+ *   @file   main.cpp
+ *   @brief  Main application code for AD5686 firmware example program
+ *   @author ssmith (sean.smith@analog.com)
+******************************************************************************
+* Copyright (c) 2019 Analog Devices, Inc.  
+* 
+* All rights reserved.
+* 
+* Redistribution and use in source and binary forms, with or without 
+* modification, are permitted provided that the following conditions are met:
+*   - Redistributions of source code must retain the above copyright notice, 
+*     this list of conditions and the following disclaimer.
+*   - Redistributions in binary form must reproduce the above copyright notice, 
+*     this list of conditions and the following disclaimer in the documentation 
+*     and/or other materials provided with the distribution.  
+*   - Modified versions of the software must be conspicuously marked as such.
+*   - This software is licensed solely and exclusively for use with 
+*     processors/products manufactured by or for Analog Devices, Inc.
+*   - This software may not be combined or merged with other code in any manner 
+*     that would cause the software to become subject to terms and 
+*     conditions which differ from those listed here.
+*   - Neither the name of Analog Devices, Inc. nor the names of its 
+*     contributors may be used to endorse or promote products derived 
+*     from this software without specific prior written permission.
+*   - The use of this software may or may not infringe the patent rights 
+*     of one or more patent holders. This license does not release you from 
+*     the requirement that you obtain separate licenses from these patent 
+*     holders to use this software.
+* 
+* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" 
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+* NON-INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A 
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, 
+* INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+* SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES 
+* (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF 
+* INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE 
+* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+* POSSIBILITY OF SUCH DAMAGE.
+* 
+* 20180927-7CBSD SLA
+*****************************************************************************/
+
+#include <stdio.h>
+#include <mbed.h>
+#include "app_config.h"
+
+#define NOT_USED 0
+#define WAIT_MENU_TIME 1
+
+static void print_title(void);
+static float get_voltage_float(void);
+static int getMenuSelect(uint8_t *menuSelect);
+static void print_prompt(int16_t selected_dac, float ref_voltage);
+static uint16_t voltage_to_code(float voltage, float vRef);
+static uint8_t menu_1_select_dac(uint16_t *selected_dac);
+static void menu_2_write_to_input_register(int16_t selected_dac, float vref); 
+static void menu_3_update_dac(int16_t selected_dac);
+static void menu_4_write_and_update_dac(int16_t selected_dac, float vref); 
+static int8_t menu_5_power_down_mode(int16_t selected_dac);
+static int8_t menu_6_select_ref_voltage(float *vref);
+static void menu_7_read_back_registers();
+static int8_t menu_8_set_ldac_mask();
+static void menu_9_assert_ldac();
+static int8_t menu_10_set_gain();
+static void menu_11_assert_soft_reset();
+static void menu_12_assert_hard_reset();
+static uint16_t get_voltage_code(float vRef);
+static uint8_t selectChannel(uint16_t selectedDac);
+static void set_default_pins(void);
+
+/******************************************************************************/
+/************************** Variables Declarations ****************************/
+/******************************************************************************/
+extern ad5686_chip_info chip_info[];
+
+/**
+	The following definitions are a requirement for the platform_driver
+	Pin are changed if required in the app_config.h file
+ ***/
+DigitalOut SS(SPI_CS);
+mbed::SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK);
+mbed::I2C i2c(I2C_SDA, I2C_SCL);
+
+i2c_init_param i2c_params =
+{
+	// i2c type
+	GENERIC_I2C,
+	// i2c id
+	NOT_USED,
+	// i2c max speed (hz)
+	100000,
+	// i2c slave address (AD5693)
+	//0x98	
+ 	// i2c slave address (AD5696)
+	0x18 
+};
+
+
+spi_init_param spi_params = {
+	MBED,
+	//spi_type
+	GENERIC_SPI,
+	//id
+	NOT_USED,
+	//frequency
+	2000000, 
+	// SPI mode
+	SPI_MODE_2,
+	//CS mapping
+	SPI_CS, 
+};
+
+gpio_desc gpio_gain =
+{
+	GENERIC_GPIO,
+	NOT_USED,
+	NOT_USED,
+	GAIN_PIN
+};
+
+gpio_desc gpio_ldac =
+{
+	GENERIC_GPIO,
+	NOT_USED,
+	NOT_USED,
+	LDAC_PIN
+};
+
+gpio_desc gpio_reset =
+{
+	GENERIC_GPIO,
+	//TYPE
+	NOT_USED,
+	//ID
+	NOT_USED,
+	//NUMBER
+	RESET_PIN
+};
+
+ad5686_init_param init_params = {
+
+	// I2C parameters
+	i2c_params,
+	// SPI parameters
+	spi_params,
+	//GPIO's
+	gpio_reset,
+	gpio_ldac,
+	gpio_gain,
+	//Set this in app_config.h
+	ACTIVE_DEVICE,
+};
+
+
+ad5686_dev *device;
+int32_t connected = -1;
+uint8_t gpioGainVal = 0;
+
+//! Configure and instantiate the UART
+Serial pc(USBTX, USBRX, 115200);
+
+int main()
+{
+
+	uint8_t menuSelect = 0;
+	uint16_t selected_dac = 1;
+	float ref_voltage = 2.5;
+
+	print_title();
+	connected = ad5686_init(&device, init_params);
+	set_default_pins();
+	while (connected == SUCCESS)
+	{
+		// Switch menu based on user's input
+		print_prompt(selected_dac, ref_voltage);
+		if (getMenuSelect(&menuSelect) == FAILURE)
+			print_prompt(selected_dac, ref_voltage);
+		else
+			switch (menuSelect)
+			{
+			case 1:
+				menu_1_select_dac(&selected_dac);
+				break;
+
+			case 2:
+				menu_2_write_to_input_register(selected_dac, ref_voltage);
+				break;
+
+			case 3:
+				menu_3_update_dac(selected_dac);
+				break;
+
+			case 4:
+				menu_4_write_and_update_dac(selected_dac, ref_voltage);
+				break;
+
+			case 5:
+				menu_5_power_down_mode(selected_dac);
+				break;
+
+			case 6:
+				menu_6_select_ref_voltage(&ref_voltage);
+				break;
+
+			case 7:
+				menu_7_read_back_registers();
+				break;
+
+			case 8:
+				menu_8_set_ldac_mask();
+				break;
+
+			case 9:
+				menu_9_assert_ldac();
+				break;
+
+			case 10:
+				menu_10_set_gain();
+				break;
+
+			case 11:
+				menu_11_assert_soft_reset();
+				break;
+
+			case 12:
+				menu_12_assert_hard_reset();
+				break;
+
+			default :
+				pc.printf("Incorrect Option\n");
+				break;
+			}
+		//Allow some time before menu switches
+		wait(1);
+	}
+	//Should never be reached
+	return 0;
+}
+
+static void print_title()
+{
+	pc.printf("*****************************************************************\n");
+	pc.printf("* EVAL-nanoDAC+ Demonstration Program for mbed                  *\n");
+	pc.printf("*                                                               *\n");
+	pc.printf("* This program demonstrates communication with the nanoDAC+     *\n");
+	pc.printf("* family of Rail-to-Rail DACs with SPI/I2C Interface.           *\n");
+	pc.printf("*                                                               *\n");
+	pc.printf("* Set the baud rate to 115200                                   *\n");
+	pc.printf("* For Compile requirements see the user-guide                   *\n");
+	pc.printf("*****************************************************************\n");
+}
+
+
+/*************************************************************************//**
+ * @brief  - Prints the "main menu" prompt to the console
+ *
+ * @param selected_dac	- only 1,2,4,8 (DAC A/B/C/D) are valid
+ * @param ref_voltage	- For displaying in the UI
+ *
+ * @return None.
+*****************************************************************************/
+static void print_prompt(int16_t selected_dac, float ref_voltage)
+{
+	pc.printf("\n\nCommand Summary:\n\n");
+
+	if (chip_info[device->act_device].register_map == AD5686_REG_MAP)
+	{
+		pc.printf("  1 -Select DAC\n");
+		pc.printf("  2 -Write to input register (no update)\n");
+		pc.printf("  3 -Update DAC from input\n");
+		pc.printf("  4 -Write and update DAC\n");
+		pc.printf("  5 -Power down mode\n");
+		pc.printf("  6 -Select reference voltage\n");
+		pc.printf("  7 -Read back all registers\n");
+		pc.printf("  8 -Set LDAC# mask\n");
+		pc.printf("  9 -Assert LDAC#\n");
+		pc.printf("  10-Set gain\n");
+		pc.printf("  11-Assert Software Reset\n");
+		pc.printf("  12-Assert Hardware Reset\n");
+		pc.printf("\n");
+		pc.printf("\n  Reference Voltage: %f\n", ref_voltage);
+
+		switch (selected_dac)
+		{
+		case 1:{ pc.printf("  DAC A is currently selected\n"); break; }
+		case 2:{ pc.printf("  DAC B is currently selected\n"); break; }
+		case 4:{ pc.printf("  DAC C is currently selected\n"); break; }
+		case 8:{ pc.printf("  DAC D is currently selected\n"); break; }
+		default: {
+				pc.printf("  Please select a DAC (Option 1):\n");
+				selected_dac = 0;
+			}
+		}
+	}
+	else
+	{
+		/*
+		 * This code runs for products in the nanoDAC+ family that have the 
+		 * reduced register map
+		 */
+		
+		pc.printf("  1 -NOP: Do nothing\n");
+		pc.printf("  2 -Write Input register\n");
+		pc.printf("  3 -Software LDAC\n");
+		pc.printf("  4 -Write to DAC and Input registers\n");
+		pc.printf("  5 -Write to control registers\n");
+		pc.printf("\n");
+		pc.printf("\n  Reference Voltage: %f\n", ref_voltage);
+
+	}
+}
+
+static int getMenuSelect(uint8_t *menuSelect) {
+	int inp = pc.scanf("%2d", (int *) menuSelect);
+	
+	if (inp == 0 || *menuSelect > 12)
+	{
+		pc.printf("\n\n*****   Invalid entry: ignoring *****\n");
+		wait(WAIT_MENU_TIME);
+		return FAILURE;
+	}
+	else
+		return SUCCESS;
+}
+
+/*************************************************************************//**
+ * @brief				- Select active DAC - only one channel can be active
+ *
+ * @param selected_dac - only 1,2,4,8 (DAC A/B/C/D) are valid
+ *
+ * @return None.
+*****************************************************************************/
+static uint8_t menu_1_select_dac(uint16_t *selected_dac)
+{
+	char string[5] = "0001";
+	char *str = string;
+	int8_t cnt = 3;
+	uint16_t dac = 0;
+	pc.printf("  \nDAC selections are represented in binary with\n");
+	pc.printf("  bits corresponding to: DCBA\n");
+	pc.printf("  (See datasheet for details and explanation)\n");
+	pc.printf("  For example:\n\n");
+	pc.printf("     0001 - DAC A\n");
+	pc.printf("     0010 - DAC B\n");
+	pc.printf("     0100 - DAC C\n");
+	pc.printf("     1000 - DAC D\n");
+	pc.printf("   i.e. Enter 4 binary digits. All other values will be ignored\n");
+	pc.printf("  Enter DAC to write to: ");
+    pc.scanf("%4s", string);
+	while (cnt >= 0)
+	{
+		if ((*str != '1' && *str != '0') || *str == '\0')
+		{
+			pc.printf("\nInvalid entry - exactly 4 binary characters are required\n");
+			dac = 0;
+			break;
+		}
+		else if (*str++ == '1')
+			dac |= (1 << cnt);
+		cnt--;
+	}
+
+	switch (dac)
+	{
+	case 1:{ pc.printf("You selected DAC A\n"); *selected_dac = dac; break; }
+	case 2:{ pc.printf("You selected DAC B\n"); *selected_dac = dac; break; }
+	case 4:{ pc.printf("You selected DAC C\n"); *selected_dac = dac; break; }
+	case 8:{ pc.printf("You selected DAC D\n"); *selected_dac = dac; break; }
+	default: {
+			pc.printf("\n  Please select DAC in the format described above:\n");
+			pc.printf("\n  No changes made:\n");
+			wait(2);
+		}
+	}
+
+	return SUCCESS; // Always returns success, consider adding a fail code later.
+}
+
+/*************************************************************************//**
+ * @brief Write to input-register - do not update DAC
+ *
+ * @param selected_dac - only 1,2,4,8 (DAC A/B/C/D) are valid
+ *
+ * @return None.
+*****************************************************************************/
+static void menu_2_write_to_input_register(int16_t selected_dac, float vref) 
+{
+	unsigned short vdata = get_voltage_code(vref);
+	enum ad5686_dac_channels
+		chan = (ad5686_dac_channels)selectChannel(selected_dac);
+	ad5686_write_register(device, chan, vdata);
+}
+
+/*************************************************************************//**
+ * @brief				- Updates DAC outputs from its input registers 
+ *
+ * @param selected_dac	- Selected DAC (1,2,4,8 -> DAC A,B,C,D)
+*****************************************************************************/
+static void menu_3_update_dac(int16_t selected_dac)
+{
+	enum ad5686_dac_channels
+		chan = (ad5686_dac_channels)selectChannel(selected_dac);
+	ad5686_update_register(device, chan);
+	pc.printf("  Updated DAC(s)\n");
+	wait(3);
+}
+
+/*************************************************************************//**
+ * @brief				- Write a value to the select_dac
+ *
+ * @param selected_dac	- Selected DAC (1,2,4,8 -> DAC A,B,C,D)
+ * @param vRef			- Reference voltage
+*****************************************************************************/
+static void menu_4_write_and_update_dac(int16_t selected_dac, float vref) 
+{
+	unsigned short vdata = get_voltage_code(vref);
+
+	pc.printf("Entered code: %x ", vdata);
+
+	//!Convert from user-selected 2**n dac-select to the enum
+	//!used in the NoOS driver
+	enum ad5686_dac_channels
+		chan = (ad5686_dac_channels)selectChannel(selected_dac);
+
+	ad5686_write_update_register(device, chan, vdata);
+}
+
+/*************************************************************************//**
+ * @brief				- Write a value to the select_dac
+ *
+ * @param selected_dac	- Selected DAC (1,2,4,8 -> DAC A,B,C,D)
+ * @param vRef			- Reference voltage
+ *
+ * @return			    - currently active channel
+*****************************************************************************/
+static uint8_t selectChannel(uint16_t selectedDac)
+{
+	enum ad5686_dac_channels chan;
+	switch (selectedDac)
+	{
+	case 1  : {chan = AD5686_CH_0; break; }
+	case 2  : {chan = AD5686_CH_1; break; }
+	case 4  : {chan = AD5686_CH_2; break; }
+	case 8  : {chan = AD5686_CH_3; break; }
+	case 16 : {chan = AD5686_CH_4; break; }
+	case 32 : {chan = AD5686_CH_5; break; }
+	case 64 : {chan = AD5686_CH_6; break; }
+	case 128: {chan = AD5686_CH_7; break; }
+	default: {
+			break;
+		}
+	}
+	return (uint8_t)chan;
+
+}
+
+/*************************************************************************//**
+ * @brief				- Configure the power-down mode
+ *
+ * @param selected_dac	- Selected DAC (1,2,4,8 -> DAC A,B,C,D)
+ * @param vRef			- Reference voltage
+ *
+ * @return			    - PASS/FAIL flag - currently unused
+*****************************************************************************/
+static int8_t menu_5_power_down_mode(int16_t selected_dac)
+{
+	// Cancel if no DAC selected
+	if(selected_dac == 0)
+	{
+		pc.printf("  No DAC selected, no changes made");
+		return FAILURE;
+	}
+
+	// Prompt for power mode
+	printf("\n  Power Modes:\n");
+	printf("    1-Normal Operation\n");
+	printf("    2-1kOhm to GND Power-Down\n");
+	printf("    3-100kOhm to GND Power-Down\n");
+	printf("    4-Three-State Power-Down\n");
+	printf("  Select a power mode: ");
+
+	// Get input
+	int mode_input;
+	int inp = pc.scanf("%1d", &mode_input);
+	if (inp == 0)
+	{
+		pc .printf("*****   Invalid entry: ignoring *****\n");
+		wait(3);
+	}
+	
+
+	uint8_t selected_mode = 0;
+
+	// Basic input validation
+	if(mode_input > 4 || mode_input < 1)
+	{
+		printf("Invalid selection - no changes made\n");
+		wait(2);
+		return SUCCESS;
+	}
+	else
+		// Show validated input on console
+		pc.printf("\nSelected DAC: %d", mode_input);
+
+	// Select proper power mode
+	switch(mode_input)
+	{
+	case 1:
+		selected_mode = AD5686_PWRM_NORMAL;
+		break;
+
+	case 2:
+		selected_mode = AD5686_PWRM_1K;
+		break;
+
+	case 3:
+		selected_mode = AD5686_PWRM_100K;
+		break;
+
+	case 4:
+		selected_mode = AD5686_PWRM_THREESTATE;
+		break;
+
+	default:
+		break;
+	}
+
+	// Check bit-wise which DACs are selected
+	uint8_t dac1 = (selected_dac >> 0) & 1;
+	uint8_t dac2 = (selected_dac >> 1) & 1;
+	uint8_t dac3 = (selected_dac >> 2) & 1;
+	uint8_t dac4 = (selected_dac >> 3) & 1;
+
+	// Apply power to selected DACS
+	if(dac1)
+	{
+		pc.printf("  Applying power mode to DAC A...");
+		ad5686_power_mode(device, AD5686_CH_0, selected_mode);
+	}
+	if (dac2)
+	{
+		pc.printf("  Applying power mode to DAC B...");
+		ad5686_power_mode(device, AD5686_CH_1, selected_mode);
+	}
+	if (dac3)
+	{
+		pc.printf("  Applying power mode to DAC C...");
+		ad5686_power_mode(device, AD5686_CH_2, selected_mode);
+	}
+	if (dac4)
+	{
+		pc.printf("  Applying power mode to DAC D...");
+		ad5686_power_mode(device, AD5686_CH_3, selected_mode);
+	}
+
+	pc.printf("  Done!");
+
+	return SUCCESS;
+}
+
+/*************************************************************************//**
+ * @brief				- Select internal or external reference
+ *
+ * @param vRef			- Reference voltage
+ *
+ * @return			    - PASS/FAIL flag - currently unused
+*****************************************************************************/
+static int8_t menu_6_select_ref_voltage(float *vref)
+{
+	// Prompt for internal or external
+	pc.printf("  1-Internal (2.5v)\n");
+	pc.printf("  2-External\n");
+	pc.printf("  Select a reference voltage source:");
+
+	int vref_source;
+	int inp = pc.scanf("%1d", &vref_source);
+	if (inp == 0)
+	{
+		pc .printf("*****   Invalid entry: ignoring *****\n");
+		wait(3);
+	}
+
+	if (vref_source == INTERNAL)
+		pc.printf("\nInternal selected\n");
+	else if (vref_source == EXTERNAL)
+		pc.printf(" External selected\n");
+	else
+	{
+		pc.printf("\nInvalid Entry: No changes made\n");
+		wait(2);
+		return FAILURE;
+	}
+
+
+	float fvref = 0;  // Custom vref
+
+	switch(vref_source)
+	{
+	case 1:
+		*vref = 2.5;
+		break;
+
+	case 2:
+		// If external, prompt for exact vref
+		pc.printf("  Enter selected external reference voltage:");
+		inp = pc.scanf("%f", &fvref);
+		if (inp == 0)
+		{
+			pc .printf("*****   Invalid entry: ignoring *****\n");
+			wait(3);
+		}
+		pc.printf("%fV selected\n", fvref);
+		*vref = fvref;
+		wait(2);
+		break;
+
+	default:
+		pc.printf("  Incorrect entry\n");
+		wait(2);
+		break;
+	}
+
+	return SUCCESS;
+
+}
+
+
+/*************************************************************************//**
+ * @brief				- Reads back all DAC registers 
+*****************************************************************************/
+static void menu_7_read_back_registers()
+{
+	uint32_t reg1 = ad5686_read_back_register(device, AD5686_CH_0);
+	uint32_t reg2 = ad5686_read_back_register(device, AD5686_CH_1);
+	uint32_t reg3 = ad5686_read_back_register(device, AD5686_CH_2);
+	uint32_t reg4 = ad5686_read_back_register(device, AD5686_CH_3);
+
+	pc.printf("\n  All DAC register values:\n");
+	pc.printf("    DAC A -  %x\n", (unsigned int) reg1);
+	pc.printf("    DAC B -  %x\n", (unsigned int) reg2);
+	pc.printf("    DAC C -  %x\n", (unsigned int) reg3);
+	pc.printf("    DAC D -  %x\n", (unsigned int) reg4);
+}
+
+/*************************************************************************//**
+ * @brief				- Set the LDAC mask bits
+ *
+ * @return			    - PASS/FAIL flag - currently unused
+*****************************************************************************/
+static int8_t menu_8_set_ldac_mask()
+{
+	int enable;
+	int inp;
+	enum ad5686_dac_channels channel;
+
+	pc.printf("\n  Enter channel to update as a decimal number (0-n)\n");
+	pc.printf("  If masked, selected channel will not be updated when LDAC is asserted\n");
+	pc.printf("  Channel: ");
+	inp =  pc.scanf("%2d", (int *)&channel);
+		if (inp == 0)
+		{
+			pc .printf("*****   Invalid entry: ignoring *****\n");
+			wait(3);
+		}
+
+	pc.printf("\n  Enter LDAC mask value (1 set, 0 clear) as a decimal number\n");
+	pc.printf("  Mask: ");
+
+	inp = pc.scanf("%1d", &enable);
+	if (inp == 0)
+	{
+		pc .printf("*****   Invalid entry: ignoring *****\n");
+		wait(3);
+	}
+
+	switch (enable)
+	{
+	case 0: pc.printf("\n\nClearing LDAC mask\n"); break;
+	case 1: pc.printf("\n\nSettting LDAC mask\n"); break;
+	default:
+		pc.printf("\n\nInvalid entry: No changes made\n");
+		return FAILURE;
+	}
+
+	if (enable) pc.printf("\n\nSet LDAC mask for channel %d\n", channel);
+	else pc.printf("Cleared LDAC mask for channel %d\n", channel);
+
+	ad5686_ldac_mask(device, channel, enable);
+
+	return SUCCESS;
+}
+
+/*************************************************************************//**
+ * @brief				- Toggle the LDAC pin and update the DAC(s)
+*****************************************************************************/
+static void menu_9_assert_ldac()
+{
+	gpio_direction_output(device->gpio_ldac, GPIO_LOW);
+	// Wait to allow for controller latency
+	wait(0.1);  
+	gpio_direction_output(device->gpio_ldac, GPIO_HIGH);
+	pc.printf("  Asserted LDAC\n");
+}
+
+/*************************************************************************//**
+ * @brief				- Set the GAIN pin
+ *
+ * @return			    - PASS/FAIL flag - currently unused
+*****************************************************************************/
+static int8_t menu_10_set_gain()
+{
+	pc.printf("  GAIN options: \n");
+	pc.printf("    1-Low gain (1x)\n");
+	pc.printf("    2-High gain (2x)\n");
+	pc.printf("  Make selection: \n");
+
+	int selected_gain;
+	int inp = pc.scanf("%d", &selected_gain);
+	if (inp == 0)
+	{
+		pc .printf("*****   Invalid entry: ignoring *****\n");
+		wait(3);
+	}
+	if (selected_gain > 2 || selected_gain < 1)
+	{
+		pc.printf("Invalid selection - no changes made\n");
+		wait(2);
+		return FAILURE;
+	}
+	else
+		pc.printf("Selected gain: %d\n", selected_gain);
+
+
+	switch (selected_gain)
+	{
+	case 1:
+		//AD5686_GAIN_LOW;
+	    gpio_gain.id = NOT_USED;
+		gpio_set_value(&gpio_gain, GPIO_LOW); 
+		pc.printf("  Setting gain low");
+		gpioGainVal = 1;
+		
+		break;
+
+	case 2:
+		gpio_set_value(device->gpio_gain, GPIO_HIGH);
+		pc.printf("  Setting gain high\n");
+		gpioGainVal = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return SUCCESS;
+}
+
+/*************************************************************************//**
+ * @brief				- Do a soft (software) reset
+*****************************************************************************/
+static void menu_11_assert_soft_reset()
+{
+	pc.printf("  Performing software reset\n");
+	ad5686_software_reset(device);
+}
+
+/*************************************************************************//**
+ * @brief				- Do a hardware (gpio) reset
+*****************************************************************************/
+static void menu_12_assert_hard_reset()
+{
+	// Pull reset low then high
+	pc.printf("  Performing hardware reset\n");
+	gpio_direction_output(device->gpio_reset, GPIO_LOW);
+	// Wait to allow for controller latency
+	wait(0.1); 
+	gpio_set_value(device->gpio_reset, GPIO_HIGH);
+
+}
+
+/*************************************************************************//**
+ * @brief				- Configure the GPIO pins to default values
+*****************************************************************************/
+static void set_default_pins()
+{
+	gpio_set_value(device->gpio_reset, GPIO_HIGH);
+	gpio_set_value(device->gpio_gain, GPIO_LOW);
+	gpio_set_value(device->gpio_ldac, GPIO_LOW);
+}
+
+/*************************************************************************//**
+ * @brief Gets a voltage from the user and converts 
+ *		  it to the code the DAC understands
+ *
+ * @param vRef	- voltage value to convert - 0 to VREF
+ *
+ * @return		- corrosponding code value
+*****************************************************************************/
+static uint16_t get_voltage_code(float vRef)
+{
+	return voltage_to_code(get_voltage_float(), vRef);
+}
+
+/*************************************************************************//**
+ * @brief			- Convert voltage float to code the DAC understands
+ *
+ * @param voltage	- voltage value to convert - 0 to VREF
+ * @param vRef		- Reference voltage
+ *
+ * @return			- corrosponding code value
+*****************************************************************************/
+static uint16_t voltage_to_code(float voltage, float vRef)
+{
+
+	pc.printf("GAIN PIN STATE: %d\n", gpioGainVal);
+	if (gpioGainVal == GPIO_HIGH) 
+		vRef *= 2;
+
+	uint32_t max_code = ((uint32_t)1 << 16) - 1;
+	return (unsigned short)(voltage * (float)max_code / vRef);
+}
+
+/*************************************************************************//**
+ * @brief		- Gets a voltage from the user
+ *		
+ * @return		- voltage as a float
+*****************************************************************************/
+static float get_voltage_float()
+{
+	float dac_voltage;
+	pc.printf("  Enter Desired DAC output voltage: ");
+	wait_ms(1);
+	int inp = pc.scanf("%f", &dac_voltage);
+	if (inp == 0)
+	{
+		pc .printf("*****   Invalid entry: ignoring *****\n");
+		wait(3);
+	}
+    pc.printf("%f V\n", dac_voltage);
+
+	return dac_voltage;
+}
+