diff --git a/include/aio.h b/include/aio.h index 2065adb..517c871 100644 --- a/include/aio.h +++ b/include/aio.h @@ -55,7 +55,7 @@ struct aio_t { libusb_device_handle* handle; enum aio_pump_mode_t pump_mode; float water_temp; - uint16_t pump_counter; + int16_t pump_counter; uint16_t pump_speed; uint16_t fan_speed[2]; }; diff --git a/src/aio.c b/src/aio.c index c3fa81a..c51906b 100644 --- a/src/aio.c +++ b/src/aio.c @@ -11,21 +11,12 @@ static constexpr uint8_t max_curve_points = 7; static uint8_t req[buf_size], resp[buf_size]; -static struct aio_params_t params = { - .fans = { - .setpoint = 43.5f, - .min_duty = 20, - .max_duty = 80, - .fan_stop = false, - .ctrl = { - .Ki = 0.1f, - .Kd = 10.0f - }, - }}; - -static inline float clamp(const float value, const float min, const float max) { - return fmaxf(fminf(value, max), min); -} +static const struct curve_point_t fan_curve[] = { + { .temp = 37, .duty = 15 }, + { .temp = 40, .duty = 40 }, + { .temp = 46, .duty = 60 }, + { .temp = 50, .duty = 100 } +}; static void aio_usb_claim(libusb_device_handle *dev) { int ret = libusb_claim_interface(dev, 0); @@ -43,7 +34,7 @@ static void aio_usb_release(libusb_device_handle *dev) { } static int aio_post(libusb_device_handle *dev, const int req_len, const int resp_len) { - // applog(LOG_DBG, "writing to aio, %02x", req[0]); + applog(LOG_DBG, "writing to aio reg 0x%02x", req[0]); int ret = 0; ret += libusb_bulk_transfer(dev, 0x01, req, req_len, nullptr, usb_timeout); ret += libusb_bulk_transfer(dev, 0x81, resp, resp_len, nullptr, usb_timeout); @@ -51,19 +42,9 @@ static int aio_post(libusb_device_handle *dev, const int req_len, const int resp } static float aio_get_water_temp(libusb_device_handle *dev) { - static float last_read = 36.6f; // sane init value so it doenst ramp the fan up req[0] = 0xa9; - if (aio_post(dev, 1, 6) != 0) - return last_read; - const float temp = (float)resp[3] + (float)resp[4] / 10.0f; - - if (temp > 10.0f && temp < 65.0f) { - constexpr float max_change = 0.5f; // 0.5C change per refresh cycle - const float delta = temp - last_read; - last_read += fmaxf(fminf(delta, max_change), -max_change); - } - - return last_read; + aio_post(dev, 1, 6); + return (float)resp[3] + (float)resp[4] / 10.0f; } static uint16_t aio_get_pump_speed(libusb_device_handle *dev) { @@ -91,6 +72,8 @@ static void aio_get_fan_speed(libusb_device_handle *dev, uint16_t *speeds) { } static void aio_set_fan_duty(libusb_device_handle *dev, const uint8_t *duty) { + if (duty == nullptr) + return; static uint8_t last_duty = 255; if (duty[0] == last_duty) return; @@ -98,8 +81,6 @@ static void aio_set_fan_duty(libusb_device_handle *dev, const uint8_t *duty) { for (uint8_t i = 0; i < 2; i++) { req[1] = i; req[2] = MIN(MAX(duty[i], 0), 100); - if (params.fans.fan_stop && req[2] <= params.fans.min_duty) - req[2] = 0; if (aio_post(dev, sizeof(req), buf_size) == 0) last_duty = req[2]; } @@ -199,7 +180,9 @@ void aio_detect(struct aio_t *aio) { libusb_detach_kernel_driver(aio->handle, 0); aio_usb_claim(aio->handle); - applog(LOG_INF, "found Corsair AIO device at %04x:%04x, fw ver: %s. Set point is %.1fC, fan stop %s", AIO_USB_VID, AIO_USB_PID, aio_get_firmware_version(aio->handle, (char[16]){0}), (double)params.fans.setpoint, params.fans.fan_stop ? "ENABLED" : "DISABLED"); + applog(LOG_INF, "found Corsair AIO device at %04x:%04x, fw ver: %s", AIO_USB_VID, AIO_USB_PID, aio_get_firmware_version(aio->handle, (char[16]){0})); + aio_set_fan_duty(aio->handle, nullptr); // so it doenst complain the func is unused + aio_set_fan_curve(aio->handle, fan_curve, sizeof(fan_curve) / sizeof(fan_curve[0])); aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_QUIET); // needed for init ig? aio_set_color(aio->handle, AIO_COLOR_FIXED, 0, nullptr, 0); // so it doenst complain the func is unused aio_usb_release(aio->handle); @@ -216,46 +199,57 @@ void aio_update(struct aio_t *aio) { aio->pump_mode = aio_get_pump_mode(aio->handle); aio_get_fan_speed(aio->handle, aio->fan_speed); - /* fan logic */ - static float fan_duty = 0.0f; - static float prev_temp = 36.0f; // 20 avoids huge jump of slope at boot - const float error = aio->water_temp - params.fans.setpoint; - const float slope = aio->water_temp - prev_temp; - prev_temp = aio->water_temp; + const uint16_t avg_rpm = (uint16_t)((aio->fan_speed[0] + aio->fan_speed[1]) / 2); + switch (aio->pump_mode) { + case AIO_PUMP_MODE_QUIET: + if (avg_rpm >= 500) + aio->pump_counter++; + else + aio->pump_counter = 0; - fan_duty += error * params.fans.ctrl.Ki + slope * params.fans.ctrl.Kd; - fan_duty = clamp(fan_duty, params.fans.min_duty, params.fans.max_duty); + if (aio->pump_counter >= 300) { + aio->pump_counter = 0; + aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED); + } + break; + case AIO_PUMP_MODE_BALANCED: + if (avg_rpm >= 700) + aio->pump_counter++; + else if (avg_rpm <= 400) + aio->pump_counter--; + else + aio->pump_counter = 0; - // applog(LOG_DBG, "Fan duty %.3f, error %.4f, slope %.4f", (double)fan_duty, (double)error * (double)params.fans.ctrl.Ki, (double)slope * (double)params.fans.ctrl.Kd); - aio_set_fan_duty(aio->handle, (uint8_t[]){(uint8_t)fan_duty, (uint8_t)fan_duty}); // wew lad + if (aio->pump_counter >= 300) { + aio->pump_counter = 0; + aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_EXTREME); + } + if (aio->pump_counter <= -300) { + aio->pump_counter = 0; + aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_QUIET); + } + break; + case AIO_PUMP_MODE_EXTREME: + if (avg_rpm <= 500) + aio->pump_counter--; + else + aio->pump_counter = 0; - /* pump logic */ - if (fan_duty > (float)params.fans.max_duty * 0.75f && aio->pump_counter < 300) - aio->pump_counter++; - if (fan_duty < (float)params.fans.min_duty * 1.75f && aio->pump_counter > 0) - aio->pump_counter--; - - if (aio->pump_counter > 280) - aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_EXTREME); - if (aio->pump_counter > 60) - aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED); - if (aio->pump_counter == 0) - aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_QUIET); + if (aio->pump_counter <= -300) { + aio->pump_counter = 0; + aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED); + } + break; + case AIO_PUMP_MODE_UNKNOWN: + aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED); + break; + } aio_usb_release(aio->handle); } void aio_close(const struct aio_t *aio) { - const struct curve_point_t fan_curve[] = { - { .temp = 34, .duty = 20}, - { .temp = 35, .duty = 35 }, - { .temp = 39, .duty = 50 }, - { .temp = 46, .duty = 75 }, - { .temp = 55, .duty = 100} - }; - aio_set_pump_mode(aio->handle, AIO_PUMP_MODE_BALANCED); - aio_set_fan_curve(aio->handle, fan_curve, sizeof(fan_curve) / sizeof(fan_curve[0])); libusb_attach_kernel_driver(aio->handle, 0); // reattach so liquidctl still works libusb_close(aio->handle); libusb_exit(nullptr);