etisserant@280: /**
etisserant@280:  * Win32 specific code
etisserant@280:  **/ 
etisserant@280: 
greg@205: #include <stdio.h>
greg@205: #include <sys/timeb.h>
greg@205: #include <time.h>
greg@205: #include <windows.h>
greg@205: 
etisserant@280: /* provided by POUS.C */
etisserant@280: extern int common_ticktime__;
etisserant@280: 
greg@244: long AtomicCompareExchange(long* atomicvar, long compared, long exchange)
greg@205: {
greg@205:     return InterlockedCompareExchange(atomicvar, exchange, compared);
greg@205: }
greg@205: 
greg@205: struct _timeb timetmp;
greg@205: void PLC_GetTime(IEC_TIME *CURRENT_TIME)
greg@205: {
greg@205: 	_ftime(&timetmp);
greg@205: 	
greg@205: 	(*CURRENT_TIME).tv_sec = timetmp.time;
greg@205: 	(*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000;
greg@205: }
greg@205: 
greg@205: void PLC_timer_notify()
greg@205: {
greg@205:     PLC_GetTime(&__CURRENT_TIME);
greg@205:     __run();
greg@205: }
greg@205: 
greg@205: HANDLE PLC_timer = NULL;
greg@205: void PLC_SetTimer(long long next, long long period)
greg@205: {
greg@229: 	LARGE_INTEGER liDueTime;
greg@205: 	/* arg 2 of SetWaitableTimer take 100 ns interval*/
greg@205: 	liDueTime.QuadPart =  next / (-100);
greg@205: 	
greg@205: 	/*
greg@205: 	printf("SetTimer(%lld,%lld)\n",next, period);
greg@205: 	*/
greg@205: 	
greg@205: 	if (!SetWaitableTimer(PLC_timer, &liDueTime, common_ticktime__, NULL, NULL, 0))
greg@205:     {
greg@205:         printf("SetWaitableTimer failed (%d)\n", GetLastError());
greg@205:     }
greg@229: }
greg@229: 
greg@229: /* Variable used to stop plcloop thread */
greg@229: int runplcloop;
greg@229: void PlcLoop()
greg@229: {
greg@229: 	runplcloop = 1;
greg@229: 	while(runplcloop)
greg@229: 	{
greg@229: 	// Set a timer
greg@229: 	PLC_SetTimer(Ttick,Ttick);
greg@205: 	if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0)
greg@205: 	{
greg@205: 		printf("WaitForSingleObject failed (%d)\n", GetLastError());
greg@205: 	}
greg@205: 	PLC_timer_notify();
greg@229: 	}
greg@205: }
greg@205: 
greg@229: HANDLE PLC_thread;
greg@244: HANDLE debug_sem;
etisserant@280: HANDLE debug_wait_sem; 
etisserant@280: HANDLE python_sem;
etisserant@280: HANDLE python_wait_sem; 
etisserant@280: 
etisserant@280: #define maxval(a,b) ((a>b)?a:b)
greg@229: int startPLC(int argc,char **argv)
greg@205: {
greg@229: 	unsigned long thread_id = 0;
greg@205: 	/* Translate PLC's microseconds to Ttick nanoseconds */
greg@205: 	Ttick = 1000000 * maxval(common_ticktime__,1);
greg@205: 
greg@244: 	debug_sem = CreateSemaphore( 
greg@244: 							NULL,           // default security attributes
greg@244: 					        1,  			// initial count
etisserant@280: 					        1,  			// maximum count
greg@244: 					        NULL);          // unnamed semaphore
greg@244:     if (debug_sem == NULL) 
greg@244:     {
etisserant@280:         printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
greg@244:         return;
greg@244:     }
greg@244:     
etisserant@280: 	debug_wait_sem = CreateSemaphore( 
greg@244: 					        NULL,           // default security attributes
greg@244: 					        0,  			// initial count
etisserant@280: 					        1,  			// maximum count
etisserant@280: 					        NULL);          // unnamed semaphore
etisserant@280: 
etisserant@280:     if (debug_wait_sem == NULL) 
etisserant@280:     {
etisserant@280:         printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError());
etisserant@280:         return;
etisserant@280:     }
etisserant@280: 
etisserant@280: 	python_sem = CreateSemaphore( 
etisserant@280: 					        NULL,           // default security attributes
etisserant@280: 					        1,  			// initial count
etisserant@280: 					        1,  			// maximum count
etisserant@280: 					        NULL);          // unnamed semaphore
etisserant@280: 
etisserant@280:     if (python_sem == NULL) 
etisserant@280:     {
etisserant@280:         printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
etisserant@280:         return;
etisserant@280:     }
etisserant@280: 	python_wait_sem = CreateSemaphore( 
etisserant@280: 					        NULL,           // default security attributes
etisserant@280: 					        0,  			// initial count
etisserant@280: 					        1,  			// maximum count
etisserant@280: 					        NULL);          // unnamed semaphore
etisserant@280: 
etisserant@280: 
etisserant@280:     if (python_wait_sem == NULL) 
etisserant@280:     {
etisserant@280:         printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError());
etisserant@280:         return;
etisserant@280:     }
etisserant@280: 
greg@229: 	
greg@205: 	/* Create a waitable timer */
greg@205:     PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
greg@205:     if(NULL == PLC_timer)
greg@205:     {
greg@205:         printf("CreateWaitableTimer failed (%d)\n", GetLastError());
greg@205:         return 1;
greg@205:     }
greg@205:     if( __init(argc,argv) == 0 )
greg@205:     {
greg@205:     	printf("Tick Time : %d ms\n", common_ticktime__);
greg@229:     	PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id);
greg@205:     }
greg@229:     else{
greg@229:     	return 1;
greg@229:     }
greg@205:     return 0;
greg@205: }
greg@244: static int __debug_tick;
greg@244: 
greg@244: int TryEnterDebugSection(void)
greg@244: {
greg@244: 	//printf("TryEnterDebugSection\n");
greg@244: 	return WaitForSingleObject(debug_sem, 0) == WAIT_OBJECT_0;
greg@244: }
greg@244: 
greg@244: void LeaveDebugSection(void)
greg@244: {
greg@244: 	ReleaseSemaphore(debug_sem, 1, NULL);
greg@244:     //printf("LeaveDebugSection\n");
greg@244: }
greg@229: 
greg@229: int stopPLC()
greg@229: {
greg@229: 	runplcloop = 0;
greg@229: 	WaitForSingleObject(PLC_thread, INFINITE);
greg@244: 	__cleanup();
greg@244: 	__debug_tick = -1;
etisserant@280: 	ReleaseSemaphore(debug_wait_sem, 1, NULL);
greg@244: 	CloseHandle(debug_sem);
etisserant@280: 	CloseHandle(debug_wait_sem);
greg@244: 	CloseHandle(PLC_timer);
greg@229: 	CloseHandle(PLC_thread);
greg@229: }
greg@229: 
greg@229: /* from plc_debugger.c */
greg@244: int WaitDebugData()
greg@229: {
etisserant@280: 	WaitForSingleObject(debug_wait_sem, INFINITE);
greg@244: 	return __debug_tick;
greg@229: }
greg@229:  
etisserant@280: /* Called by PLC thread when debug_publish finished
greg@229:  * This is supposed to unlock debugger thread in WaitDebugData*/
greg@229: void InitiateDebugTransfer()
greg@229: {
greg@244:     /* remember tick */
greg@244:     __debug_tick = __tick;
greg@244:     /* signal debugger thread it can read data */
etisserant@280:     ReleaseSemaphore(debug_wait_sem, 1, NULL);
greg@229: }
greg@244: 
greg@244: void suspendDebug()
greg@244: {
greg@244:     /* Prevent PLC to enter debug code */
greg@244: 	WaitForSingleObject(debug_sem, INFINITE);  
greg@244: }
greg@244: 
greg@244: void resumeDebug()
greg@244: {
greg@244:     /* Let PLC enter debug code */
greg@244: 	ReleaseSemaphore(debug_sem, 1, NULL);
greg@244: }
etisserant@280: 
etisserant@280: /* from plc_python.c */
etisserant@280: int WaitPythonCommands(void)
etisserant@280: {
etisserant@280:     /* Wait signal from PLC thread */
etisserant@280: 	WaitForSingleObject(python_wait_sem, INFINITE);
etisserant@280: }
etisserant@280:  
etisserant@280: /* Called by PLC thread on each new python command*/
etisserant@280: void UnBlockPythonCommands(void)
etisserant@280: {
etisserant@280:     /* signal debugger thread it can read data */
etisserant@280: 	ReleaseSemaphore(python_wait_sem, 1, NULL);
etisserant@280: }
etisserant@280: 
etisserant@280: int TryLockPython(void)
etisserant@280: {
etisserant@280: 	return WaitForSingleObject(python_sem, 0) == WAIT_OBJECT_0;
etisserant@280: }
etisserant@280: 
etisserant@280: void UnLockPython(void)
etisserant@280: {
etisserant@280: 	ReleaseSemaphore(python_sem, 1, NULL);
etisserant@280: }
etisserant@280: 
etisserant@280: void LockPython(void)
etisserant@280: {
etisserant@280: 	WaitForSingleObject(python_sem, INFINITE);
etisserant@280: }
etisserant@280: