/**********************************************************************
  BL2600_VI_Engine.c Z-World - 2004

  This sample program exchanges data with the LabVIEW
  Virtual Instrument BL2600_VI_01.VI

  Instructions:
  1) Set the correct IP address in TCP_CONFIG.LIB
  2) Make the following connections on the BL2600:

       Digital I/O           High Cur. Digital I/O   Analog I/O
       J3:DIO00 -- J3:DN16   J13:HOUT0 -- J3:DN28    J11:AN0 -- J11:AV0
       J3:DIO01 -- J3:DN17   J13:HOUT1 -- J3:DN29    J11:AN1 -- J11:AV1
       J3:DIO02 -- J3:DN18   J13:HOUT2 -- J3:DN30    J11:AN2 -- J11:AV2
       J3:DIO03 -- J3:DN19   J13:HOUT3 -- J3:DN31    J11:AN3 -- J11:AV3
       J3:DIO04 -- J3:DN20
       J3:DIO05 -- J3:DN21    (You need not make all these connections to
       J3:DIO06 -- J3:DN22     try this program. The loop-backs will allow
       J3:DIO07 -- J3:DN23     show inputs changing from outputs set on the
       J3:DIO08 -- J3:DN24     VI panel. You can use use external I/O
       J3:DIO09 -- J3:DN25     instead.)
       J3:DIO10 -- J3:DN26
     	 J3:DIO11 -- J3:DN27

   3) Compile and run this program.
   4) On a PC connected to the same network, either run LabVIEW and
      open and run BL2600_VI_01.VI, or run BL2600_VI_01.EXE
      ( requires installation of LabVIEW run-time support). See Application
      Note AN407.

  Application note AN408 will present a more versatile LabVIEW VI Engine
  with a RabbitWeb interface for configuration.

  This Program was based on a Dynamic C/LabVIEW program written for
  the BL2100 by Tom Kaminski of Madison Area Technical College,
  Madison Wisconsin
**********************************************************************/

#define TCPCONFIG 1
#use "dcrtcp.lib"

//#define LV_VERBOSE

#define LVTIMEOUT 2500L   // Abort LV socket when data not received after this
                          // interval

#define PORT 695          // Port in use by the LabView TCP function

#define LV_PASSWORD "BL2600 BL2600\r\n"  // Hardcode LabVIEW VI password here

void main()
{
	auto int bytes_read, i;
	auto long digOutBitsReceived, digInBitsToSend, mask;
	auto char buffer[56];             // TCP Character buffer
	auto char *t_ptr, **T_ptr ;       // Needed for strtod and strtol calls
	auto float voltage[4], current[4];
	auto char outstring[120];
   auto int accessGranted;
	auto tcp_Socket socket;           // TCP socket variable
   auto unsigned long lastReadTime;

   brdInit();                        // Initialize BL2600
	sock_init();                      // Initialize the Socket structure
   digOutConfig(0xFFFF);             // Configure Outputs
   digHoutConfig(0);                 // Configure HC Outputs
   digHTriStateConfig(0);
   anaOutConfig(0,0);
   anaInConfig(0,1);
   anaInConfig(1,1);
   anaInConfig(2,1);
   anaInConfig(3,1);

	while(1) {              // Loop forever

     // Make sure Ethernet is ready
     while (ifpending(IF_DEFAULT) == IF_COMING_UP){
        tcp_tick(NULL);
     }

     // Wait for TCP open call from VI client
	  tcp_listen(&socket,PORT,0,0,NULL,0);

#ifdef LV_VERBOSE
	  printf("Waiting for connection...\n");
#endif
  	  while(!sock_established(&socket)){
         tcp_tick(NULL);
     }
     while(sock_bytesready(&socket)==-1){
         tcp_tick(NULL);
     }

     // Read password
     memset(buffer,0,sizeof(buffer));
 	  if((bytes_read = sock_fastread(&socket,buffer,35))== -1){
        // Abort.
        break;
     }
     accessGranted = 0;

     // **** Verify password  ****
	  if(bytes_read >= 2) {
        if(!strcmp(buffer, LV_PASSWORD)){
           if(sock_write(&socket,"ACKPW",strlen("ACKPW"))==strlen("ACKPW"))
           {
              accessGranted = 1;
              lastReadTime = MS_TIMER;
           }
           else{
             break;
           }
        }
        else {
  	        if(sock_write(&socket,"NOACK",strlen("NOACK"))!=strlen("NOACK"))
           {
             break;
           }
        }
     }

#ifdef LV_VERBOSE
	  printf("Connection received...\n");
#endif
     if(accessGranted){
  		  do {
		 	bytes_read=sock_fastread(&socket,buffer,sizeof(buffer)-1);
         if(bytes_read==-1)break;
			if(bytes_read>0) {
 			   lastReadTime = MS_TIMER;
#ifdef LV_VERBOSE
			   printf("%s \n",buffer);  // Print data sent form LabView
#endif
			   t_ptr = &buffer[0] ;        // Set up pointer to scan data
			   T_ptr = &t_ptr ;            // Set up **ptr to next call

			   digOutBitsReceived = strtol(t_ptr, T_ptr, 10); // get DigOut values

            // Get analog values
            for(i=0;i<4;i++){
			      voltage[i] = strtod(t_ptr, T_ptr);  // Get DAC Ch0 data
            }

            //**** HC Digital output 0-4 values are received as bits 16-19
            //   of digOutBitsReceived
			  	for (i=19; i > 15; i--)           // Do all 4 DigHOut channels
			  	{
               // Set Channels
              digHout(i-16,(long)((1L << i) & digOutBitsReceived) ? 1:0 );
			   }

            //**** Digital output 0-15 values are received as bits 0-15
            //   of digOutBitsReceived
			  	for (i=15; i > -1; i--)
			  	{
               // Set Channels
               digOut(i,(long)((1L << i) & digOutBitsReceived) ? 1:0 );
			   }

            //**** Set received analog values
            for(i=0;i<4;i++){
               anaOutVolts(i, voltage[i]);
            }
            anaOutPwr(1);

            //**** Digital inputs 16-31 are sent as bits 0-15 in digInBitsToSend
				digInBitsToSend = 0 ;
            mask = 0x8000;                      // mask bit is bit 15
				for(i=31; i > 15; i--)
				{
					if (digIn(i) == 1){
                  digInBitsToSend = digInBitsToSend | mask; // Set bit
               }
               mask = mask >> 1;                // shift mask bit right
				}

            //**** Construct output string ****
				sprintf(outstring,
                "%8.0f %10.3e %10.3e %10.3e %10.3e \xD\xA",
                (float)digInBitsToSend, anaInVolts(0,0), anaInVolts(1,0),
                anaInVolts(2,0), anaInVolts(3,0));

#ifdef LV_VERBOSE
				printf("%s",outstring);
#endif
            // Send the data
		      if(sock_write(&socket,outstring,strlen(outstring))==-1){
               break;
            }
		  	}  // End if bytes_read...
         else{
            if(MS_TIMER - lastReadTime >=LVTIMEOUT){
  			      // Data reception has stopped, abort
               break;
            }
          }
		 } while(tcp_tick(&socket));  //  End do loop
     } // End if(accessGranted)

     sock_abort(&socket);

#ifdef LV_VERBOSE
     printf("Connection closed...\n");
#endif
	} // End loop forever
}