#include #include "timing.hpp" #include #include #include #include #include #include "dprint.hpp" #include static void (__interrupt __far *prev_int8)()=NULL; volatile unsigned long tick_counter,start_tick_counter; // note : if timer handler is installed for more than 497 days then // tick_counter will overflow. ** don't use this in OS code ** void (*install_timer_handler)(void (*fun)())=NULL; // function to install timer void (*uninstall_timer_handler)()=NULL; unsigned char timer_installed=0; static dostime_t dos_start_time; static dosdate_t dos_start_date; static chain_on=0,chain_counter=0; int total_timer_calls=0; #define MAX_TIMER_CALLS 10 #define TICKS_PER_SEC 100 struct { int and_call_mask; void ( *fun)(); } timer_calls[MAX_TIMER_CALLS]; void add_timer_call(void ( *fun)(), int and_call_mask) { if (total_timer_calls>=MAX_TIMER_CALLS) { dprintf("Too many timer calls installed\n"); exit(0); } timer_calls[total_timer_calls].fun=fun; timer_calls[total_timer_calls].and_call_mask=and_call_mask; total_timer_calls++; } void remove_timer_call(void ( *fun)()) { for (int i=0;i>8)); sti(); timer_installed=1; } atexit(timer_uninit); start_tick_counter=tick_counter=clock(); } } static char dim[12]={31, // Jan 29, // Feb 31, // March 30, // Apr 31, // May 30, // June 31, // July 30, // Aug 31, // Sept 31, // October 30, // Nov 31}; // Dec static int days_in_month(long month, long year) { if (month==1 && (((year-1)%4)==0)) // check for leap-year return 28; else return dim[month]; } void timer_uninit() { chain_on=0; if (timer_installed) { if (uninstall_timer_handler) uninstall_timer_handler(); else { if (prev_int8) { outp(0x43,0x36); // set timer speed back to 18.2 outp(0x40,0); outp(0x40,0); _dos_setvect(8,prev_int8); // don't try to restore the clock, we used chain_intr /* unsigned long ticks_passed=tick_counter-start_tick_counter; unsigned long hsec=ticks_passed*100/TICKS_PER_SEC; // now calculate how much time we stole from DOS and adjust the clock dos_start_time.hsecond=((long)dos_start_time.hsecond+hsec)%100; dos_start_time.second=((long)dos_start_time.second+hsec/100)%60; dos_start_time.minute=((long)dos_start_time.minute+hsec/(100*60))%60; dos_start_time.hour=((long)dos_start_time.hour+hsec/(100*60*60))%24; long days=hsec/(100*60*60*24); while (days) { dos_start_date.dayofweek=(dos_start_date.dayofweek+2)%7-1; dos_start_date.day=dos_start_date.day+1; if (days_in_month(dos_start_date.month,dos_start_date.year)>dos_start_date.day) { dos_start_date.day=1; dos_start_date.month++; if (dos_start_date.month>12) { dos_start_date.month=1; dos_start_date.year++; } } days--; } */ _dos_settime(&dos_start_time); _dos_setdate(&dos_start_date); prev_int8=NULL; } } timer_installed=0; } } void time_marker::get_time() { seconds=0; if (timer_installed) micro_seconds=tick_counter*1000/TICKS_PER_SEC; else micro_seconds=clock()*10; } time_marker::time_marker() { seconds=0; if (timer_installed) micro_seconds=tick_counter*1000/TICKS_PER_SEC; else micro_seconds=clock()*10; } double time_marker::diff_time(time_marker *other) { return (double)(micro_seconds-other->micro_seconds)/1000.0; } void milli_wait(unsigned wait_time) { if (timer_installed) { unsigned long wait_tick=wait_time*10/TICKS_PER_SEC+tick_counter; while (tick_counter