DIRECT HARDWARE ACCESS - DOS


// File...: RTCTEST.C (c) SSV SOFTWARE SYSTEMS 1998
// Version: 1.00 (Build 2 - 16 Bit DOS)
// Date...: 27.Jul.1998

//              *** DISCLAIMER OF WARRENTY ***
// =======================================================                                                                       
// THIS  CODE AND INFORMATION IS PROVIDED "AS IS"  WITHOUT         
// A  WARRANTY OF  ANY KIND, EITHER  EXPRESSED OR  IMPLIED,        
// INCLUDING  BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF         
// MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

// Typedefs

typedef unsigned char BYTE;
typedef unsigned int  WORD;

// Includes

#include ‹stdlib.h›
#include ‹stdio.h›
#include ‹graphics.h›
#include ‹conio.h›
#include ‹dos.h›
#include ‹bios.h›
#include ‹string.h›

// Defines

#ifdef __cplusplus
   #define __CPPARGS ...
#else
   #define __CPPARGS
#endif
#define ID_TIMER            1             // Timer ID
#define RTC_AdrPort      0x70             // I/O Addr. RTC Addr. Port
#define RTC_DataPort     0x71             // I/O Addr. RTC Data Port
#define RTC_Seconds      0x00             // AddrIndex RTC Seconds
#define RTC_SecondsAlarm 0x01             // AddrIndex RTC Seconds Alarm
#define RTC_Minutes      0x02             // AddrIndex RTC Minutes
#define RTC_MinutesAlarm 0x03             // AddrIndex RTC Minutes Alarm
#define RTC_Hours        0x04             // AddrIndex RTC Hours
#define RTC_HoursAlarm   0x05             // AddrIndex RTC Hours Alarm
#define RTC_DayOfWeek    0x06             // AddrIndex RTC Day of Week
#define RTC_DateOfMonth  0x07             // AddrIndex RTC Date of Month
#define RTC_Month        0x08             // AddrIndex RTC Month
#define RTC_Year         0x09             // AddrIndex RTC Year
#define RTC_RegisterA    0x0a             // AddrIndex RTC RegisterA
#define RTC_RegisterB    0x0b             // AddrIndex RTC RegisterB
#define RTC_RegisterC    0x0c             // AddrIndex RTC RegisterC
#define RTC_RegisterD    0x0d             // AddrIndex RTC RegisterD
#define MASTER_PIC	 0x20             // Base Addr. Master PIC
#define SLAVE_PIC        0xa0             // Base Addr. Slave PIC
#define EOI              0x20             // PIC EndOfInterrupt Command
#define IRQ1                1             // Interrupt Request 1
#define IRQ2                2             // Interrupt Request 2
#define IRQ3                3             // Interrupt Request 3
#define IRQ4                4             // Interrupt Request 4
#define IRQ5                5             // Interrupt Request 5
#define IRQ6                6             // Interrupt Request 6
#define IRQ7                7             // Interrupt Request 7
#define IRQ8                8             // Interrupt Request 8
#define IRQ9                9             // Interrupt Request 9
#define IRQ10              10             // Interrupt Request 10
#define IRQ11              11             // Interrupt Request 11
#define IRQ12              12             // Interrupt Request 12
#define IRQ13              13             // Interrupt Request 13
#define IRQ14              14             // Interrupt Request 14
#define IRQ15              15             // Interrupt Request 15

// Globals

long glIrq8Counter= 0l;
void interrupt (*oldIRQ8Handler) (__CPPARGS);

// Internal Function Prototyps

BYTE           ReadPort     (WORD);
void           WritePort    (WORD, BYTE);
void           SendEOI      (BYTE);
void           EnableIRQ    (BYTE);
void           DisableIRQ   (BYTE);
void           SetIRQ       (BYTE, void interrupt (*) ());
void interrupt IRQ8Handler  (__CPPARGS);
BYTE           ReadTimeByte (BYTE);
BYTE           ReadRTC      (WORD);
void           WriteRTC     (WORD, BYTE);
void           main         ();

//***************************************************************************

BYTE ReadPort (WORD wPortAddr)
{
   return (inportb (wPortAddr));
}

//***************************************************************************

void WritePort (WORD wPortAddr, BYTE bData)
{
   outportb (wPortAddr, bData);
}

//***************************************************************************

void SendEOI (BYTE  bIrqNumber)
{
   if (bIrqNumber › 7) WritePort (SLAVE_PIC, EOI);
   WritePort (MASTER_PIC, EOI);
}

//***************************************************************************

void EnableIRQ (BYTE bIrqNumber)
{
   int nPort;

   // Build PIC Mask Port Addr. (BaseAddr + 1)...

   nPort= (bIrqNumber ‹= 7) ? MASTER_PIC : SLAVE_PIC;
   nPort++;

   bIrqNumber &= 0x0007;
   WritePort (nPort, ReadPort (nPort) & ~(1 ‹‹ bIrqNumber));
}

//***************************************************************************

void DisableIRQ (BYTE bIrqNumber)
{
   int nPort;

   // Build PIC Mask Port Addr. (BaseAddr + 1)...

   nPort= (bIrqNumber ‹= 7) ? MASTER_PIC : SLAVE_PIC;
   nPort++;

   bIrqNumber &= 0x0007;
   WritePort (nPort, ReadPort (nPort) | (1 ‹‹ bIrqNumber));
}

//***************************************************************************

void SetIRQ (BYTE bIrqNumber, void interrupt (*IrqHandler) (__CPPARGS))
{
   switch (bIrqNumber) {
      case IRQ1 : setvect (0x09, IrqHandler); break;
      case IRQ2 : setvect (0x0a, IrqHandler); break;
      case IRQ3 : setvect (0x0b, IrqHandler); break;
      case IRQ4 : setvect (0x0c, IrqHandler); break;
      case IRQ5 : setvect (0x0d, IrqHandler); break;
      case IRQ6 : setvect (0x0e, IrqHandler); break;
      case IRQ7 : setvect (0x0f, IrqHandler); break;
      case IRQ8 : setvect (0x70, IrqHandler); break;
      case IRQ9 : setvect (0x71, IrqHandler); break;
      case IRQ10: setvect (0x72, IrqHandler); break;
      case IRQ11: setvect (0x73, IrqHandler); break;
      case IRQ12: setvect (0x74, IrqHandler); break;
      case IRQ13: setvect (0x75, IrqHandler); break;
      case IRQ14: setvect (0x76, IrqHandler); break;
      case IRQ15: setvect (0x77, IrqHandler); break;
      default   : break;
   }
}

//***************************************************************************

void interrupt IRQ8Handler (__CPPARGS)
{
   glIrq8Counter++;
   ReadRTC (RTC_RegisterC);
   SendEOI (IRQ8);
}

//***************************************************************************

BYTE ReadTimeByte (BYTE AddrIndex)
{
   // Wait if RTC internal "Update in Progress"...

   while (ReadRTC (RTC_RegisterA) & 0x80);

   // Read RTC Time Byte in Bin or BCD format, return always Bin...

   if (ReadRTC (RTC_RegisterB) & 0x02)
      return ((ReadRTC (AddrIndex) ›› 4) * 10 + (ReadRTC (AddrIndex) & 0x0f)); // BCD -› Bin
   else
      return (ReadRTC (AddrIndex));
}

//***************************************************************************

void WriteRTC (WORD Addr, BYTE Value)
{
   WritePort (RTC_AdrPort, (BYTE) Addr);  // Write Addr. to RTC Addr. Port
   WritePort (RTC_DataPort, Value);       // Write Data to RTC Data Port
}

//***************************************************************************

BYTE ReadRTC (WORD Addr)
{
   WritePort (RTC_AdrPort, (BYTE) Addr);  // Write Addr. to RTC Addr. Port
   return (ReadPort (RTC_DataPort));      // Read RTC Data Port
}

//***************************************************************************

void main (void)
{
   int  nGdriver, nGmode, nColor;
   char szBuffer[16];

   // Setup GraphicsMode...

   detectgraph (&nGdriver, &nGmode);
   initgraph (&nGdriver, &nGmode, "..\\bgi");
   nColor= getcolor ();
   setfillstyle (EMPTY_FILL, nColor);
   settextstyle (DEFAULT_FONT, HORIZ_DIR, 8);
   setviewport (0, 0, 639, 479, 0);

   // Set new InterruptHandler for IRQ8 (RTC Interrupt)...

   oldIRQ8Handler= getvect (0x70);
   SetIRQ (IRQ8, IRQ8Handler);

   // Enable RTC Interrupt...

   WriteRTC (RTC_RegisterB, (BYTE) ((ReadRTC (RTC_RegisterB) | 0x40) & 0x7f));
   EnableIRQ (IRQ8);

   // Update RTC Time and Interrupt Counter on Screen...

   while (bioskey (1) == 0) {

      // Update RTC Time in upper half...

      clearviewport ();
      sprintf (szBuffer, "%02d:%02d:%02d",
	       ReadTimeByte (RTC_Hours),
	       ReadTimeByte (RTC_Minutes),
	       ReadTimeByte (RTC_Seconds));
      outtextxy (65, 95, szBuffer);

      // Update Interrupt Counter in lower half...

      if (glIrq8Counter › 999999l) glIrq8Counter= 0;
      sprintf (szBuffer, "%06ld", glIrq8Counter);
      outtextxy (130, 325, szBuffer);

      // Line upper/lower half. Delay for next Update...

      line (0, 240, 640, 240);
      delay (1000);
   }

   // Disable RTC Interrupt, Reset IRQ8 Vector...

   DisableIRQ (IRQ8);
   WriteRTC (RTC_RegisterB, (BYTE) (ReadRTC (RTC_RegisterB) & 0xbf));
   SetIRQ (IRQ8, oldIRQ8Handler);
   bioskey (0);
   closegraph ();
}


| Home Page |

SSV SOFTWARE SYSTEMS PC/104 Products. Software Support. File: P133.HTM, Last Update: 02-Aug-1998
Copyright (c) 1996 - 1998 WST. All rights reserved.