From 7266e4131af7e61f0e4b3af69d4a7c2cbab4df71 Mon Sep 17 00:00:00 2001 From: Scott Wilde Date: Sun, 9 May 2021 13:50:38 -0500 Subject: [PATCH] Initial commit for KrakenX fan controller Commits squashed and amended for code style by Adam Honse --- .../FanController_NZXTKraken.cpp | 71 +++++++++ .../FanController_NZXTKraken.h | 23 +++ .../NZXTKrakenController.cpp | 135 ++++++++++++++++++ .../NZXTKrakenController.h | 32 ++++- .../NZXTKrakenControllerDetect.cpp | 12 ++ FanController/FanController.h | 3 +- 6 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 Controllers/NZXTKrakenController/FanController_NZXTKraken.cpp create mode 100644 Controllers/NZXTKrakenController/FanController_NZXTKraken.h diff --git a/Controllers/NZXTKrakenController/FanController_NZXTKraken.cpp b/Controllers/NZXTKrakenController/FanController_NZXTKraken.cpp new file mode 100644 index 000000000..d16739085 --- /dev/null +++ b/Controllers/NZXTKrakenController/FanController_NZXTKraken.cpp @@ -0,0 +1,71 @@ +/*-----------------------------------------*\ +| FanController_NZXTKraken.cpp | +| | +| Generic Fan Interface for NZXT Kraken | +| | +| swilde 5/2021 | +\*-----------------------------------------*/ + +#include "FanController_NZXTKraken.h" + +FanController_NZXTKraken::FanController_NZXTKraken(NZXTKrakenController* kraken_ptr) +{ + kraken = kraken_ptr; + + name = "NZXT Kraken X2"; + description = "NZXT Kraken X42/X52/X62/X72"; + version = kraken->GetFirmwareVersion(); + location = kraken->GetLocation(); + serial = kraken->GetSerialString(); + + kraken->UpdateStatus(); + + fan new_fan; + + /*---------------------------------------------------------*\ + | Add fan | + | X52 has a max fan RPM of 200, the X42 and X62 max is 1800 | + \*---------------------------------------------------------*/ + new_fan.name = "NZXT Kraken Fan"; + new_fan.speed_min = 25; + new_fan.speed_max = 100; + new_fan.speed_cmd = 100 * kraken->fan_speed / 2000; + new_fan.prev_speed_cmd = 0; + new_fan.rpm_rdg = kraken->fan_speed; + fans.push_back(new_fan); + + /*---------------------------------------------------------*\ + | Add pump | + \*---------------------------------------------------------*/ + new_fan.name = "NZXT Kraken Pump"; + new_fan.speed_min = 50; + new_fan.speed_max = 100; + new_fan.speed_cmd = 100 * kraken->pump_speed / 2800; + new_fan.prev_speed_cmd = 0; + new_fan.rpm_rdg = kraken->pump_speed; + fans.push_back(new_fan); + + UpdateControl(); +} + +void FanController_NZXTKraken::UpdateControl() +{ + if(fans[0].speed_cmd != fans[0].prev_speed_cmd) + { + kraken->SetSpeed(NZXT_KRAKEN_CHANNEL_FAN, fans[0].speed_cmd); + fans[0].prev_speed_cmd = fans[0].speed_cmd; + } + if(fans[1].speed_cmd != fans[1].prev_speed_cmd) + { + kraken->SetSpeed(NZXT_KRAKEN_CHANNEL_PUMP, fans[1].speed_cmd); + fans[1].prev_speed_cmd = fans[1].speed_cmd; + } +} + +void FanController_NZXTKraken::UpdateReading() +{ + kraken->UpdateStatus(); + + fans[0].rpm_rdg = kraken->fan_speed; + fans[1].rpm_rdg = kraken->pump_speed; +} diff --git a/Controllers/NZXTKrakenController/FanController_NZXTKraken.h b/Controllers/NZXTKrakenController/FanController_NZXTKraken.h new file mode 100644 index 000000000..de7537af6 --- /dev/null +++ b/Controllers/NZXTKrakenController/FanController_NZXTKraken.h @@ -0,0 +1,23 @@ +/*-----------------------------------------*\ +| FanController_NZXTKraken.h | +| | +| Generic Fan Interface for NZXT Kraken | +| | +| swilde 5/2021 | +\*-----------------------------------------*/ + +#pragma once +#include "FanController.h" +#include "NZXTKrakenController.h" + +class FanController_NZXTKraken : public FanController +{ +public: + FanController_NZXTKraken(NZXTKrakenController* kraken_ptr); + + void UpdateControl(); + void UpdateReading(); + +private: + NZXTKrakenController* kraken; +}; diff --git a/Controllers/NZXTKrakenController/NZXTKrakenController.cpp b/Controllers/NZXTKrakenController/NZXTKrakenController.cpp index 591094a01..388731c9a 100644 --- a/Controllers/NZXTKrakenController/NZXTKrakenController.cpp +++ b/Controllers/NZXTKrakenController/NZXTKrakenController.cpp @@ -41,6 +41,9 @@ NZXTKrakenController::NZXTKrakenController(hid_device* dev_handle, const char* p | Get the firmware version | \*-----------------------------------------------------*/ UpdateStatus(); + + int major_firmware_version = std::stoi(firmware_version.substr(0, firmware_version.find("."))); + supports_cooling_profiles = major_firmware_version >= 3; } NZXTKrakenController::~NZXTKrakenController() @@ -196,3 +199,135 @@ void NZXTKrakenController::SendEffect \*-----------------------------------------------------*/ hid_write(dev, usb_buf, 64); } + +void NZXTKrakenController::SetSpeed(unsigned char channel, unsigned int speed_cmd) +{ + unsigned char duty; + + /*-----------------------------------------------------*\ + | Verify channel | + \*-----------------------------------------------------*/ + if(channel == NZXT_KRAKEN_CHANNEL_FAN) + { + duty = std::max((unsigned char) 25, std::min((unsigned char) 100, (unsigned char) speed_cmd)); + } + else if(channel == NZXT_KRAKEN_CHANNEL_PUMP) + { + duty = std::max((unsigned char) 50, std::min((unsigned char) 100, (unsigned char) speed_cmd)); + } + else + { + return; + } + + /*-----------------------------------------------------*\ + | Write speed | + \*-----------------------------------------------------*/ + if(supports_cooling_profiles) + { + SetFixedSpeedProfile(channel, duty); + } + else + { + SetInstantaneousSpeed(channel, duty); + } +} + +void NZXTKrakenController::SetFixedSpeedProfile(unsigned char channel, unsigned char duty) +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set to fan write | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x02; + usb_buf[0x01] = 0x4d; + + usb_buf[0x02] = channel; + + /*-----------------------------------------------------*\ + | Generate steps | + \*-----------------------------------------------------*/ + unsigned char temps[36]; + for(int i = 0; i < 30; i++) + { + temps[i] = 20 + i; + } + for(int i = 0; i <= 5; i++) + { + temps[30 + i] = 50 + 2*i; + } + + /*-----------------------------------------------------*\ + | Write temp speed pairs | + \*-----------------------------------------------------*/ + unsigned char curr_duty = duty; + for(int i = 0; i < 36; i++) + { + if(temps[i] == 60) + { + curr_duty = 100; + } + + /*-----------------------------------------------------*\ + | Set channel and index | + \*-----------------------------------------------------*/ + usb_buf[0x02] = channel + i; + + /*-----------------------------------------------------*\ + | Set temp | + \*-----------------------------------------------------*/ + usb_buf[0x03] = temps[i]; + + /*-----------------------------------------------------*\ + | Set duty | + \*-----------------------------------------------------*/ + usb_buf[0x04] = curr_duty; + + /*-----------------------------------------------------*\ + | Write speed | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + } +} + +void NZXTKrakenController::SetInstantaneousSpeed(unsigned char channel, unsigned char duty) +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set to fan write | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x02; + usb_buf[0x01] = 0x4d; + + /*-----------------------------------------------------*\ + | Set channel | + \*-----------------------------------------------------*/ + usb_buf[0x02] = channel; + + /*-----------------------------------------------------*\ + | Set temp (0 for instantaneous speed) | + \*-----------------------------------------------------*/ + usb_buf[0x03] = 0; + + /*-----------------------------------------------------*\ + | Set duty | + \*-----------------------------------------------------*/ + usb_buf[0x04] = duty; + + /*-----------------------------------------------------*\ + | Write speed | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); +} diff --git a/Controllers/NZXTKrakenController/NZXTKrakenController.h b/Controllers/NZXTKrakenController/NZXTKrakenController.h index 8387a9892..b35cd6559 100644 --- a/Controllers/NZXTKrakenController/NZXTKrakenController.h +++ b/Controllers/NZXTKrakenController/NZXTKrakenController.h @@ -48,6 +48,12 @@ enum NZXT_KRAKEN_SPEED_FASTEST = 0x04, /* Fastest speed */ }; +enum +{ + NZXT_KRAKEN_CHANNEL_FAN = 0x80, /* Fan channel */ + NZXT_KRAKEN_CHANNEL_PUMP = 0xc0, /* Pump channel */ +}; + class NZXTKrakenController { public: @@ -58,6 +64,12 @@ public: std::string GetLocation(); std::string GetSerialString(); + void SetSpeed + ( + unsigned char channel, + unsigned int speed_cmd + ); + void UpdateEffect ( NZXTKrakenChannel_t channel, @@ -68,9 +80,12 @@ public: std::vector colors ); -private: void UpdateStatus(); + unsigned int fan_speed; + unsigned int pump_speed; + +private: void SendEffect ( unsigned char channel, @@ -83,12 +98,23 @@ private: int size = 0 ); + void SetFixedSpeedProfile + ( + unsigned char channel, + unsigned char duty + ); + void SetInstantaneousSpeed + ( + unsigned char channel, + unsigned char duty + ); + hid_device* dev; // -- status std::string firmware_version; double liquid_temperature; std::string location; - unsigned int fan_speed; - unsigned int pump_speed; + + bool supports_cooling_profiles; }; diff --git a/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp b/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp index f91edbc59..53d48d805 100644 --- a/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp +++ b/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp @@ -13,6 +13,7 @@ #include #include "Detector.h" #include "NZXTKrakenController.h" +#include "FanController_NZXTKraken.h" #include "RGBController.h" #include "RGBController_NZXTKraken.h" @@ -37,6 +38,17 @@ void DetectNZXTKrakenControllers(hid_device_info* info, const std::string& name) RGBController_NZXTKraken* rgb_controller = new RGBController_NZXTKraken(controller); rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); + + if(info->product_id == NZXT_KRAKEN_X2_PID) + { + /*---------------------------------------------*\ + | Kraken M22 doesn't have liquid temp sensor or | + | ability to report or set fan or pump speeds | + \*---------------------------------------------*/ + FanController_NZXTKraken* fan_controller = new FanController_NZXTKraken(controller); + fan_controller->name = name; + ResourceManager::get()->RegisterFanController(fan_controller); + } } } /* DetectNZXTKrakenControllers() */ diff --git a/FanController/FanController.h b/FanController/FanController.h index 19b5633cc..a6d70fee5 100644 --- a/FanController/FanController.h +++ b/FanController/FanController.h @@ -22,6 +22,7 @@ typedef struct \*--------------------------------------------------------------*/ std::string name; /* Fan name */ unsigned int speed_cmd; /* Speed command */ + unsigned int prev_speed_cmd; /* Last speed command */ unsigned int speed_min; /* Minimum speed command */ unsigned int speed_max; /* Maximum speed command */ unsigned int rpm_rdg; /* RPM reading */ @@ -48,4 +49,4 @@ public: \*---------------------------------------------------------*/ virtual void UpdateControl() = 0; virtual void UpdateReading() = 0; -}; \ No newline at end of file +};