home *** CD-ROM | disk | FTP | other *** search
- #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 <dos.h>
- #include <bios.h>
- #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 <stdio.h>
-
- #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
-