greg@205: #include <stdio.h>
greg@205: #include <sys/timeb.h>
greg@205: #include <time.h>
greg@205: #include <windows.h>
greg@205: 
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: //long AtomicExchange(long* atomicvar,long exchange)
greg@205: //{
greg@205: //    return InterlockedExchange(atomicvar, exchange);    
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;
greg@244: HANDLE wait_sem; 
greg@244: #define MAX_SEM_COUNT 10
greg@229: 
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
greg@244: 					        MAX_SEM_COUNT,  // maximum count
greg@244: 					        NULL);          // unnamed semaphore
greg@244:     if (debug_sem == NULL) 
greg@244:     {
greg@244:         printf("CreateMutex error: %d\n", GetLastError());
greg@244:         return;
greg@244:     }
greg@244:     
greg@244: 	wait_sem = CreateSemaphore( 
greg@244: 					        NULL,           // default security attributes
greg@244: 					        0,  			// initial count
greg@244: 					        MAX_SEM_COUNT,  // maximum count
greg@244: 					        NULL);          // unnamed semaphore
greg@229: 
greg@244:     if (wait_sem == NULL) 
greg@229:     {
greg@229:         printf("CreateMutex error: %d\n", GetLastError());
greg@229:         return;
greg@229:     }
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;
greg@244: 	ReleaseSemaphore(wait_sem, 1, NULL);
greg@244: 	CloseHandle(debug_sem);
greg@244: 	CloseHandle(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: {
greg@244: 	WaitForSingleObject(wait_sem, INFINITE);
greg@244: 	return __debug_tick;
greg@229: }
greg@229:  
greg@229: /* 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: 	/* Leave debugger section */
greg@244: 	ReleaseSemaphore(debug_sem, 1, NULL);
greg@244:     /* remember tick */
greg@244:     __debug_tick = __tick;
greg@244:     /* signal debugger thread it can read data */
greg@244:     ReleaseSemaphore(wait_sem, 1, NULL);
greg@229: }
greg@244: 
greg@244: void suspendDebug()
greg@244: {
greg@247: 	__DEBUG = 0;
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@247: 	__DEBUG = 1;
greg@244:     /* Let PLC enter debug code */
greg@244: 	ReleaseSemaphore(debug_sem, 1, NULL);
greg@244: }