/* Raydium - CQFD Corp. http://raydium.org/ License: GPL - GNU General Public License, see "gpl.txt" file. */ #ifndef DONT_INCLUDE_HEADERS #include "index.h" #else #include "headers/timecall.h" #endif #ifdef WIN32 #define __GETTIMEOFDAY_USEC 1000 #else #define __GETTIMEOFDAY_USEC 1000000 #endif // needed proto int raydium_timecall_add(void *funct, GLint hz); void raydium_timecall_raydium(GLfloat step) { raydium_frame_time=step; } #ifdef WIN32 float raydium_timecall_internal_w32_detect_modulo(int div) { LARGE_INTEGER t; unsigned long mx; QueryPerformanceFrequency(&t); t.QuadPart >>= div; mx=(0xFFFFFFFF / t.LowPart); return mx/60.f; } int raydium_timecall_internal_w32_divmodulo_find(void) { float modulo_time; int div; div=-1; do{ div++; modulo_time=raydium_timecall_internal_w32_detect_modulo(div); }while(modulo_time0) { if( read(raydium_timecall_devrtc_handle, &data, sizeof(unsigned long)) == -1) { raydium_log("timecall: ERROR: reading /dev/rtc failed at runtime"); perror("system"); } else { // read first 3 bytes only missed=(data & 0xffffff00UL)>>8; raydium_timecall_devrtc_clocks+=missed; // raydium_log("%i",raydium_timecall_devrtc_clocks); } } return raydium_timecall_devrtc_clocks; #else return 0; #endif } unsigned long raydium_timecall_clock(void) { struct timeval tv; if(raydium_timecall_method==RAYDIUM_TIMECALL_METHOD_CLOCK) { #ifdef WIN32 { // return GetTickCount(); LARGE_INTEGER t; QueryPerformanceCounter(&t); t.QuadPart>>=raydium_timecall_w32_divmodulo; return t.LowPart; } #else gettimeofday(&tv,NULL); return (tv.tv_sec*1000000 + tv.tv_usec); #endif //return clock(); } //else if(raydium_timecall_method==RAYDIUM_TIMECALL_METHOD_DEVRTC) return raydium_timecall_devrtc_clock(); } signed char raydium_timecall_devrtc_rate_change(unsigned long new) { #ifndef WIN32 if(ioctl(raydium_timecall_devrtc_handle, RTC_IRQP_SET, new)==-1) { raydium_log("timecall: ERROR: changing /dev/rtc rate to %lu Hz failed !",new); raydium_log("timecall: is /proc/sys/dev/rtc/max-user-freq correct for this value ?"); perror("system"); // exit(errno); return 0; } raydium_log("timecall: /dev/rtc rate changed to %lu Hz",new); return 1; #else return 0; #endif } void raydium_timecall_devrtc_close(void) { #ifndef WIN32 if(ioctl(raydium_timecall_devrtc_handle, RTC_PIE_OFF, 0) == -1) { raydium_log("timecall: ERROR disabling /dev/rtc periodic interrupts"); perror("system"); // exit(errno); } close(raydium_timecall_devrtc_handle); #endif } unsigned long raydium_timecall_devrtc_init(void) { #ifndef WIN32 unsigned long freq; raydium_timecall_devrtc_clocks=0; if((raydium_timecall_devrtc_handle = open ("/dev/rtc", O_RDONLY)) == -1 ) { raydium_log("timecall: ERROR: /dev/rtc unavailable ! (chmod a+rx /dev/rtc ?)"); perror("system"); // exit(errno); return 0; } // ok, it's now open, so let's read actual rate if (ioctl(raydium_timecall_devrtc_handle, RTC_IRQP_READ, &freq) == -1 ) { raydium_log("timecall: ERROR reading /dev/rtc rate"); perror("system"); // exit(errno); return 0; } raydium_log("timecall: /dev/rtc rate is %lu Hz",freq); if(freq>=raydium_timecall_w32_divmodulo; raydium_timecall_clocks_per_sec=t.LowPart; #endif raydium_timecall_max_frequency=raydium_timecall_detect_frequency(); if(raydium_timecall_max_frequencyraydium_timecall_max_frequency && hz>0) raydium_log("timecall: WARNING ! this callback refresh rate (%i Hz) is probably too high for this system clock (detected at %i Hz)",hz,raydium_timecall_max_frequency); if(hz>0) raydium_log("timecall: callback %i: %i Hz (%i clocks interval)",callback,hz,raydium_timecall_interval[callback]); if(hz<0) raydium_log("timecall: softcall %i: %i Hz (%i clocks interval)",callback,-hz,raydium_timecall_interval[callback]); } int raydium_timecall_add(void *funct, GLint hz) { if(raydium_timecall_index>=RAYDIUM_MAX_TIMECALLS) { raydium_log("timecall: ERROR ! Too much timecalls, exiting."); exit(29); } raydium_timecall_funct[raydium_timecall_index]=funct; raydium_timecall_freq_change(raydium_timecall_index,hz); return raydium_timecall_index++; } void raydium_timecall_callback(void) { int i,j,steps; GLfloat stepsf; unsigned long now,phase; static unsigned long last; void (*f)(); void (*ff)(GLfloat); // workaround for time modulos now=raydium_timecall_clock(); if(last>now) { raydium_log("timecall: warning: time modulo detected: workarounding"); for(i=0;i=raydium_timecall_next[i] && raydium_timecall_interval[i]) { steps=((now-raydium_timecall_next[i])/raydium_timecall_interval[i])+1; phase=(now-raydium_timecall_next[i])-((steps-1)*raydium_timecall_interval[i]); //raydium_log("current phase overload for timecall %i: %i (total interval = %i",i,phase,raydium_timecall_interval[i]); raydium_timecall_next[i]=now+raydium_timecall_interval[i]-phase; #ifdef DEBUG_MOVIE steps=(float)raydium_timecall_interval[i]/((float)raydium_timecall_interval[i]*(1/(float)DEBUG_MOVIE)); #endif if(steps>1000) { // DEBUG ! need to calculate this value steps=100; raydium_log("WARNING: timecall's too long"); } // raydium_log("debug: need %i steps",steps); f=raydium_timecall_funct[i]; for(j=0;j