#include #include #include "clock.h" volatile unsigned int ClockTicks = 0; volatile unsigned int ClockFrequency = 0; unsigned char PitInitialized = 0; volatile TIME _InternalClock; void PitSetFrequency(int frequency) { int divisor = 1193180/frequency; // Calculate the divisor outportb(0x43, 0x36); // Set our command byte 0x36 outportb(0x40, divisor&0xFF); // Set low byte outportb(0x40, divisor>>8); // Set high byte ClockFrequency = frequency; } void i86_PitHandler(ISR_stack_regs *r) { ClockTicks++; // count tick if (ClockTicks % ClockFrequency == 0) _CLOCK_INC((TIME*)&_InternalClock); // update internal clock } unsigned int ClockSetTickCount(unsigned int i) { unsigned int r = ClockTicks; ClockTicks = i; return r; } unsigned int ClockGetTickCount() { return ClockTicks; } unsigned int PitGetFrequency() { return ClockFrequency; } void i86_PitInitialize(int freq) { PitSetFrequency(freq); ClockTicks = 0; i86_GetRTC((TIME*) &_InternalClock); PitInitialized = 1; } TIME ClockGetTime() { return _InternalClock; } unsigned char PitIsInitialized() { return PitInitialized; } inline unsigned char CmosRead (unsigned char address) { outportb(0x70, address); iowait(); return inportb(0x71); } inline void CmosWrite (unsigned char address, unsigned char val) { outportb(0x70, address); iowait(); outportb(0x71, val); } void i86_SetRTC (const TIME* time) { unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0; unsigned char ampm = ((CmosRead(0x0b)&2)==0) ? 1 : 0; CmosWrite (0, (BCD) ? (time->second%10) | (time->second/10*16) : time->second); // Seconds CmosWrite (2, (BCD) ? (time->minute%10) | (time->minute/10*16) : time->minute); // Minutes if (ampm && time->hour > 12) // Hours CmosWrite (4, (BCD) ? (((time->hour - 12) % 10) | ((time->hour - 12)/10*16) | 0x80) : (time->hour | 0x80) ); else if (ampm && time->hour == 0) // Midnight convention: 12 PM = 00:00 CmosWrite (4, (BCD) ? 0x92 : 0x8C); else CmosWrite (4, (BCD) ? (time->hour%10) | (time->hour/10*16) : time->hour); // 24h / AM CmosWrite (6, (BCD) ? (time->weekday%10) | (time->weekday/10*16) : time->weekday); // Weekday CmosWrite (7, (BCD) ? (time->day%10) | (time->day/10*16) : time->day); // Day CmosWrite (8, (BCD) ? (time->month%10) | (time->month/10*16) : time->month); // Month CmosWrite (9, (BCD) ? (time->year%10) | (time->year/10*16) : time->year); // Year CmosWrite (0x32, (BCD) ? (time->century%10) | (time->century/10*16) : time->century); // Century } void i86_GetRTC(TIME* tim) { unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0; unsigned char am_pm = ((CmosRead(0x0b)&2)==0) ? 1 : 0; tim->second = (BCD) ? (CmosRead(0x00)%16) + 10*(CmosRead(0x00)/16): CmosRead(0x00); tim->minute = (BCD) ? (CmosRead(0x02)%16) + 10*(CmosRead(0x02)/16): CmosRead(0x02); // Time is PM if (am_pm && CmosRead(0x04)&80) { tim->hour = (BCD) ? ((CmosRead(0x04)-0x80)%16) + 10*((CmosRead(0x04)-0x80)/16): CmosRead(0x04)-0x80; tim->hour += 12; } // 24Hour format, or AM else tim->hour = (BCD) ? (CmosRead(0x04)%16) + 10*(CmosRead(0x04)/16): CmosRead(0x04); tim->weekday = (BCD) ? (CmosRead(0x06)%16) + 10*(CmosRead(0x06)/16): CmosRead(0x06); tim->day = (BCD) ? (CmosRead(0x07)%16) + 10*(CmosRead(0x07)/16): CmosRead(0x07); tim->month = (BCD) ? (CmosRead(0x08)%16) + 10*(CmosRead(0x08)/16): CmosRead(0x08); tim->year = (BCD) ? (CmosRead(0x09)%16) + 10*(CmosRead(0x09)/16): CmosRead(0x09); tim->century = (BCD) ? (CmosRead(0x32)%16) + 10*(CmosRead(0x32)/16): CmosRead(0x32); }