/**************************************************************************/
/* TEST10 - show BIOS clock impact of changing PC timer frequency         */
/*        - eRTOS corrects the bios clock once per second so we don't     */
/*          drift from the real time, even despite timer rate changes     */
/**************************************************************************/

#include <stdio.h>
#include <dos.h>
#include <rtos.h>

long origdiff;
DWORD far *sysclock = 0x46cL;

DWORD bcd_decode( unsigned bcd )
{
    return(  ( bcd & 0x0f) + (( bcd >> 4 ) * 10 ));
}

DWORD read_rtc()
{
    DWORD hours, mins, secs;

    struct REGPACK regs;
    regs.r_ax = 0x200;
    intr( 0x1a, &regs );
    if ( regs.r_flags & 1 )     // error, no RTC
        return( 0 );
    hours = bcd_decode( regs.r_cx >> 8 );
    mins = bcd_decode( regs.r_cx & 255 );
    secs = bcd_decode( regs.r_dx >> 8 );
    cprintf(" %2lu:%02lu:%02lu : ", hours, mins, secs );
    return( (((hours * 60) + mins) * 60 + secs ) * 37287/2048);
}

void watch_diff( void )
{
    DWORD rtc, absdiff;
    long diff;

    int i;

    while ( 1 ) {
        rtc = read_rtc();
        diff = rtc - *sysclock - origdiff;
        absdiff = ( diff > 0 ) ? diff : -diff;

        cprintf(" Difference = %c %li.%li seconds\r\n",
            (diff > 0) ? ' ' : '-',
            (absdiff * 2048)/37287, ((absdiff % 18) * 10)/18 );


        if ( kbhit() ) exit( 0 );
        rt_sleep( 300 );
    }
}

void try_freq( int freq )
{
    printf("trying frequency : %u\n", freq );

    rt_timerfreq( freq );
    watch_diff();
}

int main(int argc, char **argv)
{

    rt_init(100);

    puts("The PC BIOS clock used by DOS is normally updated by the 18.2 Hz IRQ 0");
    puts("clock.  This is the same clock eRTOS changes if you use rt_timerfreq.");
    puts("eRTOS uses an algorithm to simulate the 18.2 Hz clock, but it's not perfect.");
    puts("This example shows the difference between the BIOS clock and the CMOS clock");

    origdiff = read_rtc() - *sysclock;

    try_freq( 100 );
}

