time fetch error

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

time fetch error

Post by suthers »

I'm currently writing a function that reads the time...
I general gist of how to do it of DexOS (Thanks Dex :D )
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
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: time fetch error

Post by Korona »

IIRC CMOS values are stored in bcd notation.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: time fetch error

Post 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
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: time fetch error

Post 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....
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: time fetch error

Post 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 :wink: :

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 :D )
Thanks,

Jules
eax
Member
Member
Posts: 57
Joined: Mon Jun 23, 2008 6:45 am

Re: time fetch error

Post 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)
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: time fetch error

Post by suthers »

eax wrote:anyway better not get into that here cheers anyway)
good point :wink:, I hope the code helps though...
Jules
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: time fetch error

Post by suthers »

Oh and if you want any help with the code for the time (or snippets), just PM me...
Jules
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Re: time fetch error

Post 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 :D )
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.
Author of COBOS
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: time fetch error

Post 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 :D )
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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: time fetch error

Post 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
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: time fetch error

Post 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? 8)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: time fetch error

Post by suthers »

Dex makes no mistakes... :lol:
Jules
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: time fetch error

Post by Combuster »

suthers wrote:Dex makes no mistakes... :lol:
Jules
No, that's a feature :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
sawdust
Member
Member
Posts: 51
Joined: Thu Dec 20, 2007 4:04 pm

Re: time fetch error

Post 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
Post Reply