/*********************************************************************
 *                 Flowcode ADC Type 6 Component Code
 *
 * File: PIC_ADC_6.c
 *
 * (c) 2009 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 110607 | BR | Created
 * 050707 | ST | Fixes to code
 * 130309 | BR | Moved Functions from FCD files into Component code files
 * 170409 | BR | Added ReadAsString Function
 * 130509 | BR | Added % definitions to DefinesCode section
 * 160609 | BR | Removed NumBytes Parameter from String Function
 *
 ********************************************************************/

/*********************************************************************

 Return & parameter types:
   void
   char
   short
   char*

 Pin directions:
   0 = OUTPUT
   2 = INPUT
   3 = BIDIRECTIONAL

**********************************************************************

[Settings]
CLSID={4FFA7653-1978-4FDA-8900-9DBF554C9255}
IsAnalogue=1
MultipleAllowed=1
Description=ADC Type 6 Flowcode Component

**********************************************************************

[MacroNames]
Count=5
1=SampleADC
2=ReadAsByte
3=ReadAsInt
4=ReadAsVoltage
5=ReadAsString

[MacroReturns]
1=void
2=char
3=short
4=float
5=char*

[MacroIsPrivate]
1=1
2=0
3=0
4=0
5=0

[MacroParameters_SampleADC]
Count=0

[MacroParamTypes_SampleADC]

[MacroParameters_ReadAsByte]
Count=0

[MacroParamTypes_ReadAsByte]

[MacroParameters_ReadAsInt]
Count=0

[MacroParamTypes_ReadAsInt]


[MacroParameters_ReadAsVoltage]
Count=0

[MacroParamTypes_ReadAsVoltage]


[MacroParameters_ReadAsString]
Count=0

[MacroParamTypes_ReadAsString]

 ********************************************************************/

/********************************************************************
 * ADDITIONAL CODE
 ********************************************************************/

/*DefinesCode_Start*/

/**** Macro Substitutions ****
%a = Which ADC Channel
%b = Acquisition time
%c = Conversion Speed
%d = VRef+ Option
%e = VRef Voltage x 0.01V
******************************/

/*DefinesCode_End*/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

/********************************************************************
 * FUNCTIONS
 ********************************************************************/

void SampleADC(void)
{
/*Macro_SampleADC_Start*/

/*******Supported Devices******************************************************************
// 16C72, 16C72A, 16CR72, 16F72, 16C73, 16C73A, 16C73B, 16F73, 16C74, 16C74A, 16C74B, 16F74,
// 16C76, 16F76, 16C77, 16F77, 16C716, 16F716
******************************************************************************************/

	#define MX_ADC_CHANNEL		%a
	#define MX_ADC_SAMP_TIME 	%b
	#define MX_ADC_CONV_SP		%c
	#define MX_ADC_VREF_OPT		%d

	//set up ADC conversion
	char old_tris, cnt;

	//find appropriate bit
	#if (MX_ADC_CHANNEL == 0)
		#define MX_ADC_TRIS_MSK  0x01
		#define MX_ADC_TRIS_REG  trisa
		adcon1 = 0x04;
	#endif
	#if (MX_ADC_CHANNEL == 1)
		#define MX_ADC_TRIS_MSK  0x02
		#define MX_ADC_TRIS_REG  trisa
		adcon1 = 0x04;
	#endif
	#if (MX_ADC_CHANNEL == 2)
		#define MX_ADC_TRIS_MSK  0x04
		#define MX_ADC_TRIS_REG  trisa
		adcon1 = 0x00;
	#endif
	#if (MX_ADC_CHANNEL == 3)
		#define MX_ADC_TRIS_MSK  0x08
		#define MX_ADC_TRIS_REG  trisa
		adcon1 = 0x04;
		#if (MX_ADC_VREF_OPT != 0)
			#pragma error "Target device is currently using AN3 for VREF+"
		#endif
	#endif
	#if (MX_ADC_CHANNEL == 4)
		#define MX_ADC_TRIS_MSK  0x20
		#define MX_ADC_TRIS_REG  trisa
		adcon1 = 0x00;
	#endif
	#if (MX_ADC_CHANNEL == 5)
		#define MX_ADC_TRIS_MSK  0x01
		#define MX_ADC_TRIS_REG  trise
		adcon1 = 0x00;
	#endif
	#if (MX_ADC_CHANNEL == 6)
		#define MX_ADC_TRIS_MSK  0x02
		#define MX_ADC_TRIS_REG  trise
		adcon1 = 0x00;
	#endif
	#if (MX_ADC_CHANNEL == 7)
		#define MX_ADC_TRIS_MSK  0x04
		#define MX_ADC_TRIS_REG  trise
		adcon1 = 0x00;
	#endif

	//sanity check
	#ifndef MX_ADC_TRIS_MSK
		#pragma error "ADC Type 6 conversion code error - please contact technical support"
	#endif

	//assign VREF functionality
	#if (MX_ADC_VREF_OPT != 0)
		adcon1 = adcon1 + 1;
	#endif

	//store old tris value, and set the i/o pin as an input
	old_tris = MX_ADC_TRIS_REG;
	MX_ADC_TRIS_REG = MX_ADC_TRIS_REG | MX_ADC_TRIS_MSK;

	//turn ADC on
	adcon0 = (0x01 | (MX_ADC_CONV_SP << 6)) | (MX_ADC_CHANNEL << 3);

	//wait the acquisition time
	cnt = 0;
	while (cnt < MX_ADC_SAMP_TIME) cnt++;

	//begin conversion and wait until it has finished
	adcon0 = adcon0 | 0x04;
	while (adcon0 & 0x04);

	//restore old tris value, and reset adc registers
	MX_ADC_TRIS_REG = old_tris;
	adcon1 = 0x07;
	adcon0 = 0x00;

	#undef MX_ADC_TRIS_REG
	#undef MX_ADC_TRIS_MSK
	#undef MX_ADC_SAMP_TIME
	#undef MX_ADC_CHANNEL
	#undef MX_ADC_CONV_SP
	#undef MX_ADC_VREF_OPT

/*Macro_SampleADC_End*/
}




char ReadAsByte(void)
{
/*Macro_ReadAsByte_Start*/

	SampleADC();

	return adres;

/*Macro_ReadAsByte_End*/
}



short ReadAsInt(void)
{
/*Macro_ReadAsInt_Start*/

	short iRetVal;

	SampleADC();

	iRetVal = (adres << 2);

	return (iRetVal);

/*Macro_ReadAsInt_End*/
}



float ReadAsVoltage()
{
/*Macro_ReadAsVoltage_Start*/

	char bLength;
	int iSample;
	float fSample, fVoltage, fVperDiv;

	#define MX_ADC_VREF_V		%e

	iSample = ReadAsInt();											//Read as 10-bit Integer

	fVoltage = float32_from_int32(MX_ADC_VREF_V);					//Convert reference voltage count to floating point (0 - 500 x 10mV)
	fVoltage = float32_mul(fVoltage, 0.01);							//Convert reference voltage count to actual voltage (0 - 5)
	fVperDiv = float32_mul(fVoltage, 0.000976);						//Convert actual voltage to voltage per division (VRef / 1024)
	fSample = float32_from_int32(iSample);							//Convert to floating point variable
	fVoltage = float32_mul(fSample, fVperDiv);						//Calculate floating point voltage

	#undef MX_ADC_VREF_V
	return (fVoltage);

/*Macro_ReadAsVoltage_End*/
}



void ReadAsString(char* FCR_RETVAL, char FCR_RETVAL_SIZE)
{
/*Macro_ReadAsString_Start*/

	float fVoltage;

	fVoltage = ReadAsVoltage();
	FCI_FLOAT_TO_STRING(fVoltage, 2, FCR_RETVAL, FCR_RETVAL_SIZE);	//Convert to String

/*Macro_ReadAsString_End*/
}