blob: 5a1cab14a7eb8a6874017eb2c0808bc5e5691161 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 ACIN, Profactor GmbH
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alois Zoitl, Gerhard Ebenhofer - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "pctimeha.h"
#include "../../core/devexec.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
const TForteInt32 CPCTimerHandler::csm_nTicksPerSecond = 1000;
CTimerHandler* CTimerHandler::createTimerHandler(CDeviceExecution& pa_poDeviceExecution){
return new CPCTimerHandler(pa_poDeviceExecution);
}
CPCTimerHandler::CPCTimerHandler(CDeviceExecution& pa_poDeviceExecution) : CTimerHandler(pa_poDeviceExecution) {
}
CPCTimerHandler::~CPCTimerHandler(){
disableHandler();
}
/*
HANDLE gDoneEvent;
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
CPCTimerHandler *timerHandler = (CPCTimerHandler*) lpParam;
if(timerHandler != 0){
if(timerHandler->isAlive() ){
timerHandler->nextTick();
}
else{
SetEvent(gDoneEvent);
}
}
}
bool CPCTimerHandler::run(){
HANDLE hTimer = NULL;
// Use an event object to track the TimerRoutine execution
gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == gDoneEvent){
return false;
}
// Set a timer to call the timer routine in 10 seconds.
if (!CreateTimerQueueTimer( &hTimer, 0, (WAITORTIMERCALLBACK)TimerRoutine, this, 0, 1000 / CPCTimerHandler::csm_nTicksPerSecond, 0))
{
return false;
}
if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)
return false;
DeleteTimerQueueTimer(0, hTimer,0);
CloseHandle(gDoneEvent);
return true;
}*/
void CPCTimerHandler::run(){
DWORD stReq = 0; // in us
LARGE_INTEGER stReqTimeVal = { 0, 0 };
LARGE_INTEGER stFrequenzy = { 0, 0 }; // clocks per second
LARGE_INTEGER stElapsed1 = { 0, 0 };
LARGE_INTEGER stElapsed2 = { 0, 0 };
LARGE_INTEGER stError = { 0, 0 };
LARGE_INTEGER stISum = { 0, 0 };
LARGE_INTEGER stWaittime = { 0, 0 };
QueryPerformanceFrequency(&stFrequenzy);
QueryPerformanceCounter(&stElapsed1);
stReqTimeVal.QuadPart = stFrequenzy.QuadPart / CPCTimerHandler::csm_nTicksPerSecond;
//stReqTimeVal = 1000000 / CPCTimerHandler::csm_nTicksPerSecond;
while(isAlive()){
stWaittime.QuadPart *= 1000; // calculate in ms, not sec
stReq = static_cast<DWORD>(stWaittime.QuadPart / stFrequenzy.QuadPart); // calculate elapsed time in ms
// dont give up the thread if we still have to do some ticks(some os have 10ms minimum threadtime)
if(stReq > 0){
Sleep(stReq);
}
nextTick();
// sample new time
stElapsed2.QuadPart = stElapsed1.QuadPart;
QueryPerformanceCounter(&stElapsed1);
// calulate controler error: Diff - Setupvalue = Error
stError.QuadPart = stElapsed1.QuadPart - stElapsed2.QuadPart;
stError.QuadPart = stReqTimeVal.QuadPart - stError.QuadPart;
// I-controller
stISum.QuadPart += stError.QuadPart;
// calculate new Output
stWaittime.QuadPart = stReqTimeVal.QuadPart + stISum.QuadPart;
if(stWaittime.QuadPart < 0){
stWaittime.QuadPart = 0;
}
}
}
void CPCTimerHandler::enableHandler(void){
start();
}
void CPCTimerHandler::disableHandler(void){
end();
}
void CPCTimerHandler::setPriority(int pa_nPriority){
//TODO think on hwo to handle this.
}
int CPCTimerHandler::getPriority(void) const{
//TODO think on hwo to handle this.
return 1;
}