/**********************************************************************
  BL2100_VI.c Z-World - 2005

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

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

       Digital I/O                    Analog I/O
       J13:OUT10 -- J11:IN10       J1:DA0 -- J1: AD0
       J13:OUT11 -- J11:IN11       J1:DA1 -- J1: AD1
       J13:OUT12 -- J11:IN12       J1:DA2 -- J1: AD2
       J13:OUT13 -- J11:IN13       J2:DA3 -- J1: AD3
       J13:OUT14 -- J11:IN14
       J13:OUT15 -- J11:IN15    (You need not make all these connections to
                                 try this program. The loop-backs will
       J7:OUT09 -- J11:IN09      show inputs changing from outputs set on the
       J7:OUT08 -- J11:IN08      VI panel. You can use use external I/O
       						         instead.)
       J7:OUT07 -- J4:IN07
       J7:OUT06 -- J4:IN06
       J7:OUT05 -- J4:IN05
       J7:OUT04 -- J4:IN04
       J7:OUT03 -- J4:IN03
       J7:OUT02 -- J4:IN02
       J7:OUT01 -- J4:IN01
       J7:OUT00 -- J4:IN00

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


      Once a socket has been established between the Rabbit, Labview,
      the Rabbit can send and receive data (in the form of a string) back
      and forth between Labview software on the PC and vica-versa.

  This Program was based on a Dynamic C/LabVIEW program written for
  the BL2100 by Tom Kaminski of Madison Area Technical College,
  Madison Wisconsin
**********************************************************************/
#class auto
#define TCPCONFIG 1
#use "dcrtcp.lib"

#define LV_VERBOSE        // Define this to get a verbose listing of the
								  // transaction.

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

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

#define DA0	0              // Analog channel 0
#define DA1	1              // Analog channel 1
#define DA2 2					// Analog channel 2
#define DA3 3					// Analog channel 3

#define NUMB_ANA_INPUT     4          // Number of Analog inputs on the device

#define NUMB_ANA_OUTPUT    4          // Number of Analog outputs on the device


#define LV_PASSWORD "Rabbit Rabbit\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[NUMB_ANA_INPUT];
	auto char outstring[120];
   auto int accessGranted;
	auto tcp_Socket socket;           // TCP socket variable
   auto unsigned long lastReadTime;

   brdInit();                        // Initialize BL2100
   digOutConfig(0x0000);            //Initialize digital outputs sinking
	sock_init();                     // Initialize the Socket structure

   while(1) {              // Loop forever

     // Make sure Ethernet is ready
     while (ifpending(IF_DEFAULT) == IF_COMING_UP){
        tcp_tick(NULL);
     }
     //Make sure Ethernet is ready
     //This is called after the sock_init() function is called, it waits
     //for the ethernet chip to come up and negotiate things like fullduplex,
     //halfduplex, 10baseT, 100baseT with the connected device. Once the
     //hardware successfully negotiates, they are ready to communicate. Then
     //we wait until the Rabbit sets its network parameters or receives them
     //via DHCP. Once this is complete, the interface is up and ready to
     //communicate with other network applications like Labview. When we get
     //out of this loop, a socket is not establisehd, only the hardware
     //devices are ready to communicate.
     //
     //The Ifpending loop insures that the interface is up (The Ethernet chip
     //is stabilized and the Rabbit has an IP address). Then tcp_listen
     //is called to create the socket, allocate the appropriate socket
     //buffers, and listen for an incoming connectionon a particular port.
     //Then we poll on sock_establised while we wait for the Labview
     //device to establish a connection to use. Once this occurs, we move on.
     //Now we can read and write to the labview device via our socket. Once
     //we are done, the labview device closes the connection which causes
     //tcp_tick to return a 0 and will break out of the loop. Then we
     //abort the socket and the cycle starts again.....



     // 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            //Use this to get verbose listing of transaction
	  printf("Connection received...\n");
#endif
     if(accessGranted){
  		  do {
		 	bytes_read=sock_fastread(&socket,buffer,sizeof(buffer)-1);
         if(bytes_read==-1)break;
         //The sock_fastread function returns the following values:
         //-1 - there was an error, perhaps the other device has lost power,
         //and/or the socket connection was broken.
         //0 - there are no bytes received and the socket is ok.
         //Other number -- then this is the number of bytes received from
         //the other end of the socket.
			if(bytes_read>0) {
 			   lastReadTime = MS_TIMER;  // If there is data from VI host
#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

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


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

//The expression  ( (1L << i)  &  digOutBitsReceived )  tests one bit and
// is true if  the ith bit in digOutBitsReceived  is set:.

//(expression ? A : B) =  A if expression is true (non-zero),  B if expression
//is false (zero)

            //**** Set received analog values

            for(i=0; i < 4; i++)
            {
               anaOutVolts(i, voltage[i]);
            }

            //****Digitial inputs 0-15 are sent as bits 0-15 in digInBitsToSend on
            //the 2100

				digInBitsToSend = 0 ;
               										  //0x80 = 10000000 Binary
            //mask = 0x80;                      // mask bit is bit 7 for the 2500
              mask = 0x8000;                    //0x8000 = 1000000000000000
           for(i=15; i >= 0; i--)                //mask bit is bit 15 on the BL2100
				{
					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), anaInVolts(1),
                anaInVolts(2), anaInVolts(3));
            printf("String = %s   \n", outstring);



#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
}