Created
January 30, 2012 05:27
-
-
Save midnightmagic/1702722 to your computer and use it in GitHub Desktop.
artfan
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define LINUX 1 | |
#include "adl_sdk.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#define DEBUG_ERROR (verbosity == verbosity) | |
#define DEBUG_INFO (verbosity >= 1) | |
#define LOGBUFSIZE 1024 | |
//Main Group of APIs | |
extern int ADL_Main_Control_Create(ADL_MAIN_MALLOC_CALLBACK, int); | |
extern int ADL_Main_Control_Destroy(); | |
//General Adapter APIs | |
extern int ADL_Adapter_NumberOfAdapters_Get(int *); | |
extern int ADL_Adapter_AdapterInfo_Get(LPAdapterInfo, int); | |
//Overdrive5 APIs | |
extern int ADL_Overdrive5_Temperature_Get(int, int, ADLTemperature *); | |
extern int ADL_Overdrive5_FanSpeedInfo_Get(int, int, ADLFanSpeedInfo *); | |
extern int ADL_Overdrive5_FanSpeed_Get(int, int, ADLFanSpeedValue *); | |
extern int ADL_Overdrive5_FanSpeed_Set(int, int, ADLFanSpeedValue *); | |
extern int ADL_Overdrive5_CurrentActivity_Get(int, ADLPMActivity *); | |
struct tinfo { | |
int iAdapterIndex; | |
char strUDID[256]; | |
int iBusNumber; | |
int iSlaveIndex; | |
int iMasterTemp; | |
int iSlaveTemp; | |
int iMinPercent; | |
int iMaxPercent; | |
int iFanSpeed; | |
int iTemp; | |
char velocity; | |
int nPrevTemp; | |
float fIntegral; | |
int iPrevSum; | |
int iPrevTemps[60]; | |
int iRealFanSpeed; | |
int iEngineClock; | |
int iMemoryClock; | |
int iActivityPercent; | |
int iSlaveEngineClock; | |
int iSlaveMemoryClock; | |
int iSlaveActivityPercent; | |
int iMaxActivityPercent; | |
}; | |
struct slave_candidates { | |
int iAdapterIndex; | |
int iBusNumber; | |
int candidate; | |
}; | |
#define MAX_ADAPTERS 8 | |
int ninfos; | |
//struct tinfo info[MAX_ADAPTERS]; | |
struct tinfo *info=NULL; | |
struct slave_candidates *sinfo=NULL; | |
// Memory allocation function | |
void* __stdcall ADL_Main_Memory_Alloc ( int iSize ) | |
{ | |
void* lpBuffer = calloc ( iSize, 1 ); | |
return lpBuffer; | |
} | |
// Optional Memory de-allocation function | |
void __stdcall ADL_Main_Memory_Free ( void** lpBuffer ) | |
{ | |
if ( NULL != *lpBuffer ) | |
{ | |
free ( *lpBuffer ); | |
*lpBuffer = NULL; | |
} | |
} | |
void do_dump_info(LPAdapterInfo b, unsigned long int i) { | |
printf("Retrieving from index %ld..\n", i); | |
printf("iSize: %d iAdapterIndex: %d\n", (*b).iSize, (*b).iAdapterIndex); | |
printf("strUDID: %s\n", (*b).strUDID); | |
printf("iBusNumber: %d iDeviceNumber: %d iFunctionNumber: %d\n", | |
(*b).iBusNumber, (*b).iDeviceNumber, (*b).iFunctionNumber); | |
printf("iVendorID: %d\n", (*b).iVendorID); | |
printf("strAdapterName: %s\n", (*b).strAdapterName); | |
printf("strDisplayName: %s\n", (*b).strDisplayName); | |
printf("iPresent: %d iXScreenNum: %d iDrvIndex: %d\n", | |
(*b).iPresent, (*b).iXScreenNum, (*b).iDrvIndex); | |
printf("strXScreenConfigName: %s\n", (*b).strXScreenConfigName); | |
printf("Calculated struct size: %ld\n", sizeof(*b)); | |
printf("----------\n"); | |
} | |
void dump_info(LPAdapterInfo b, int size, int i) { | |
if (0>i) { | |
i=0; | |
while(i<size) { | |
do_dump_info(b+i, i); | |
i++; | |
} | |
} else { | |
do_dump_info(b+i, (unsigned long int)i); | |
} | |
} | |
int enum_adapters(int minfan, int verbosity) | |
{ | |
int iNumAdapters = 0; | |
LPAdapterInfo lpAdapterInfo = NULL; | |
int i, j, dupe, lpStatus; | |
ADLTemperature Temperature; | |
ADLFanSpeedInfo FanSpeedInfo; | |
ADLFanSpeedValue FanSpeedValue; | |
if(ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "ADL Initialization Error!\n"); | |
return 1; | |
} | |
if(ADL_Adapter_NumberOfAdapters_Get(&iNumAdapters) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get the number of adapters!\n"); | |
return 1; | |
} else { | |
if (DEBUG_INFO) | |
printf("Total number of adapters known: %d\n", iNumAdapters); | |
if (8<iNumAdapters) { | |
if (DEBUG_INFO) | |
printf("Do you really have %d adapters in-system? I guess we'll see.\n", iNumAdapters); | |
} | |
} | |
if(iNumAdapters <= 0) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "No adapters found!\n"); | |
return 1; | |
} | |
if (!info) { | |
info=calloc(sizeof(struct tinfo),iNumAdapters); | |
if (!info) { | |
if (DEBUG_ERROR) | |
printf("Unable to allocate %ld bytes!\n", sizeof(struct tinfo)*iNumAdapters); | |
return 1; | |
} | |
} | |
if (!sinfo) { | |
sinfo=calloc(sizeof(struct slave_candidates),iNumAdapters); | |
if (!sinfo) { | |
if (DEBUG_ERROR) | |
printf("Unable to allocate %ld bytes!\n", sizeof(struct slave_candidates)*iNumAdapters); | |
return 1; | |
} | |
} | |
lpAdapterInfo = calloc(iNumAdapters,sizeof(AdapterInfo)); | |
// memset(lpAdapterInfo, 0, iNumAdapters * sizeof(AdapterInfo)); | |
if(ADL_Adapter_AdapterInfo_Get(lpAdapterInfo, iNumAdapters * sizeof(AdapterInfo)) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get adapter info!\n"); | |
return 1; | |
} | |
ninfos = 0; | |
for(i = 0; i < iNumAdapters; i++) { | |
// skip ghost adapters.. | |
if (ADL_Adapter_Active_Get(lpAdapterInfo[i].iAdapterIndex, &lpStatus) != ADL_OK) { | |
if (DEBUG_INFO) | |
printf("Unable to check adapter %d active state. Skipping.\n", lpAdapterInfo[i].iAdapterIndex); | |
return 1; | |
} else { | |
if (lpStatus != ADL_TRUE) { | |
if (DEBUG_INFO) | |
printf("Reported state of %d is %d, NOT ADL_TRUE, skipping.\n", lpAdapterInfo[i].iAdapterIndex, lpStatus); | |
continue; | |
} | |
} | |
if(! lpAdapterInfo[i].iPresent || lpAdapterInfo[i].iXScreenNum < 0 | |
|| lpAdapterInfo[i].strXScreenConfigName[0] == 0x0 ) { | |
if (DEBUG_INFO) | |
printf("Adapter %d appears to be a ghost. Skipping.\n", lpAdapterInfo[i].iAdapterIndex); | |
continue; | |
} | |
//ignore duplicate adapters | |
dupe = 0; | |
for(j = 0; j < ninfos; j++) { | |
if(!strcmp(lpAdapterInfo[i].strUDID, info[j].strUDID)) { | |
if (DEBUG_INFO) | |
printf("Adapter %d appears to have a duplicate strUDID with adapter %d. Skipping.\n", lpAdapterInfo[i].iAdapterIndex, lpAdapterInfo[j].iAdapterIndex); | |
dupe = 1; | |
break; | |
} | |
} | |
if(dupe) | |
continue; | |
memset(&Temperature, 0, sizeof(ADLTemperature)); | |
Temperature.iSize = sizeof(ADLTemperature); | |
if(ADL_Overdrive5_Temperature_Get(lpAdapterInfo[i].iAdapterIndex, 0, &Temperature) != ADL_OK) { | |
if (DEBUG_INFO) | |
fprintf(stderr, "Cannot get temperature!\n"); | |
return 1; | |
} else { | |
if (DEBUG_INFO) | |
printf("Retrieved temp from %d %3i.%01i°C\n", lpAdapterInfo[i].iAdapterIndex, Temperature.iTemperature / 1000, (Temperature.iTemperature % 1000) / 100 ); | |
} | |
memset(&FanSpeedInfo, 0, sizeof(ADLFanSpeedInfo)); | |
FanSpeedInfo.iSize = sizeof(ADLFanSpeedInfo); | |
if(ADL_Overdrive5_FanSpeedInfo_Get(lpAdapterInfo[i].iAdapterIndex, 0, &FanSpeedInfo) != ADL_OK) { | |
if (DEBUG_INFO) | |
fprintf(stderr, "Cannot get fan speed info!\n"); | |
// return 1; | |
} | |
if(!(FanSpeedInfo.iFlags & (ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ | ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE))) { | |
if (DEBUG_INFO) | |
fprintf(stderr, "Adapter doesn't support fan speed control! %i Slave candidate..?\n", FanSpeedInfo.iFlags); | |
sinfo[lpAdapterInfo[i].iAdapterIndex].iAdapterIndex=lpAdapterInfo[i].iAdapterIndex; | |
sinfo[lpAdapterInfo[i].iAdapterIndex].iBusNumber=lpAdapterInfo[i].iBusNumber; | |
sinfo[lpAdapterInfo[i].iAdapterIndex].candidate=1; | |
continue; | |
} | |
memset(&FanSpeedValue, 0, sizeof(ADLFanSpeedValue)); | |
FanSpeedValue.iSize = sizeof(ADLFanSpeedValue); | |
FanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; | |
if(ADL_Overdrive5_FanSpeed_Get(lpAdapterInfo[i].iAdapterIndex, 0, &FanSpeedValue) != ADL_OK) { | |
if (DEBUG_INFO) | |
fprintf(stderr, "Cannot get fan speed!\n"); | |
return 1; | |
} | |
info[ninfos].iAdapterIndex = lpAdapterInfo[i].iAdapterIndex; | |
strcpy(info[ninfos].strUDID, lpAdapterInfo[i].strUDID); | |
info[ninfos].iBusNumber = lpAdapterInfo[i].iBusNumber; | |
info[ninfos].iSlaveIndex = -1; // Sentinel value, -1 means Master has no slave | |
// info[ninfos].iMinPercent = FanSpeedInfo.iMinPercent; | |
info[ninfos].iMinPercent = (FanSpeedInfo.iMinPercent < minfan ? minfan : FanSpeedInfo.iMinPercent); | |
// info[ninfos].iMinPercent = 30.0; // FTS man..! Setting fan minimum to 0?! | |
info[ninfos].iMaxPercent = FanSpeedInfo.iMaxPercent; | |
info[ninfos].iFanSpeed = FanSpeedValue.iFanSpeed; | |
info[ninfos].iTemp = Temperature.iTemperature; | |
info[ninfos].fIntegral = 0.; | |
info[ninfos].nPrevTemp = 0; | |
info[ninfos].iPrevSum = info[ninfos].iTemp * 60; | |
for(j = 0; j < 60; j++) | |
info[ninfos].iPrevTemps[j] = info[ninfos].iTemp; | |
if (DEBUG_INFO) | |
fprintf(stdout, "Adapter %i: idx %i temp %3i.%01i°C speed %3i%% (%3i%% - %3i%%)\n", | |
ninfos, | |
info[ninfos].iAdapterIndex, | |
info[ninfos].iTemp / 1000, (info[ninfos].iTemp % 1000) / 100, | |
info[ninfos].iFanSpeed, | |
info[ninfos].iMinPercent, | |
info[ninfos].iMaxPercent); | |
ninfos += 1; | |
} | |
if(ninfos == 0) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "No adapters found!\n"); | |
return 1; | |
} | |
//find slaves | |
for(i = 0; i < iNumAdapters; i++) { | |
for(j = 0; j < ninfos; j++) { | |
if(info[j].iSlaveIndex == -1) { | |
if((info[j].iBusNumber == lpAdapterInfo[i].iBusNumber + 1) || (info[j].iBusNumber == lpAdapterInfo[i].iBusNumber - 1)) { | |
if (sinfo[i].candidate != 0) { | |
info[j].iSlaveIndex = lpAdapterInfo[i].iAdapterIndex; | |
if (DEBUG_INFO) | |
printf("Found probable slave for Bus %d on Bus %d\n", info[j].iBusNumber,lpAdapterInfo[i].iBusNumber); | |
break; | |
} | |
} | |
} | |
} | |
} | |
return 0; | |
} | |
static float targettemp = 85.0; //deg C | |
static int minfan = 30; | |
static float Kp = 1.; | |
static float Ki = 0.5; | |
static float Kd = 1.; | |
static float Ff = 0.2; | |
static int verbosity=0; | |
static int sleepytime=3; | |
int calc_new_fanspeed(int idx) | |
{ | |
float curtemp, avgtemp; | |
float Sp, Si, Sd, Sf, Ss; | |
int newfanspeed; | |
curtemp = (float)(info[idx].iTemp) / 1000.0; | |
info[idx].fIntegral += curtemp - targettemp; | |
// Clamp integral else long-running fan controller | |
// running @ 10% or whatever minfan is, would NEVER | |
// POSSIBLY hope to ever catch up to runaway card temps | |
// and we guarantee we hit the danger safety zone | |
// trigger, throwing away the smooth PID curves. :( | |
// The clamp value was chosen because we want | |
// at most 10 seconds to overcome historical | |
// fIntegral accumulation. | |
if (info[idx].fIntegral < (float)minfan/Ki) | |
info[idx].fIntegral = (float)minfan/Ki; | |
avgtemp = (float)(info[idx].iPrevSum) / (1000.0 * 60); | |
Sp = (curtemp - targettemp) * Kp; | |
Si = info[idx].fIntegral * Ki; | |
Sd = (curtemp - avgtemp) * Kd; | |
Sf = (float)(info[idx].iMaxActivityPercent) * Ff; | |
Ss = Sp + Si + Sd; | |
if (idx == 0 && (DEBUG_INFO)) | |
printf("\n(Sp:%f + Si:%f + Sd:%f)>Sf:%f?\n", Sp, Si, Sd, Sf); | |
newfanspeed = Ss; | |
// This is a feed-forward override. | |
// When the card is extra-busy, we can set the | |
// Fan to some fraction of max based on card busy-ness | |
// Which will prevent insane runaway that PID isn't | |
// reacting fast enough to. | |
newfanspeed=(newfanspeed < Sf)?Sf:newfanspeed; | |
if(newfanspeed < info[idx].iMinPercent) | |
newfanspeed = info[idx].iMinPercent; | |
if(newfanspeed > info[idx].iMaxPercent) | |
newfanspeed = info[idx].iMaxPercent; | |
if(curtemp > targettemp + 5.0) { | |
newfanspeed = info[idx].iMaxPercent; | |
// The integral is the knob that most directly contributes | |
// to fanspeed. If we set it to 100 here, fanspeed goes to | |
// 100% -- so this should probably more accurately be | |
// set to iMaxPercent.. | |
info[idx].fIntegral = 100.; | |
} | |
if (newfanspeed < minfan) { | |
return minfan; | |
} else { | |
return newfanspeed; | |
} | |
} | |
int main(int argc, char **argv) | |
{ | |
int i, tfanspeed, opt; | |
int opflags; | |
char *logfile=NULL, *logbuf=NULL; | |
int f=0; off_t l; time_t t; | |
ADLTemperature Temperature; | |
ADLFanSpeedValue FanSpeedValue; | |
ADLFanSpeedValue FanSpeedCurrent; | |
ADLPMActivity PMActivity; | |
if (argc > 1) { | |
while ((opt=getopt(argc, argv, "hl:t:m:p:i:d:s:vf:")) != -1) { | |
switch(opt) { | |
case 'h': | |
printf("artfan v0.2, based originally on ArtForZz's awesome generous pastebin.\n"); | |
printf("Seriously, very very few of you fully realise how important his contributions have been.\n"); | |
printf("Modified very heavily by midnightmagic. Modifications ©2011 midnightmagic\n"); | |
printf("Usage: %s [ [-h] | [-l logfile] [-t targettemp] [-m minfan] [-s sleepinterval] [-v[v]] [-p Kp] [-i Ki] [-d Kd] [ -f FeedForward ]\n", argv[0]); | |
return 1; | |
case 'l': | |
printf("Logging to: %s\n", optarg); | |
if (logfile) { | |
free(logfile); | |
logfile=NULL; // probably unnecessary | |
} | |
logfile=calloc(strlen(optarg)+1, 1); | |
if (NULL==logfile) { | |
if (DEBUG_ERROR) | |
printf("Error allocating %d bytes.\n", (int)strlen(optarg)+1); | |
return 1; | |
} | |
strncpy(logfile, optarg, strlen(optarg)+1); | |
if (logbuf) { | |
free(logbuf); | |
logbuf=NULL; // also probably unnecessary | |
} | |
if ((logbuf=calloc(LOGBUFSIZE+1,1)) == NULL) { | |
// and now we can use logbuf != NULL to check if we should log, later on. | |
if (DEBUG_ERROR) | |
printf("Could not allocate %d bytes for logfile buffer.\n", LOGBUFSIZE); | |
return 1; | |
} | |
break; | |
case 't': | |
targettemp=atof(optarg); | |
if (DEBUG_INFO) | |
printf("Setting target temperature to %.2f\n", targettemp); | |
break; | |
case 'm': | |
minfan=atoi(optarg); | |
if (DEBUG_INFO) | |
printf("Setting minfan speed to %d\n", minfan); | |
break; | |
case 'p': | |
Kp=atof(optarg); | |
if (DEBUG_INFO) | |
printf("Setting Kp to %f\n", Kp); | |
break; | |
case 'i': | |
Ki=atof(optarg); | |
if (DEBUG_INFO) | |
printf("Setting Ki to %f\n", Ki); | |
break; | |
case 'd': | |
Kd=atof(optarg); | |
if (DEBUG_INFO) | |
printf("Setting Kd to %f\n", Kd); | |
break; | |
case 's': | |
sleepytime=atoi(optarg); | |
if (DEBUG_INFO) | |
printf("Setting reset interval to %d seconds.\n", sleepytime); | |
break; | |
case 'v': | |
++verbosity; | |
if (DEBUG_INFO) | |
printf("Verbosity increased, now: %d\n", verbosity); | |
break; | |
case 'f': | |
Ff=atof(optarg); | |
if (DEBUG_INFO) | |
printf("Setting feedforward multiplier (times activityPercent) to %f\n", Ff); | |
break; | |
default: | |
if (DEBUG_ERROR) | |
printf("Unknown arg. Try -h.\n"); | |
return 1; | |
} | |
} // End of arg-runner while loop. | |
if (optind>argc) if (DEBUG_INFO) printf("Remaining args:\n"); | |
for(i=optind;i<argc;i++){ | |
if (DEBUG_INFO) | |
printf("%s\n", argv[i]); | |
} | |
if (optind>argc) return 1; | |
} | |
if(enum_adapters(minfan, verbosity)) | |
return 1; | |
memset(&Temperature, 0, sizeof(ADLTemperature)); | |
Temperature.iSize = sizeof(ADLTemperature); | |
memset(&FanSpeedValue, 0, sizeof(ADLFanSpeedValue)); | |
FanSpeedValue.iSize = sizeof(ADLFanSpeedValue); | |
FanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; | |
FanSpeedValue.iFlags = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED; | |
memset(&FanSpeedCurrent, 0, sizeof(ADLFanSpeedValue)); | |
FanSpeedCurrent.iSize=sizeof(ADLFanSpeedValue); | |
FanSpeedCurrent.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; | |
memset(&PMActivity, 0, sizeof(PMActivity)); | |
PMActivity.iSize=sizeof(PMActivity); | |
while(1) { | |
for(i = 0; i < ninfos; i++) { | |
//retrieve current fanspeed | |
if(ADL_Overdrive5_FanSpeed_Get(info[i].iAdapterIndex, 0, &FanSpeedCurrent) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get FanSpeed for card %d\n", info[i].iAdapterIndex); | |
return 1; | |
} | |
if(FanSpeedCurrent.iSpeedType==ADL_DL_FANCTRL_SPEED_TYPE_RPM) { | |
if (DEBUG_ERROR) | |
fprintf(stderr,"WARNING: Current Fan Speed in RPM NOT PERCENT AS REQUESTED! DANGER! MANUALLY SET FANSPEEDS TO SOMETHING HIGHER! QUICK!\n"); | |
return 1; | |
} | |
if(ADL_Overdrive5_CurrentActivity_Get(info[i].iAdapterIndex, &PMActivity) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get current activity for adapter %d\n", info[i].iAdapterIndex); | |
return 1; | |
} | |
info[i].iEngineClock=PMActivity.iEngineClock; | |
info[i].iMemoryClock=PMActivity.iMemoryClock; | |
info[i].iActivityPercent=PMActivity.iActivityPercent; | |
// And record the MaxActivity, which will possibly be overwritten later if the slave is doing more | |
info[i].iMaxActivityPercent=info[i].iActivityPercent; | |
//get current temp | |
if(ADL_Overdrive5_Temperature_Get(info[i].iAdapterIndex, 0, &Temperature) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get temperature for adapter %d\n", info[i].iAdapterIndex); | |
return 1; | |
} | |
info[i].iMasterTemp = Temperature.iTemperature; | |
if(info[i].iSlaveIndex != -1) { | |
if(ADL_Overdrive5_Temperature_Get(info[i].iSlaveIndex, 0, &Temperature) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get temperature for adapter %d\n", info[i].iSlaveIndex); | |
return 1; | |
} | |
info[i].iSlaveTemp = Temperature.iTemperature; | |
if(Temperature.iTemperature < info[i].iMasterTemp) { | |
Temperature.iTemperature = info[i].iMasterTemp; | |
} | |
if(ADL_Overdrive5_CurrentActivity_Get(info[i].iSlaveIndex, &PMActivity) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot get current activity for adapter %d\n", info[i].iSlaveIndex); | |
return 1; | |
} | |
info[i].iSlaveEngineClock=PMActivity.iEngineClock; | |
info[i].iSlaveMemoryClock=PMActivity.iMemoryClock; | |
info[i].iSlaveActivityPercent=PMActivity.iActivityPercent; | |
if (info[i].iMaxActivityPercent < info[i].iSlaveActivityPercent) | |
info[i].iMaxActivityPercent = info[i].iSlaveActivityPercent; | |
} | |
info[i].iRealFanSpeed = FanSpeedCurrent.iFanSpeed; | |
info[i].iPrevSum -= info[i].iPrevTemps[info[i].nPrevTemp]; | |
info[i].iPrevSum += info[i].iTemp; | |
info[i].iPrevTemps[info[i].nPrevTemp] = info[i].iTemp; | |
info[i].iTemp = Temperature.iTemperature; | |
tfanspeed = calc_new_fanspeed(i); | |
if (tfanspeed > info[i].iFanSpeed) { | |
info[i].velocity='^'; | |
} else if (tfanspeed == info[i].iFanSpeed) { | |
info[i].velocity='*'; | |
} else { | |
info[i].velocity='v'; | |
} | |
if(tfanspeed != info[i].iFanSpeed) { | |
info[i].iFanSpeed = info[i].iRealFanSpeed; // was tfanspeed here too before.. | |
// info[i].iFanSpeed = tfanspeed; | |
FanSpeedValue.iFanSpeed = tfanspeed; | |
if(ADL_Overdrive5_FanSpeed_Set(info[i].iAdapterIndex, 0, &FanSpeedValue) != ADL_OK) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "Cannot set fan speed!\n"); | |
return 1; | |
} | |
} | |
info[i].nPrevTemp = (info[i].nPrevTemp + 1) % 60; // advance the round-robin head ptr.. | |
} | |
//print status line | |
for(i = 0; i < ninfos; i++) { | |
if(i) | |
fprintf(stdout, "|"); | |
if(info[i].iSlaveIndex != -1) { | |
fprintf(stdout, "%i:%2i.%01i/%2i.%01i°C%c%2i", | |
i, | |
info[i].iMasterTemp / 1000, (info[i].iMasterTemp % 1000) / 100, | |
info[i].iSlaveTemp / 1000, (info[i].iSlaveTemp % 1000) / 100, | |
info[i].velocity, | |
info[i].iFanSpeed); | |
} else { | |
fprintf(stdout, "%i:%3i.%01i°C:%c%2i%%", | |
i, | |
info[i].iMasterTemp / 1000, (info[i].iMasterTemp % 1000) / 100, | |
info[i].velocity, | |
info[i].iFanSpeed); | |
} | |
} | |
fprintf(stdout, " \r"); | |
fflush(stdout); | |
if (logbuf) { | |
t=time(); | |
f=open(logfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); | |
if (!f) { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "ERROR: Unable to open logfile %s.\n", logfile); | |
} else { | |
if ((l=lseek(f, 0, SEEK_END)) >= 0) { // We'll be appending.. | |
for (i=0;i<ninfos;i++) { | |
snprintf(logbuf, LOGBUFSIZE-1, "%ld:%d:%.1f:%d:%d:%d:%d\n", | |
t, | |
info[i].iAdapterIndex, (float)info[i].iMasterTemp/1000.0, | |
info[i].iRealFanSpeed, | |
info[i].iEngineClock/100, info[i].iMemoryClock/100, | |
info[i].iActivityPercent); | |
write(f, logbuf, strlen(logbuf)); // who cares if it works. | |
if (info[i].iSlaveIndex != -1) { | |
snprintf(logbuf, LOGBUFSIZE-1, "%ld:%d:%.1f:%d:%d:%d:%d\n", | |
t, | |
info[i].iSlaveIndex, (float)info[i].iSlaveTemp/1000.0, | |
info[i].iRealFanSpeed, | |
info[i].iSlaveEngineClock/100, | |
info[i].iSlaveMemoryClock/100, | |
info[i].iSlaveActivityPercent); | |
write(f,logbuf,strlen(logbuf)); | |
} | |
} | |
} else { | |
if (DEBUG_ERROR) | |
fprintf(stderr, "ERROR: Unable to seek to end of logfile.\n"); | |
} | |
fsync(f); | |
close(f); | |
} | |
} | |
sleep(sleepytime); | |
} | |
printf("done\n"); | |
ADL_Main_Control_Destroy(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment