

#include "Execute3dm.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "..\Process3dm\Execute3dxStruct.h"
 


extern int ServerNode(void);


FILE* file_3dx_fp; 
FILE* file_xyz_fp;

unsigned int NurbCount;

extern unsigned int CRC32(unsigned char, unsigned int);
extern unsigned int CRCend(unsigned int);


int main( int argc, const char *argv[] )
{



	const char* arg = argv[1];

    const char* sFileName = arg;




 
	if ( argc != 2)
	{
		printf("Syntax: %s <file_name>.3dx \n",argv[0] );
		exit(-1);
	}
	if(strcmp(".3dx", sFileName + strlen(sFileName) - 4) != 0)
	{
		printf("File must have extension \".3dx\"\n");
		exit(-1);
	}
	    // open file containing executible ORDER_PACKETS
    file_3dx_fp = fopen( sFileName, "rb");
    if ( !file_3dx_fp ) 
    {
      printf("Unable to open file %s.\n", sFileName);
	  exit(-1);
    }
		
		//Open the ".xyz" file for writing. "ClientKernel()"
		//uses this to store the generated points.
		//(name for output ".xyz" file point cloud import for Rhino3d)
	char * pXyzFileName = (char *) alloca(strlen(sFileName) + 20);
	strncpy(pXyzFileName, sFileName, strlen(sFileName) - 3);
	pXyzFileName[strlen(sFileName) - 3] = 0;
	strcat(pXyzFileName, "xyz");
		//create the executable file of the processed ".xyz" file
	file_xyz_fp = fopen(pXyzFileName, "wb+");
	if(!file_xyz_fp )
	{
		printf("Error...\n" );
		exit(-1);
	} 
	
		//go to the end of the data section of the file.
	if(fseek(file_3dx_fp, -4, SEEK_END))
	{
		printf("Error...\n" );
		exit(-1);
	}	 	
	unsigned int DataEnd = ftell(file_3dx_fp);
		//reset to the beginning
	if(fseek(file_3dx_fp, 0, SEEK_SET))
	{
		printf("Error...\n" );
		exit(-1);
	}		//generate the CRC on the file
	unsigned int vCRC32 = 0;
 	while((unsigned int) ftell(file_3dx_fp) < DataEnd)
	{
 
		vCRC32 = CRC32(fgetc(file_3dx_fp), vCRC32);
	}
 


	vCRC32 = CRCend(vCRC32);	
		//get CRC value.
	unsigned int vCRC32File;
	if(fread(&vCRC32File, sizeof(unsigned int), 1, file_3dx_fp) != 1)
	{
		printf("Error...\n" );
		exit(-1);
	}	//check generated against recorded value for CRC	
	if(vCRC32 != vCRC32File)
	{
		printf("Error...\n" );
		exit(-1);	
	}	
	
		//reset to the beginning
	if(fseek(file_3dx_fp, 0, SEEK_SET))
	{
		printf("Error...\n" );
		exit(-1);
	}
	
		//check magic number for ".3dx" file.
	unsigned int Magic3dxFile;
	if(fread(&Magic3dxFile, sizeof(unsigned int), 1, file_3dx_fp) != 1)
	{
		printf("Error...\n" );
		exit(-1);
	}	
	if(strncmp((const char *) &Magic3dxFile, MAGIC_3DX_FILE, 4) != 0)
	{
		printf("Error...\n" );
		exit(-1);
	}	//check version/rev.
	unsigned int VersionRev;
	if(fread(&VersionRev, sizeof(unsigned int), 1, file_3dx_fp) != 1)
	{
		printf("Error...\n" );
		exit(-1);
	}
	if(VersionRev != VERSION_REV_3DX)
	{
		printf("Error...\n" );
		exit(-1);
	}	//get NURB count.
	if(fread(&NurbCount, sizeof(unsigned int), 1, file_3dx_fp) != 1)
	{
		printf("Error...\n" );
		exit(-1);
	}	
	if(NurbCount < 1)
	{
		printf("Error...\n" );
		exit(-1);

	}




	if(!ServerNode())
		exit(-1);



	
		//Close the ".3dx" file.
	if( fclose( file_3dx_fp ) )
	{
    	printf("Error...\n" );
		exit(-1);   
	}


		//Close the ".xyz" file.
	if( fclose( file_xyz_fp ) )
	{
    	printf("Error...\n" );
		exit(-1);   
	}
		 





 



}



/*




								
								  --------------
			TO CPU <------------>|	IEEE1588    |
								 |	  TSU	    |						 -------------
                                  --------------  						|			  |
	----------------------------  			|	 						|             |
   |							|	        |     ---------			    |             |
   |							|	  RMII  |    |		   |			|			  |
   |	   MAC1					|----------------|   PHY   |------------|	ETHERNET  |
   |							|	             |         |		   -|	SWITCH	  |
   |							|	              ---------		 -----|-|   (LOCAL)   |
   |----------------------------|								|	  |	|			  |
   |							|	              ---------		|	  |	|             |
   |							|	  RMII       |		   |	|	  |	|			  |
   |	   MAC2					|----------------|   PHY   |----|--	  |	|			  |
   |							|	             |         |	|  |  |	|			  |
   |							|	              ---------		|  |  |	| 		      |
	----------------------------								|  |  |	 -------------
																|  |  |
																|  |  |
																|  |  |
																|  |  |
																|  |  |
																|  |  |
								  --------------				|  |  |
			TO CPU <------------>|	IEEE1588    |				|  |  |
								 |	  TSU	    |				|  |  |
                                  --------------				|  |  |
	----------------------------  			|					|  |  |
   |							|	        |     ---------		|  |  |
   |							|	  RMII  |    |		   |	|  |  |
   |	   MAC1					|----------------|   PHY   |----------
   |							|	             |         |    |  |
   |							|	              ---------	    |  |
   |----------------------------|					            |  | 
   |							|	              ---------	    |  |
   |							|	  RMII       |		   |    |  |
   |	   MAC2					|----------------|   PHY   |----|-----
   |							|	             |         |    |  |  |
   |							|	              ---------     |  |  |
	----------------------------								|  |  |
																|  |  |
																|  |  |
																|  |  |
																|  |  |
																|  |  |
																|  |  |
								  --------------				|  |  |
			TO CPU <------------>|	IEEE1588    |				|  |  |			 -------------
								 |	  TSU	    |				|  |  |			|			  |
                                  --------------				|  |  |			|             |
	----------------------------  			|					|  |  |			|             |
   |							|	        |     ---------		|  |  |			|			  |
   |							|	  RMII  |    |		   |	|  |  |			|	ETHERNET  |
   |	   MAC1					|----------------|   PHY   |----   |  |			|	SWITCH	  |
   |							|	             |         |	   |  |			|   (GLOBAL)  |---- (TO OUTSIDE WORLD)
   |							|	              ---------		   |  |			|			  |
   |----------------------------|								   |  |			|             |   
   |							|	              ---------		   |   ---------|			  |
   |							|	  RMII       |		   |	    ------------|			  |
   |	   MAC2					|----------------|   PHY   |--------------------|			  |
   |							|	             |         |					| 		      |
   |							|	              ---------						 -------------
	----------------------------

				.									.
				.                                   .
				.                                   .
				.                                   .
				.                                   .





	- IEEE 1588 based design.

	- A highly deterministic mode with a "local" ethernet switch to control
      motion control packet delivery and a "global" ethernet switch is
	  used for outside communications.

	  Both MAC's are used on the 440EP in this mode, where the non-IEEE1588
	  MAC is used for "outside" communications.
	

	- For less deterministic control, one MAC per 440EP is used with one
	  ethernet switch.

	  Both outside and IEEE1588 traffic runs on one network.

	  The ethernet switch provides some filtering of outside traffic.

	
	
	- Both methods described above use the SAME protocol for delivery of
	  motion control packets.

	  All motion control packets are "TCP\IP" based (even when using the
	  the highly determistic "local" connection.
	
	
	
	- The IEEE 1588 TSU is implemented with a protion of the on board
	  FPGA.
	
	
	
	
	I review document "C:\Rhino3D\Project-Documentation\IEEE1588-Docs\PPC440EP_UM2000_v1_19.pdf".
	Both Ethernet MAC'S are completely independent.

	The use a DMA type "MAL" controller to read and write the MAC's FIFOS.

	There is no type of hardware repeater mechanism to loop the input of one MAC to the output
	of the other, so an Ethernet switch must be used to connect ajacent nodes.

    I reviewed "C:\Rhino3D\Project-Documentation\IEEE1588-Docs\tutorial-basic.pdf" to get a 
	refresher on "IEEE1588" protocol.

	I reviewed "C:\Rhino3D\Project-Documentation\IEEE1588-Docs\rmii_1_2.pdf and mmi_to_rmii.pdf" to
	get a feeling of what it will take to design the "IEEE1588 TSU" FPGA logic and connect it
	to the RMII MAC/PHY interface.

	This may not be too difficult!!!
	
	
	Now, before I outline the methodogy of how motion control packets (ORDER_OBJECTS)
	are passed, we make the assumption that the IEEE 1588 protocol is running in
	the backround and ALL FPGA "clocks" of all slave units are being maintained at the
	to have the same value (or as close to the save value as possible).

	With this assumtion, we make the additional assumtion that the "kernel" interrupts
	are occuring together on all units.
	
	(Remember, the regularity of the IEEE1588 update is not important in this protocol, but
	 it is assumed that the updates are happening at intervals of low priority. In other
	 words, the transmittion of "ORDER_PACKET's" has higher priority then the transmittion
	 of IEEE 1588 maintaince commands).


	What is missing at this point, is the method to control trajectory rate.


						1) - Control Accel/Decel at the beginning and end of the
						     the IMAGE_3DX object.

					    2) - Control of constant vector velocity along the path
						     of the curve.
	

	At this point I cannot see if item "2" above (see "Notes-On-Rhino3d.txt") is
	an issue anymore now that I descovered that the values of the knot vectors
	themselves represent the distance (length) along the curve.

	Does anything have to be done? I know by looking at the ".dmp" files that
	taking two ajacent arcs (which were converted to NURBS) with different 
	radius, and joining them together such that the connecting point is
	tangent, I need only take the total length specified by the knot
	vectors of both arcs, add them together, and divide by the "desired"
	time of execution, to obtain the value of "constant" vector velocity.

	Is this true for the generalized (free hand) NURBS as well?

	Item "1" above, (which has not been address), may be accomplished by
	making the "reference" itself a "two-dimension" NURBS, with the "Y"
	axis being "total" length, and the "X" axis being "time".
	reference "time" itself.

	The reference to this NURBS is "time to execute the lenght of the
	control curve".

	For example, to produce a "trapazoidal" ramping function, the following would
	have to be calulcated.



	

			|
			|
			|
			|
			|
			|		   x1
			|		   |	
			|          |
			|	y1 --  ************......
			|		  *
			|		 *
			|		 *
			|		*
			|       *
			|       *
			|       *
			|	   *
		y	|      *
			|      *
			|      *
			|     *  		
			|     *
			|     *
			|     *
			|    * 
			|    *
			|    *
			|	 *
			|	*
			|	*
			|	*
			|	*
			|  *		
			|  *
			|**
		     -----------------------------------------------------------------------------

									x

					y1 - Total "length" of the "trajectory" NURBS curve (as indicated by knot vector)
                    x1 - Total time to execute "length" y1

					reference - "Total time to execute the length of the "control" NURBS curve"
					            (which would be the same time to execute the length of
								 the "trajectory" NURBS curve.


    We then use the value of "y" as the reference to the "trajectory" NURBS curve.

	What is involved here is that be must determine the values of the control
	points P(x,y) and knots that construct the curve above.

	This is kind of messy when considering that these points are parameters of
	a given trajectory (e.g, there are variables).

	However, there is payoff to this complexity.

	Complex velocity control along the "trajectory" NURBS curve can be achieved
	using this method.

	For instance, a "control" curve could be construct to actually  reverse
	direction (or oscillate) on a certain portion of the the "tarjectory"
	curve before finishing at the final destination.


			|
			|
			|
			|
			|							
			|							     x1
			|							     |	
			|						         |
			|						  y1 --  ************......
			|								*
			|							    *
			|							   *
			|							   *
			|						       *
			|						       *
			|						      *
			|							  *
		y	|						      *
			|						      *
			|						     *
			|       		            *
			|      **        **        *
			|     *  *      *  *      *
			|     *   *    *    *    *
			|    *     *  *      *  *
			|    *      **        **
			|    *
			|	 *
			|	*
			|	*
			|	*
			|	*
			|  *		
			|  *
			|**
		     -----------------------------------------------------------------------------

									x




	Because of the complex involved in constructing a "control" NURBS, we not concern
	ourselves with trajectory control in this simulation.

	All "trajectory" curves in this simulation will run at constant velocity (e.g., 
	no accel/decel control).




	Now, we dicuss the method of "ORDER_PACKET" delievery to the slave nodes.





	(add)
	?????????????????????????????????????????????

	As far as the methodology of up updating the the "Slave" node's reference counter with the IEEE1588
	calculated time, I have outlined some ideas below.

		Once the the "masters" reference counter value is determined by way of the IEEE1588 protocol, it is stored
		in a register in the slave unit that is updated with the SAME clock source as the slaves 
		reference counter (In other words, this value is NOT directly loaded into the slaves reference counter.

		When the masters reference counter is determined, one of two conditions exist relative to the slaves
		reference counter:

					- The value of the master's reference counter is "ahead" of the value of the current
					  slaves reference counter.

					- The value of the msters's reference counter is "behind" the value of the current
					  slaves reference counter.

		The method to correct the slaves reference counter is as follows:

					- Take the difference of the two counter values.

					- Add or subtract a count from the slave's refernence count depending on the
					  the polarity of the difference.

	    The procedure above is done at some predefined interval, at a rate that minimizes the effect
		of observing "jitter" on the slaves generated trajectory.




	????????????????????????????????????????????







*/
