Page 1 of 2
time fetch error
Posted: Fri Jun 27, 2008 10:46 am
by suthers
I'm currently writing a function that reads the time...
I general gist of how to do it of DexOS (Thanks Dex
)
So I 'translated' the asm code into C...
And this is what I got:
Code: Select all
void fetch_time()
{
outportb(0x70, 0x32);
century = inportb(0x71);
outportb(0x70, 0x9);
year = inportb(0x71);
outportb(0x70, 0x8);
month = inportb(0x71);
outportb(0x70, 0x7);
day = inportb(0x71);
outportb(0x70, 0x4);
hour = inportb(0x71);
outportb(0x70, 0x2);
minute = inportb(0x71);
outportb(0x70, 0x0);
second = inportb(0x71);
return;
};
I then print out the variables...
But according to it is the 39/06/3108 and the time is 23:66:89
The month and year are right...
But the century is WAY to high, the hour is wrong (it's currently 17:45..., about 5 mins after test...) and the day, minute and second isn't even possible.
But the weird thing is I got the outport and inport values from dexos, so I assume they should be right...
So I don't know what's wrong....
Any suggestions?
Thanks in advance,
Jules
Re: time fetch error
Posted: Fri Jun 27, 2008 11:02 am
by Korona
IIRC CMOS values are stored in bcd notation.
Re: time fetch error
Posted: Fri Jun 27, 2008 11:03 am
by piranha
Are you running this on an emulator?
I don't know about other things, but I do know that Qemu as an option for reporting the correct time.
As for your code...I based mine off of Linux:
Code: Select all
unsigned char read_cmos(unsigned char addr)
{
unsigned char r;
outb(0x70,addr);
__asm__ __volatile__ ("jmp 1f; 1: jmp 1f;1:");
r = inb(0x71);
__asm__ __volatile__ ("jmp 1f; 1: jmp 1f;1:");
return r;
}
Code: Select all
#define BCD2BIN(bcd) ((((bcd)&15) + ((bcd)>>4)*10))
get_time_stuff()
{
asm("cli");
now.sec = BCD2BIN(readCMOS(0x0));
now.min = BCD2BIN(readCMOS(0x2));
now.hour = BCD2BIN(readCMOS(0x4));
now.day = BCD2BIN(readCMOS(0x7));
now.month = BCD2BIN(readCMOS(0x8));
now.year = BCD2BIN(readCMOS(0x9));
asm("sti");
}
You aren't using a BCD2BIN thingy.
[Edit]Korona beat me to it...
-JL
Re: time fetch error
Posted: Fri Jun 27, 2008 11:04 am
by suthers
You are having a joke, what the hell is the point in that notation....
Well anyway, thanks
Thanks,
Jules
edit: Thanks, piranha, I use bochs as an emu and I've synced it to real time...
Jules
second edit: Sorry lost my temper for a second there....
Re: time fetch error
Posted: Fri Jun 27, 2008 1:21 pm
by suthers
Thanks a lot, that fixed it.
I wrote a converter.
Which is here in case somebody has a similar question in the future and the forum search actually works
:
Code: Select all
char bcd_2_bin(char convert) //yah I liked your name piranha :D
{
char copy = convert;
copy = copy & 0xf;
convert = convert & 0xf0;
convert = convert >> 4;
char output = convert * 10;
output += copy;
return output;
};
It takes in a char that contains a packed bcd value and outputs it in standard binary (in a char again).
This was the most efficient way I could think of doing it, please tell me if you can think of anything more efficient.
(except for writing it in assembler
)
Thanks,
Jules
Re: time fetch error
Posted: Fri Jun 27, 2008 2:54 pm
by eax
This post should help me in the next few weeks if I keep reading . (Not meaning to go offtopic but in case you didnt check my last edit on that other post, well no offense taken with any of that , it was all easily warranted comments. (I also follow where I have been mis-interpretting much of the code thanks to a latter comment you made, I was thinking about the & in terms of the address of pointer operator as opposed to logical and!! dow! - anyway better not get into that here cheers anyway)
Re: time fetch error
Posted: Fri Jun 27, 2008 3:13 pm
by suthers
eax wrote:anyway better not get into that here cheers anyway)
good point
, I hope the code helps though...
Jules
Re: time fetch error
Posted: Fri Jun 27, 2008 3:17 pm
by suthers
Oh and if you want any help with the code for the time (or snippets), just PM me...
Jules
Re: time fetch error
Posted: Sat Jun 28, 2008 12:25 am
by os64dev
suthers wrote:*snip*
It takes in a char that contains a packed bcd value and outputs it in standard binary (in a char again).
This was the most efficient way I could think of doing it, please tell me if you can think of anything more efficient.
(except for writing it in assembler
)
Thanks,
Jules
The fastest method is not to depack it anyway, just display it as hexidecimal and it will show the correct time.
I think there is also a bit somewhere in the CMOS that tells if the data in in BCD or in plain decimal.
Re: time fetch error
Posted: Sat Jun 28, 2008 1:10 am
by Brendan
Hi,
os64dev wrote:suthers wrote:*snip*
It takes in a char that contains a packed bcd value and outputs it in standard binary (in a char again).
This was the most efficient way I could think of doing it, please tell me if you can think of anything more efficient.
(except for writing it in assembler
)
The fastest method is not to depack it anyway, just display it as hexidecimal and it will show the correct time.
That works, until you start doing calculations (like converting to/from UTC, or working out "seconds since 1970").
The next fastest way is probably to use a lookup table (especially if it's likely the table will be in the CPUs cache). You could probably even do 2 values at a time (use an array of 16-bit integers with 65536 entries).
os64dev wrote:I think there is also a bit somewhere in the CMOS that tells if the data in in BCD or in plain decimal.
There is, and you can change this bit so that the RTC operates in "binary mode", but that will mess up other OSs (e.g. Windows) and the BIOS. It might be a good idea to skip the BCD->binary conversion if the RTC is in binary mode though (in case some other OS changed it).
If you do change the RTC from "BCD mode" to "binary mode" then you need to update the rest of the RTC because changing the mode won't change the values reported (you'd just end up with an RTC using binary mode on BCD data, which will stuff things up). You can't switch to binary mode, then read the values, then switch back to BCD mode.
Also note that the location of the century value is *not* standard, and you shouldn't assume that it's in "CMOS location 0x32". Older computers didn't have any century value at all, and for newer computers you should find out where it is from ACPI tables (from the FADT?).
If there is no century value (or if you couldn't be bothered with ACPI) you could just assume "century = 20" and you'd be good for about 92 years. A better idea might be "#define CURRENT_YEAR 08" followed by "if (year >= CURRENT_YEAR) {century = 20} else {century = 21}". In this case you're good for almost 100 years after the OS was released, and you can update "CURRENT_YEAR" each time you release a new version of your OS.
Cheers,
Brendan
Re: time fetch error
Posted: Sat Jun 28, 2008 3:23 am
by suthers
Brendan wrote:Also note that the location of the century value is *not* standard, and you shouldn't assume that it's in "CMOS location 0x32". Older computers didn't have any century value at all, and for newer computers you should find out where it is from ACPI tables (from the FADT?).
Well, it works for the moment (does this mean that dexos is flawed?), but I'll get round to reading the location of the century from the ACPI tables.
Thanks,
Jules
Re: time fetch error
Posted: Sat Jun 28, 2008 10:21 am
by Brendan
Hi,
suthers wrote:Brendan wrote:Also note that the location of the century value is *not* standard, and you shouldn't assume that it's in "CMOS location 0x32". Older computers didn't have any century value at all, and for newer computers you should find out where it is from ACPI tables (from the FADT?).
Well, it works for the moment (does this mean that dexos is flawed?), but I'll get round to reading the location of the century from the ACPI tables.
Windows is flawed, Linux is flawed, Free/Net/OpenBSD is flawed, DOS was flawed, OS/2 was flawed, OS X is flawed, my OSs are flawed. I haven't seen the source code for DexOS - maybe it's the only OSs that's ever existed that doesn't have flaws?
Cheers,
Brendan
Re: time fetch error
Posted: Sat Jun 28, 2008 3:30 pm
by suthers
Dex makes no mistakes...
Jules
Re: time fetch error
Posted: Sat Jun 28, 2008 3:36 pm
by Combuster
suthers wrote:Dex makes no mistakes...
Jules
No, that's a feature
Re: time fetch error
Posted: Wed Oct 15, 2008 9:43 am
by sawdust
piranha wrote:
Code: Select all
unsigned char read_cmos(unsigned char addr)
{
unsigned char r;
outb(0x70,addr);
__asm__ __volatile__ ("jmp 1f; 1: jmp 1f;1:");
r = inb(0x71);
__asm__ __volatile__ ("jmp 1f; 1: jmp 1f;1:");
return r;
}
Code: Select all
#define BCD2BIN(bcd) ((((bcd)&15) + ((bcd)>>4)*10))
get_time_stuff()
{
asm("cli");
now.sec = BCD2BIN(readCMOS(0x0));
now.min = BCD2BIN(readCMOS(0x2));
now.hour = BCD2BIN(readCMOS(0x4));
now.day = BCD2BIN(readCMOS(0x7));
now.month = BCD2BIN(readCMOS(0x8));
now.year = BCD2BIN(readCMOS(0x9));
asm("sti");
}
Hi,
I tried this one and got the following
sec= 18, min=1, hour=19, day= 14, month=10, year=8 century= 20
The actual time was 1:01 p.m, 18 seconds, 10/14/2008.
Why is hour=19 instead of 13 or 1 ?
TIA