Initial Commit

Dependencies:   AD5686

main.cpp

Committer:
ssmith73
Date:
2019-05-28
Revision:
1:384a1737b0df

File content as of revision 1:384a1737b0df:

/*************************************************************************//**
 *   @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;
}