📄 timeunit.cpp
字号:
#include "sc_cfg.h"
#include "common.h"
#include "extern.h"
#define TIMER_INTERRUPT 0x08 // 8253 timer0 interrupt number
#define RTC_WRITE_PORT 0x70 // RTC write port address
#define RTC_READ_PORT 0x71 // RTC read port address
#define TIMER_RW_PORT 0x40 // timer0 io port address
#define RTC_SECOND_REG 0x00 // RTC second register address
#define RTC_MINUTE_REG 0x02 // RTC minute register address
#define RTC_HOUR_REG 0x04 // RTC hour register address
#define RTC_WEEK_REG 0x06 // RTC hour register address
#define RTC_DAY_REG 0x07 // RTC day register address
#define RTC_MONTH_REG 0x08 // RTC month register address
#define RTC_YEAR_REG 0x09 // RTC year register address
#define RTC_CENTURY_REG 0x32 // RTC century register address
#define RTC_SET_REG 0x0b // RTC setup register address
#define RTC_STATUS_REG 0x0a // RTC status register address
#define MS_PER_TICK 5 // the time between two timer interrupt
#define ORINGAL_CNT_H 0x00 // timer0 orignal const high byte
#define ORINGAL_CNT_L 0x00 // timer0 orignal const low byte
static INT8U month_tab[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static sclock systemclock;
INT16U port_timeout[MAX_PORT];
static INT16U all_timer = 0;
static INT16U old_isp_count = 0;
static void SoftClock(); // software clock
void ReadTime(sclock *ptr);
void SetTimer(); // set 8253 interrupt
void ResetTimer(); // reset 8253 interrupt
void interrupt timer_newhand(...); // interrupt service
void interrupt (*timer_oldhand)(...); // keep old service program
void GetClock(sclock *ptr); // get time from here
void SetClock(sclock *ptr); // set time to here
BOOLEAN check_mtimeout(const INT16U timer, const int gap);
INT16U get_mtime(void);
BOOLEAN check_mtimeout(const INT16U timer, const int gap)
{
INT16U ctimer;
OS_ENTER_CRITICAL();
ctimer = all_timer;
OS_EXIT_CRITICAL();
if (ctimer >= timer) {
if ((ctimer - timer) >= gap) return (TRUE);
else return (FALSE);
}
else {
if ((~(timer - ctimer) + 1) >= gap) return (TRUE);
else return (FALSE);
}
}
INT16U get_mtime(void)
{
INT16U ctimer;
OS_ENTER_CRITICAL();
ctimer = all_timer;
OS_EXIT_CRITICAL();
return (ctimer);
}
void interrupt timer_newhand(...)
{
int i;
#ifdef YX_INT_SAM
INT8U DataonPA0, DataonPB0;
#endif
disable();
// because YC and YM use the same port to sample
// while timer interrupt comes , we need to keep orignal output
#ifdef YX_INT_SAM
DataonPA0 = inp(hardwareset[3].address + 1);
DataonPB0 = inp(hardwareset[3].address + 2);
#endif
SoftClock(); // software clock
memcpy(&systemclock, &systemclock, sizeof(sclock));
// get system clock
// now begin to sample yx and restore output
#ifdef YX_INT_SAM
yx.boardyxget();
outp(hardwareset[3].address + 1, DataonPA0);
outp(hardwareset[3].address + 2, DataonPB0);
#endif
all_timer += MS_PER_TICK;
// 50ms run once
if (++old_isp_count > (55 / MS_PER_TICK)) {
old_isp_count = 0;
ykreg.timer++;
for (i = 0; i < MAX_PORT; i++)
if (port_timeout[i] < 6000) port_timeout[i]++;
timer_oldhand();
}
else outp(0x20, 0x20);
enable();
}
void ReadTime(sclock *ptr)
{
INT8U clkmask;
outp(RTC_WRITE_PORT, RTC_SET_REG);
clkmask = inp(RTC_READ_PORT) | 0x80;
outp(RTC_WRITE_PORT, RTC_SET_REG);
outp(RTC_READ_PORT, clkmask); // stop RTC for reading
outp(RTC_WRITE_PORT, RTC_SECOND_REG);
ptr->second = BcdtoBin(inp(RTC_READ_PORT)); // read RTC second
outp(RTC_WRITE_PORT, RTC_MINUTE_REG);
ptr->minute = BcdtoBin(inp(RTC_READ_PORT)); // read RTC minute
outp(RTC_WRITE_PORT, RTC_HOUR_REG);
ptr->hour = BcdtoBin(inp(RTC_READ_PORT)); // read RTC hour
outp(RTC_WRITE_PORT, RTC_WEEK_REG);
ptr->weekday = BcdtoBin(inp(RTC_READ_PORT));
outp(RTC_WRITE_PORT, RTC_DAY_REG);
ptr->day = BcdtoBin(inp(RTC_READ_PORT)); // read RTC day
outp(RTC_WRITE_PORT, RTC_MONTH_REG);
ptr->month = BcdtoBin(inp(RTC_READ_PORT)); // read RTC month
outp(RTC_WRITE_PORT, RTC_CENTURY_REG);
ptr->year = BcdtoBin(inp(RTC_READ_PORT));
outp(RTC_WRITE_PORT, RTC_YEAR_REG); // read RTC year
ptr->year = ptr->year * 100 + BcdtoBin(inp(RTC_READ_PORT));
outp(RTC_WRITE_PORT, RTC_SET_REG);
outp(RTC_READ_PORT, clkmask & 0x7f); // reading complete start RTC
}
void SetTimer(void)
{
INT16U count;
ReadTime(&systemclock);
systemclock.msecond = 0;
count = (INT16U)(((INT32U)2386360L * MS_PER_TICK / 1000 + 1) >> 1);
outp(TIMER_RW_PORT, count & 0xff);
outp(TIMER_RW_PORT, (count >> 8) & 0xff); // set system timer0 gap
timer_oldhand = getvect(TIMER_INTERRUPT); // keep old int service
setvect(TIMER_INTERRUPT, timer_newhand); // load new int service
}
void ResetTimer(void)
{
struct time t;
struct date d;
outp(TIMER_RW_PORT, ORINGAL_CNT_L);
outp(TIMER_RW_PORT, ORINGAL_CNT_H); // restore orignal timer0 gap
setvect(TIMER_INTERRUPT, timer_oldhand); // restore old int service
OS_ENTER_CRITICAL();
t.ti_hour = systemclock.hour;
t.ti_min = systemclock.minute;
t.ti_sec = systemclock.second;
t.ti_hund = systemclock.msecond / 10;
d.da_year = systemclock.year;
d.da_mon = systemclock.month;
d.da_day = systemclock.day;
OS_EXIT_CRITICAL();
settime(&t);
setdate(&d); // restore system time
}
static void SoftClock(void)
{
systemclock.msecond += MS_PER_TICK; // mil second increase
if (systemclock.msecond < 1000) return; // ms clock
systemclock.msecond = 0;
if (++systemclock.second < 60) return; // s clock
systemclock.second = 0;
if (++systemclock.minute < 60) return; // minute clock
systemclock.minute = 0;
if (++systemclock.hour < 24) return; // hour clock
systemclock.hour = 0;
if (++systemclock.weekday > 7) systemclock.weekday = 1;
if ((systemclock.year % 4) == 0 && ((systemclock.year % 100) != 0
|| (systemclock.year % 400) == 0)) month_tab[2] = 29;
else month_tab[2] = 28; // feb month set
if (++systemclock.day <= month_tab[systemclock.month]) return; // day clock
systemclock.day = 1;
if (++systemclock.month <= 12) return; // month clock
systemclock.month = 1;
systemclock.year++; // year clock
}
void GetClock(sclock *ptr)
{
OS_ENTER_CRITICAL();
memcpy(ptr, &systemclock, sizeof(sclock)); // get system clock
OS_EXIT_CRITICAL();
}
void SetClock(sclock *ptr)
{
INT8U clkmask;
OS_ENTER_CRITICAL();
memcpy(&systemclock, ptr, sizeof(sclock)); // modify system clock
OS_EXIT_CRITICAL();
outp(RTC_WRITE_PORT, RTC_SET_REG);
clkmask = inp(RTC_READ_PORT) | 0x80;
outp(RTC_WRITE_PORT, RTC_SET_REG);
outp(RTC_READ_PORT, clkmask); // begin setup RTC time
outp(RTC_WRITE_PORT, RTC_SECOND_REG);
outp(RTC_READ_PORT, (INT8U)BintoBcd(systemclock.second));// write RTC second
outp(RTC_WRITE_PORT, RTC_MINUTE_REG);
outp(RTC_READ_PORT, (INT8U)BintoBcd(systemclock.minute));// write RTC minute
outp(RTC_WRITE_PORT, RTC_HOUR_REG);
outp(RTC_READ_PORT, (INT8U)BintoBcd(systemclock.hour)); // write RTC hour
outp(RTC_WRITE_PORT, RTC_DAY_REG);
outp(RTC_READ_PORT, (INT8U)BintoBcd(systemclock.day)); // write RTC day
outp(RTC_WRITE_PORT, RTC_MONTH_REG);
outp(RTC_READ_PORT, (INT8U)BintoBcd(systemclock.month)); // write RTC month
outp(RTC_WRITE_PORT, RTC_CENTURY_REG);
outp(RTC_READ_PORT, (INT8U)(BintoBcd(systemclock.year) >> 8));
outp(RTC_WRITE_PORT, RTC_YEAR_REG); // write RTC year
outp(RTC_READ_PORT, (INT8U)(BintoBcd(systemclock.year)));
outp(RTC_WRITE_PORT, RTC_SET_REG);
outp(RTC_READ_PORT, clkmask & 0x7f); // quit setup mode
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -