Category : Files from Magazines
Archive   : PCTV3N2.ZIP
Filename : RTCBIOS.C

 
Output of file : RTCBIOS.C contained in archive : PCTV3N2.ZIP
#pragma inline
/*
* RTCBIOS.C
* Interface module for the AT real-time clock functions 2
* through 7 and BIOS interrupt 15H functions 83H and 86H.
*
* Author Jim Mischel */
#include
#include
#include "rtcbios.h"
#define TESTING /* comment this if compiling for library */

#define ALARM 0x4A

/* SetWait -- Set a wait interval in microseconds.
* The interval is rounded up to the next multiple
* of 976 microseconds.
* At the end of the interval, the high bit or the byte
* pointed to by Flag will be set.
* Returns 0 if wait set successfully
* 1 if unable to set wait interval */
int SetWait (long ms, unsigned char far *Flag) {
char Status;
*Flag &= 0x7f; /* clear flag */
asm mov ax,8300h
asm mov cx,[word ptr ms+2] /* CX:DX = wait interval... */
asm mov dx,[word ptr ms] /* ...in microseconds */
asm les bx,[Flag] /* ES:BX=address of flag */
asm clc /* clear status */
asm int 15h /* set the wait */
asm lahf /* put flags into AH */
asm and ah,1 /* get Carry flag (bit 0) */
asm mov [Status],ah /* save status... */
return Status; /* ...and exit */
}

/* CancelWait -- Cancel wait interval set by SetWait. */
void CancelWait (void) {
asm mov ax,0040h
asm mov es,ax /* ES = BIOS data segment */
asm cli /* no interruptions! */
asm xor ax,ax /* clear... */
asm mov [byte ptr es:00A0h],al /* Wait Active flag... */
asm mov [word ptr es:009Ch],ax /* ...LSB and... */
asm mov [word ptr es:009Eh],ax /* MSB of Wait Count */
asm sti
}

/* Wait -- Delay execution for a number of microseconds.
* Wait interval is rounded up to the next multiple
* of 976 microseconds.
* Returns 0 if wait successful
* 1 if unable to wait for the interval */
int Wait (long ms) {
char Status;
asm mov ah,86h
asm mov cx,[word ptr ms+2] /* CX:DX = wait interval... */
asm mov dx,[word ptr ms] /* ...in microseconds */
asm int 15h /* do the wait */
asm lahf /* get flags into AH */
asm and ah,1 /* Carry flag is bit 0... */
asm mov [Status],ah /* ...and save as Status */
return Status;
}

/* BCDtoBin - Convert BCD value (0-99) to binary */
static int BCDtoBin (int BCD) {
return (BCD >> 4)*10 + (BCD & 0xf);
}

/* Convert binary value (0-99) to BCD */
static int BinToBCD (int Bin) {
return ((Bin / 10) << 4) + (Bin % 10);
}

/* GetRTCtime -- Get current RTC time & place in Time structure.
* Returns 0 -- function successful
* 1 -- unable to read time (Time invalid) */
int GetRTCtime (struct RTCTIME far *Time) {
char Status;
asm mov ah,2 /* Read RTC time function */
asm clc /* clear status indicator */
asm int 1ah /* go read the time */
asm lahf /* get flags to AH */
asm and ah,1 /* get status of carry flag... */
asm mov [Status],ah /* ...and store in Status */
asm jnz around /* if not successful, skip */
asm les di,[Time] /* ES:DI = address of time structure */
asm xor ah,ah
asm mov [es:di+6],ax /* save daylight flag */
asm mov al,ch
asm cld
asm stosw /* Hour,... */
asm mov al,cl
asm stosw /* ...Minute,... */
asm mov al,dh
asm stosw /* ...and Second */
/* -- Convert returned time from BCD to binary -- */
Time->Hour = BCDtoBin (Time->Hour);
Time->Min = BCDtoBin (Time->Min);
Time->Sec = BCDtoBin (Time->Sec);
around:
return Status;
}

/* SetRTCtime -- Set current time from Time structure
* Returns 0 -- function successful
* 1 -- unable to set time (Time invalid) */
int SetRTCtime (struct RTCTIME *Time) {
char Status;
struct RTCTIME WorkTime;
/* -- Convert Time to BCD in WorkTime -- */
WorkTime.Hour = BinToBCD (Time->Hour);
WorkTime.Min = BinToBCD (Time->Min);
WorkTime.Sec = BinToBCD (Time->Sec);
WorkTime.Daylight = Time->Daylight;
asm mov ah,3 /* set RTC Time function */
asm mov ch,[WorkTime.Hour]
asm mov cl,[WorkTime.Min]
asm mov dh,[WorkTime.Sec]
asm mov dl,[WorkTime.Daylight]
asm clc
asm int 1ah
asm lahf /* get flags to AH */
asm and ah,1 /* carry flag is bit 0... */
asm mov [Status],ah /* ...and store in Status */
return Status;
}

/* GetRTCdate -- Get RTC date and place in Date structure.
* Returns 0 -- function successful
* 1 -- unable to read date */
int GetRTCdate (struct RTCDATE far *Date) {
char Status;
asm mov ah,4 /* Get RTC date function */
asm clc /* clear status indicator */
asm int 1ah /* go read the date */
asm lahf /* get flags to AH */
asm and ah,1 /* get status of carry flag... */
asm mov [Status],ah /* ...and store in Status */
asm jnz around /* if not successful, skip */
asm les di,[Date] /* ES:DI = address of date structure */
asm xor ax,ax
asm cld
asm mov al,ch
asm stosw /* Save century,... */
asm mov al,cl
asm stosw /* ...year,... */
asm mov al,dh
asm stosw /* ...month,... */
asm mov al,dl
asm stosw /* ...and day */
/* -- Convert returned date from BCD to binary -- */
Date->Century = BCDtoBin (Date->Century);
Date->Year = BCDtoBin (Date->Year);
Date->Month = BCDtoBin (Date->Month);
Date->Day = BCDtoBin (Date->Day);
around:
return Status;
}

/* SetRTCdate -- Set RTC date from Date structure
* Returns 0 -- function successful
* 1 -- unable to set date */
int SetRTCdate (struct RTCDATE *Date) {
char Status;
struct RTCDATE WorkDate;
/* -- Convert Date to BCD in WorkDate -- */
WorkDate.Century = BinToBCD (Date->Century);
WorkDate.Year = BinToBCD (Date->Year);
WorkDate.Month = BinToBCD (Date->Month);
WorkDate.Day = BinToBCD (Date->Day);
asm mov ah,5 /* set RTC Date function */
asm mov ch,[WorkDate.Century]
asm mov cl,[WorkDate.Year]
asm mov dh,[WorkDate.Month]
asm mov dl,[WorkDate.Day]
asm clc
asm int 1ah
asm lahf /* get flags to AH */
asm and ah,1 /* carry flag is bit 0... */
asm mov [Status],ah /* ...and store in Status */
return Status;
}

/* SetAlarm -- Set the user alarm from the Time structure and
* install the alarm interrupt service routine.
* Returns 0 if alarm set successfully
* 1 if unable to set alarm. */
int SetAlarm (struct RTCTIME *Time,
void interrupt (*AlarmInt)()) {
char Status;
struct RTCTIME WorkTime;
/* -- Convert Time to BCD in WorkTime -- */
WorkTime.Hour = BinToBCD (Time->Hour);
WorkTime.Min = BinToBCD (Time->Min);
WorkTime.Sec = BinToBCD (Time->Sec);
asm mov ah,6 /* set alarm function */
asm mov ch,[WorkTime.Hour]
asm mov cl,[WorkTime.Min]
asm mov dh,[WorkTime.Sec]
asm clc /* fixes problem with some BIOS */
asm int 1ah
asm lahf /* get flags to AH */
asm and ah,1 /* carry flag is bit 0... */
asm mov [Status],ah /* ...and store in Status */
if (!Status)
setvect (ALARM, AlarmInt); /* install new ISR */
return Status;
}

/* ClearAlarm -- Cancel alarm set by SetAlarm */
void ClearAlarm (void) {
asm mov ah,7
asm int 1ah
}

/*** Test code ***/
#ifdef TESTING
#include

#define ESC 0x011B
volatile int TimeOut; /* Flag set by alarm ISR */
void interrupt (*OldAlarmInt) (void) = NULL; /* old alarm ISR */

/* AlarmInterrupt -- Sets the TimeOut flag and returns */
void interrupt AlarmInterrupt (void) {
#ifdef __TINY__
asm extrn DGROUP@ /* Fix problem with TC++ Tiny model */
#endif
TimeOut = 1;
}

/* Make a simple sound effect */
void SoundAlarm (void) {
static int FreqTable[] = {238,265,298,341,398,477,597,0};
int Freq;
for (Freq = 0; FreqTable[Freq] != 0; Freq++) {
sound (FreqTable[Freq]);
Wait (300000L/(Freq+1));
}
nosound ();
}

void main (void) {
unsigned char KeyFlag; /* flag used by SetWait */
int ch; /* dummy variable to read key */
struct RTCTIME Time;
struct RTCDATE Date;

/* Part 1 -- test Wait, SetWait, CancelWait */
do {
KeyFlag = 0;
while (bioskey (1)) /* empty keyboard buffer */
ch = bioskey (0);

/* -- 2.5 second wait interval -- */
if (SetWait (2500000L, &KeyFlag))
puts ("Unable to set wait interval");
printf ("Press any key.\n"
"Press ESC to move to 2nd part of test: ");
ch = bioskey (0); /* wait for character */
CancelWait (); /* cancel wait interval */
if (KeyFlag & 0x80) /* wait interval expired? */
puts ("Key pressed AFTER wait interval expired.\n");
else
puts ("Key pressed during wait interval.\n");
if (Wait (1000000L)) /* 1-second delay */
puts ("Wait error");
} while (ch != ESC); /* loop until ESC */
/* Part 2: Test GetRTCtime, GetRTCdate, SetAlarm, ClearAlarm */
if (GetRTCdate (&Date))
puts ("Unable to read RTC date");
else
printf ("Today is %02d/%02d/%02d%02d\n",
Date.Month, Date.Day, Date.Century, Date.Year);
if (GetRTCtime (&Time))
puts ("Unable to read RTC time");
else {
printf ("The time is %02d:%02d:%02d\n",
Time.Hour, Time.Min, Time.Sec);
if (Time.Daylight > 1)
puts ("Status of daylight savings "
"flag is undetermined");
else
printf ("Daylight savings time %s in effect\n",
(Time.Daylight) ? "is" : "is not");
/* -- add 30 seconds to the current time -- */
Time.Sec = Time.Sec + 30;
if (Time.Sec > 59) {
Time.Sec -= 60;
if (++Time.Min > 59) {
Time.Min -= 60;
if (++Time.Hour > 23)
Time.Hour -= 24;
}
}
OldAlarmInt = getvect (ALARM); /* Save old alarm int */
TimeOut = 0;
if (SetAlarm (&Time, AlarmInterrupt))
puts ("Unable to set alarm");
else {
printf ("Alarm will sound at %02d:%02d:%02d\n",
Time.Hour, Time.Min, Time.Sec);
puts ("Press any key to exit"
" before alarm sounds");
while (!TimeOut) { /* Wait for alarm */
if (bioskey (1)) { /* if key pressed */
bioskey (0); /* read key... */
break; /* ...and exit loop */
}
}
SoundAlarm (); /* sound the alarm */
ClearAlarm (); /* turn alarm off */
}
setvect (ALARM, OldAlarmInt); /* reset alarm int */
}
}
#endif TESTING


  3 Responses to “Category : Files from Magazines
Archive   : PCTV3N2.ZIP
Filename : RTCBIOS.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/