reading motherboard I/O address?

Just starting out? Need help? Post your questions and find answers here.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.

Hi Kale

Only Mb temp is returned correct as is, all other reading need some calculations :)
There are no floats returned, all byte values.
Here is the data sheet, all starts at page 104.
http://www.benny.zeb.be/w83627hf.pdf

fans are at $28, S29, $2a
FanRPM1 = 1350000 / FanDiv1 / value
fandiv1 is the fandivisor you have to set in the chip at startup, if the in-chip value is different than the one you use, rpm is wrong.
Watch out, if value read is 0 (fan stopped) you get divide by zero exeption, so first check.
here is the procedure to set the fan divisor

Code: Select all

Procedure setfandiv()
  ; ---------------- fan 1 en 2 ---------------------
  waarde.b = 0
  Select FanDiv1
    Case 1
      waarde.b = 0
    Case 2
      waarde.b = %10000
    Case 4
      waarde.b = %100000
    Case 8
      waarde.b = %110000
  EndSelect
  Select FanDiv2
    Case 2
      waarde.b=waarde.b+%1000000
    Case 4
      waarde.b=waarde.b+%10000000
    Case 8
      waarde.b=waarde.b+%11000000
  EndSelect
  
  ; fan 1 en 2
  WritePort( $295,  $47)
  WritePort( $296,  waarde.b)
  ; ---------------- fan 3 ---------------------
  waarde.b = 0
  Select FanDiv3
    Case 1
      waarde.b = 0
    Case 2
      waarde.b = %1000000
    Case 4
      waarde.b = %10000000
    Case 8
      waarde.b = %11000000
  EndSelect
  ; fan3
  
  WritePort( $295,  $4b)
  WritePort( $296,  waarde.b)
  
EndProcedure
A good value that mostly works okay for FanDiv1 to fanDiv3 is 4
So if you read the fans, and do the above calculation, it could work :)

voltages are little easyer.

Code: Select all

core0     = (Read($20) * 16)
core1     = (Read($21) * 16)
volt3     = (Read($22) * 16)
volt5     = (Read($23) * 16) / (50000 / (50000 + 34000))
volt12    =(Read($24) * 16) / (10000 / (10000 + 28000))
volt12neg = ((Read($25) * 16) - 3600 *  (232000 / (232000 + 56000))) / (1 -  (232000 / (232000 + 56000)))
volt5neg  = ((Read($26) * 16) - 3600 *  (120000 / (120000 + 56000))) / (1 -  (120000 / (120000 + 56000)))
All voltages are in mV, so 3.3V = 3300
The values 120000 and 56000 etc.. are the resistors on my ASUS board, and recommended by Winbond.
Could be that they are different on your board...(its not 100% standard)
But this values work fine on my Winbond chip, so il guess it will be ok for you.
I did not convert from TvicHW32 to WinIO...

Good luck,


Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.

thats extremely helpful! thanks....but.. :) i just wondered where did you get these values for the fans/voltages etc.? i noticed your .pdf is a different version chip than the one i've got, are they all contained within?

using these registers i have got sys temp and cpu voltage correct but im having trouble with the fans and cpu temp:

register: returns:
$28 25
$29 -1
$2a -1

i'm guessing i need to take a look at the W83697HF.pdf data sheet, i better get searching



--Kale

New to PureBasic and falling in Love! :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.

The PDF is for the w83627hf chip, check at Winbond for a correct datasheet http://www.winbond.com/e-winbondhtm/par ... ?Pname=184
But all Winbond Chip are very compatible, no problem, i used the values of my RAIDmonitor app using a WD83782D chip.

For correct CPU temp, you have to add a fixed value, depends on your motherboard and CPU.
Just check CPU temp in BIOS, and add difference to your reading.(don't trust other hw monitor tool, only from board manufacturer)
Every CPU type and speed is different temp, The BIOS knows this.

FAN $29 and $2A, maybe no 3rd tacho wire, or the divisor is not good, you read 255 , not -1 (stru(-1,#byte))
This looks like there is a fan, but the rotation time is higher than the max time value / divisor.(255)
Try to set the divisor (FanDiv2 and FanDiv3) to other value, mostly bigger fan runs slower, and need higher divisor.


This is the calculation for your fan1, play with the divisor to match BIOS reading.

Code: Select all

Value=25
Fandiv1=8
FanRPM1 = 1350000 / FanDiv1 / value
Debug FanRPM1
Reading chips is fun, my first board was the ASUS 2PL97 in 1997

Happy searching and coding :)


Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.

i seem to be able to read all values ok apart from the CPU temp, i found this in the data sheet:

code i'm using at the minute:

Code: Select all

#WRITE_REG = $295
#READ_REG = $296
CallFunction(0, "SetPortVal", #WRITE_REG, $50, 1)
CallFunction(0, "GetPortVal", #READ_REG, @cpuTemp, 1)
Debug "CPU Temperature: "+StrU(cpuTemp, #Byte)+"ºC"
it reads CPU Temperature: 255ºC! now i'm sure thats wrong :)

--Kale

New to PureBasic and falling in Love! :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.

All you read until now is in Bank 0 of the chip's registers
This is the default bank
You must switch to Bank 1 for temperature sensor 2



The BANK select register is at $4e
Before reading CPU temp, First set the correct bit to select bank 1
But first read the current value of this register, set the correct bit, and write back.
Never change the value of the other bits
After reading the temp2 sensor, bank 0 will be automaticly selected again




Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.
The BANK select register is at $50
Before reading CPU temp, First set the correct bit to select bank 1
But first read the current value of this register, set the correct bit, and write back.
Never change the value of the other bits
After reading the temp2 sensor, bank 0 will be automaticly selected again
i have absolutely no idea how to do this :)

--Kale

New to PureBasic and falling in Love! :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.
The BANK select register is at $50
Uups sorry, this is at $4E

Here something that could work

Code: Select all

#ADR_REG = $295
#DATA_REG = $296

CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
CallFunction(0, "GetPortVal", #DATA_REG, @Bank, 1) ; read current value of bank switch register
Bank | %00000010  ; set 2nd bit for bank 1
CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
CallFunction(0, "SetPortVal", #DATA_REG, @Bank, 1) ; and write it to select bank

; now read cpu temp
CallFunction(0, "SetPortVal", #ADR_REG, $50, 1)
CallFunction(0, "GetPortVal", #DATA_REG, @CpuTemp, 1)
Debug "CPU Temperature: "+StrU(CpuTemp, #Byte)+"ºC"


Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.

CPU Temperature still reads 255ºC :cry: grrrrr...

--Kale

New to PureBasic and falling in Love! :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.
Originally posted by Berikco


...

Code: Select all

#ADR_REG = $295
#DATA_REG = $296

CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
CallFunction(0, "GetPortVal", #DATA_REG, @Bank, 1) ; read current value of bank switch register
Bank | %00000010  ; set 2nd bit for bank 1
CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
CallFunction(0, "SetPortVal", #DATA_REG, @Bank, 1) ; and write it to select bank

; now read cpu temp
CallFunction(0, "SetPortVal", #ADR_REG, $50, 1)
CallFunction(0, "GetPortVal", #DATA_REG, @CpuTemp, 1)
Debug "CPU Temperature: "+StrU(CpuTemp, #Byte)+"ºC"
I'm a little curious about this line:

Code: Select all

Bank | %00000010  ; set 2nd bit for bank 1
Shouldn't it instead be?:

Code: Select all

Bank | %00000001  ; set 1st bit for bank 1
Just a suggestion, haven't played with this kind of stuff on a PC-system before..
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.
Originally posted by Pupil
I'm a little curious about this line:

Code: Select all

Bank | %00000010  ; set 2nd bit for bank 1
Shouldn't it instead be?:

Code: Select all

Bank | %00000001  ; set 1st bit for bank 1
Just a suggestion, haven't played with this kind of stuff on a PC-system before..
No, this is for selecting bank 0 (zero)


Kale, try this again
There whas a error in this line
CallFunction(0, "SetPortVal", #DATA_REG, @Bank, 1) ; and write it to select bank
Problem is i can't test it here, but when this topic reaches 100 posts, i'm sure it will work :)

Code: Select all

#ADR_REG = $295
#DATA_REG = $296

CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
CallFunction(0, "GetPortVal", #DATA_REG, @Bank, 1) ; read current value of bank switch register
Bank | %00000010  ; set 2nd bit for bank 1
CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
CallFunction(0, "SetPortVal", #DATA_REG, Bank, 1) ; and write it to select bank

; now read cpu temp
CallFunction(0, "SetPortVal", #ADR_REG, $50, 1)
CallFunction(0, "GetPortVal", #DATA_REG, @CpuTemp, 1)
Debug "CPU Temperature: "+StrU(CpuTemp, #Byte)+"ºC"


Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.

> No, this is for selecting bank 0 (zero)

Sorry but i think you're wrong. With your logic, how do you go about it to select bank4 there's only 3 bank select bits and you've said that bit 0 is for bank0 and bit 1 to select bank1 extrapolation gives that the next bit(bit 2) is to select bank2..In my mind this doesn't compute correctly.

I think that this is how it works:
bit2-bit0 gives the address of the bank i.e. %000(bank0), %001(bank1), %010(bank2), %011(bank3), %100(bank4), %101(bank5), %110(bank6), %111(bank7)

Don't take this post the wrong way, i'm not trying to lecture you or something, just trying to help you in case this chip doesn't work as you first aticipated.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.

Uuups true pupil, i looked over this, thanks :)
My ASUS chip works a little different, no bankswitching needed.
It has just another SMBus adress for temp sensor 2, wich ends with %...10

This one works just binary...

Any cooler results Kale?






Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.

Yipee! success atlast :) all seems to be working using this code:

Code: Select all

Procedure.s floatToString(number.f, nPlaces.l)
    r=Pow(10,nPlaces)
    vf.f=number*r
    vs.s=Str(vf)
    rs.s=Left(vs,Len(vs)-nPlaces)+"."+Right(vs,nPlaces)
    ProcedureReturn rs
EndProcedure

#ADR_REG = $295
#DATA_REG = $296

If OpenLibrary(0, "WinIo.dll")

    ;Initialise
    CallFunction(0, "InitializeWinIo")

    ;CPU Temperature
    CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
    CallFunction(0, "GetPortVal", #DATA_REG, @bank, 1) ; read current value of bank switch register
    bank | %00000001  ; set 1st bit for bank 1
    CallFunction(0, "SetPortVal", #ADR_REG, $4E, 1)
    CallFunction(0, "SetPortVal", #DATA_REG, bank, 1) ; and write it to select bank
    CallFunction(0, "SetPortVal", #ADR_REG, $50, 1) ; get temp
    CallFunction(0, "GetPortVal", #DATA_REG, @CpuTemp, 1)
    Debug "CPU Temperature: "+StrU(CpuTemp, #Byte)+"ºC"

    ;System Temperature
    CallFunction(0, "SetPortVal", #ADR_REG, $27, 1)
    CallFunction(0, "GetPortVal", #DATA_REG, @systemTemp, 1)
    Debug "System Temperature: "+StrU(systemTemp, #Byte)+"ºC"

    ;CPU Fan
    CallFunction(0, "SetPortVal", #ADR_REG, $28, 1)
    CallFunction(0, "GetPortVal", #DATA_REG, @cpuFan, 1)
    fanDivisor = 4
    cpuFan = 1350000 / fanDivisor / cpuFan
    Debug "CPU Fan: "+Str(cpuFan)+"rpm"

    ;CPU Voltage
    CallFunction(0, "SetPortVal", #ADR_REG, $20, 1)
    CallFunction(0, "GetPortVal", #DATA_REG, @cpuVoltage, 1)
    adjVoltage.s = floatToString((cpuVoltage*16)/1000, 2)
    Debug "CPU Voltage: "+adjVoltage+"v"

    ;Clean up
    CallFunction(0, "ShutdownWinIo")

EndIf
I am learning a great deal from this, thanks. Just a few questions though, 1). how would i get the CPU temp after the decimal place (55.5 instead of just 55) and 2). if i run my program all the values are right but when i run hardware doctor to display these values, then quit and then run my program again the fan speed is way out! like this:

my program 1st time: CPU Fan: 6750
hardware doc 1st time: CPU Fan: 6750
my program 2nd time: CPU Fan: 13500

im guessing hardware doc is setting the fan divisor somewhere to 8. using this code to set it back again doesn't seem to work:

Code: Select all

divisor.b = %110000 + %11000000
CallFunction(0, "SetPortVal", #ADR_REG,  $47, 1)
CallFunction(0, "SetPortVal", #DATA_REG,  divisor, 1)
any ideas?

--Kale

New to PureBasic and falling in Love! :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Berikco.
1). how would i get the CPU temp after the decimal place (55.5 instead of just 55)
There is an extra bit at $51 (bank1, bit 7) wich represends the 0.5
2). if i run my program all the values are right but when i run hardware doctor to display these values, then quit and then run my program again the fan speed is way out! like this:
im guessing hardware doc is setting the fan divisor somewhere to 8. using this code to set it back again doesn't seem to work:
Yep, same error i got about 5 years ago, and you are wright, hd changes the fandiv.
But your code to set Fandivisor is correct, try to read the register after hd has started, and use this, maybe this divisor is better.
Remember it takes a second for chip and fan to adjust to a newly set divisor.
you must always read the chips current fandiv at startup, or set your one in it. If you don't , it looks like fan is running double speed :)
And also, running two hardware monitor apps at same time can give very strange results...



Regards,

Berikco

http://www.benny.zeb.be
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Kale.

Thankyou all for your help especially Berikco, i seem to have all working now, thanks. This was a good learning thread for me.

--Kale

New to PureBasic and falling in Love! :)
Post Reply