/********************************************************************************
 * File Name: GPIB.c				 											*
 * Creation: 02/04/2001 JCG														*
 * Purpose: This OriginC sample code demonstrates how to use Origin C routines	*
 * to access HP34401A Digital MultiMeter by GPIB.								*
 * Copyright (c) OriginLab Corp.	2002, 2003, 2004, 2005, 2006, 2007			*
 * All Rights Reserved															*
 ********************************************************************************/

#include <origin.h>  // Origin C general header file
#include <NI488-2.h> // Prototypes for the National Instrument NI488.2 GPIB routines and constants.

//////////////////////////////////////////////////////////////////////////////////////////////
// There are two functions in this Origin C demo code 
// void Run() 
// void GpibError(char *msg);  
// See function discription below.
//
// After compliling, your can type the "run" command in 
// command pane of code builder to execute this program.  
////////////////////////////////////////////////////////////////////////////////////////////// 

// Define a micro to print out the error message.
#define CHECK_ERROR	if (user_ibsta & ERR) { GpibError("ibwrt or ibrd Error"); return; }

// Prototype for function GpibError
void GpibError(char *msg);       				 /* Error function declaration             */

// Global variable for the GPIB card
int Device = 0;                  				 /* Device unit descriptor                 */
int BoardIndex = 0;               				 /* Interface Index (GPIB0=0,GPIB1=1,etc.) */

//////////////////////////////////////////////////////////////////////////////////////////////
// Function: void Run()
// Purpose: 1) open the GPIB device
//			2) write GPIB command to device and read data.
//			3) Take the device offline 
// Argument(s): none.
// Return: void
//////////////////////////////////////////////////////////////////////////////////////////////
void Run() 
{
	// Define a double type vector to store the data. 
	vector<double> data(20);

	// Primary address of the device.
	int   PrimaryAddress = 8;      				/* Can be read from NI GPIB explorer       */
	
	// Secondary address of the device   
	int   SecondaryAddress = 0;    				/* No secondary	address				       */
	
	char  Buffer[21];              				/* Read buffer                             */
 
	// Initialization - Done only once at the beginning of your application.  
	// The application brings the multimeter online using ibdev. A
	// device handle, Dev, is returned and is used in all subsequent
	// calls to the device.

	Device = ibdev(                				/* Create a unit descriptor handle         */
	    BoardIndex,                				/* Board Index (GPIB0 = 0) 			       */
	    PrimaryAddress,            				/* Device primary address 8                */
	    SecondaryAddress,          				/* No secondary address   	               */
	    T10s,                     				/* Timeout setting (T10s = 10 seconds)     */
	    1,                        				/* Assert EOI line at end of write         */
	    0);                       				/* EOS termination mode                    */           
	
	CHECK_ERROR					       			/* Check error                             */
	
	ibclr(Device);                    			/* Clear the device                        */
	CHECK_ERROR					      			/* Check error 							   */

	char beep[] = "SYST:BEEP"; 		   			/* Beep once 							   */
	ibwrt(Device, beep, sizeof(beep));    
	CHECK_ERROR					   	  			/* Check error							   */

	char disp[] = "DISP:TEXT 'ORIGIN C'"; 		/* Textout Origin C 					   */
	ibwrt(Device, disp, sizeof(disp));    
	CHECK_ERROR					       			/* Check error 							   */
	
	Sleep(1000);								/* Delay 1 s 							   */

	char demo[] = "DISP:TEXT 'GPIB DEMO'"; 		/* Textout GPIB Demo					   */
	ibwrt(Device, demo, sizeof(demo));    
	CHECK_ERROR					  				/* Check error 							   */

	Sleep(1000);								/* Delay 1 s 							   */ 
	
	char rst[] = "*RST";		    			/* Reset 								   */
	ibwrt(Device, rst, sizeof(rst));    
	CHECK_ERROR					   				/* Check error 							   */
	
	char cls[] = "*CLS";		   				/* Clear register 						   */
	ibwrt(Device, cls, sizeof(cls));    
	CHECK_ERROR					  				/* Check error 							   */
	
	char meas[] = "CONF:VOLT:DC 10";			/* Measure Mode : DC 1v range			   */
	ibwrt(Device, meas, sizeof(meas));    
	CHECK_ERROR					   				/* Check error 							   */
	
	char coun[] = "SAMP:COUN 1";  				/* Data Sample counts 					   */
	ibwrt(Device, coun, sizeof(coun));    
	CHECK_ERROR					  				/* Check error 							   */
		
	for( int ii = 0; ii < data.GetSize(); ii++)
	{
		char read[] = "READ?";		  			/* Read query 							   */ 
		ibwrt(Device, read, sizeof(read));    
		CHECK_ERROR					   			/* Check error 							   */
		
		ibrd(Device, Buffer, 20);      			/* Read up to 20 bytes from the device     */
		CHECK_ERROR					   			/* Check error 							   */
	
		printf(Buffer);				   

		Buffer[user_ibcntl] = '\0';    			/* Null terminate the ASCII string         */
		data[ii] = atof(Buffer);
		
		Sleep(100)	// 0.1 second
	}
	
	printf("Finished");
	
	ibwrt(Device, beep, sizeof(beep));    
	CHECK_ERROR					   				/* Check error 							   */

	char end[] = "DISP:TEXT 'FINISHED'";
	ibwrt(Device, end, sizeof(end));    
	CHECK_ERROR					   				/* Check error 							   */

	//Uninitialization - Done only once at the end of your application.
	ibonl(Device, 0);             				/* Take the device offline                 */
	CHECK_ERROR					  				/* Check error 							   */

	ibonl(BoardIndex, 0);          				/* Take the interface offline              */
	CHECK_ERROR					   				/* Check error 							   */
}


//////////////////////////////////////////////////////////////////////////////////////////////
// Function:void GpibError(char *msg); 
// Purpose:	This function will notify you that a NI-488 function failed by
// 			printing an error message.  The status variable user_ibsta will also be
// 			printed in hexadecimal along with the mnemonic meaning of the bit
// 			position. The status variable user_iberr will be printed in decimal
// 			along with the mnemonic meaning of the decimal value.  The status
// 			variable user_ibcntl will be printed in decimal.

// 			The NI-488 function IBONL is called to disable the hardware and
// 			software.
// Argumnent(s): msg the error message will be out put
// Return: void					
//////////////////////////////////////////////////////////////////////////////////////////////

void GpibError(char *msg) 
{
    printf ("%s\n", msg);

    printf ("ibsta = &H%x  <", user_ibsta);
    if (user_ibsta & ERR )  printf (" ERR");
    if (user_ibsta & TIMO)  printf (" TIMO");
    if (user_ibsta & END )  printf (" END");
    if (user_ibsta & SRQI)  printf (" SRQI");
    if (user_ibsta & RQS )  printf (" RQS");
    if (user_ibsta & CMPL)  printf (" CMPL");
    if (user_ibsta & LOK )  printf (" LOK");
    if (user_ibsta & REM )  printf (" REM");
    if (user_ibsta & CIC )  printf (" CIC");
    if (user_ibsta & ATN )  printf (" ATN");
    if (user_ibsta & TACS)  printf (" TACS");
    if (user_ibsta & LACS)  printf (" LACS");
    if (user_ibsta & DTAS)  printf (" DTAS");
    if (user_ibsta & DCAS)  printf (" DCAS");
    printf (" >\n");

    printf ("iberr = %d", user_iberr);
    if (user_iberr == EDVR) printf (" EDVR <DOS Error>\n");
    if (user_iberr == ECIC) printf (" ECIC <Not Controller-In-Charge>\n");
    if (user_iberr == ENOL) printf (" ENOL <No Listener>\n");
    if (user_iberr == EADR) printf (" EADR <Address error>\n");
    if (user_iberr == EARG) printf (" EARG <Invalid argument>\n");
    if (user_iberr == ESAC) printf (" ESAC <Not System Controller>\n");
    if (user_iberr == EABO) printf (" EABO <Operation aborted>\n");
    if (user_iberr == ENEB) printf (" ENEB <No GPIB board>\n");
    if (user_iberr == EOIP) printf (" EOIP <Async I/O in progress>\n");
    if (user_iberr == ECAP) printf (" ECAP <No capability>\n");
    if (user_iberr == EFSO) printf (" EFSO <File system error>\n");
    if (user_iberr == EBUS) printf (" EBUS <Command error>\n");
    if (user_iberr == ESTB) printf (" ESTB <Status byte lost>\n");
    if (user_iberr == ESRQ) printf (" ESRQ <SRQ stuck on>\n");
    if (user_iberr == ETAB) printf (" ETAB <Table Overflow>\n");

    printf ("ibcntl = %ld\n", user_ibcntl);
    printf ("\n");

    /* Call ibonl to take the device and interface offline */
    ibonl (Device,0);
    ibonl (BoardIndex,0);

    return;
}