From fe240190b34eb326587191a538db88fbbe0e058f Mon Sep 17 00:00:00 2001 From: Fabian R Date: Sat, 30 Nov 2024 10:08:37 +0000 Subject: [PATCH] Major fixes and improvements for CoolerMaster ARGB Gen2 A1 V2 --- .../CMARGBGen2A1Controller.cpp | 233 +++++++++--------- .../CMARGBGen2A1Controller.h | 29 ++- .../RGBController_CMARGBGen2A1Controller.cpp | 63 ++++- .../RGBController_CMARGBGen2A1Controller.h | 2 + 4 files changed, 198 insertions(+), 129 deletions(-) diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp index 5ea68f9c..65f2fdf5 100644 --- a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp @@ -4,6 +4,7 @@ | Driver for Cooler Master ARGB Gen 2 A1 controller | | | | Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | @@ -59,26 +60,45 @@ void CMARGBGen2A1controller::SaveToFlash() hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); } void CMARGBGen2A1controller::SetupDirectMode() { + ResetDevice(); + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; /*---------------------------------------------*\ | Swith to direct mode | \*---------------------------------------------*/ - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_LIGHTNING_CONTROL; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - usb_buf[4] = 0x01; // channel??? + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_HW_MODE_SETUP; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[4] = CM_ARGB_GEN2_A1_CHANNEL_ALL; // CHANNEL + usb_buf[5] = CM_ARGB_GEN2_A1_SUBCHANNEL_ALL; // SUBCHANNEL + usb_buf[6] = CM_ARGB_GEN2_A1_CUSTOM_MODE; + usb_buf[7] = CM_ARGB_GEN2_A1_SPEED_HALF; + usb_buf[8] = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; + usb_buf[9] = 0xFF; // R + usb_buf[10] = 0xFF; // G + usb_buf[11] = 0xFF; // B hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_SHORT)); + + std::vector colorOffChain; + colorOffChain.push_back(0); + for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) + { + SendChannelColors(channel, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL, colorOffChain); + } + + for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) + { + SetCustomSequence(channel); + } software_mode_activated = true; } @@ -144,10 +164,19 @@ void CMARGBGen2A1controller::SetupZoneSize(unsigned int zone_id, unsigned int si hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); + + /*---------------------------------------------*\ + | Refresh direct mode to cycle the strips | + | with the new length | + \*---------------------------------------------*/ + if(software_mode_activated) + { + SetupDirectMode(); + } } -void CMARGBGen2A1controller::SendDirectChannel(unsigned int zone_id, std::vector colors) +void CMARGBGen2A1controller::SendChannelColors(unsigned int zone_id, unsigned int subchannel_id, std::vector colors) { /*---------------------------------------------*\ | Create the color data array | @@ -160,53 +189,53 @@ void CMARGBGen2A1controller::SendDirectChannel(unsigned int zone_id, std::vector unsigned int offset; - unsigned char packet_start[CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL] = + /*----------------------------------------------------*\ + | Break-up color data in packet/s | + | Intentionally clearing first packet only | + | Leaving garbage on subsequent packets | + | Original software appears to not clear them anyways. | + \*----------------------------------------------------*/ + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + for(unsigned int p = 0; p < CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL && it != color_data.end(); p++) { - 0x00, 0x01, 0x82 - }; + offset = 1; - /*---------------------------------------------*\ - | Send 3 packets for the zone | - \*---------------------------------------------*/ - for(unsigned int p = 0; p < CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL; p++) - { - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + usb_buf[offset++] = p; + usb_buf[offset++] = CM_ARGB_GEN2_A1_SET_RGB_VALUES; + usb_buf[offset++] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[offset++] = 1 << zone_id; + usb_buf[offset++] = 1 << subchannel_id; - usb_buf[1] = packet_start[p]; - usb_buf[2] = 0x09; - - if(p == 0) + while(it != color_data.end() && offset < CM_ARGB_GEN2_A1_PACKET_LENGTH) { - usb_buf[3] = 1 << zone_id; - usb_buf[5] = 0x3C; - - offset = 6; - } - else - { - offset = 3; - } - - while(offset < CM_ARGB_GEN2_A1_PACKET_LENGTH && it != color_data.end()) - { - usb_buf[offset] = *it; - offset++; + usb_buf[offset++] = *it; it++; } + if(p >= CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL - 1 || it == color_data.end()) + { + /*--------------------------*\ + | Rewrite as end packet | + \*--------------------------*/ + usb_buf[1] = p + 0x80; + } + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - /*---------------------------------------------*\ - | This device needs some delay before we send | - | any other packet | - \*---------------------------------------------*/ - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + /*-----------------------------------------------*\ + | This device needs some delay before we send | + | any other packet :( | + | This time is critical since the device is | + | still latching its input buffer. | + | Reducing this may start to introduce artifacts | + \*-----------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_MEDIUM)); } /*---------------------------------------------*\ | Next channel needs some delay as well | \*---------------------------------------------*/ - std::this_thread::sleep_for(std::chrono::milliseconds(2)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_SHORT)); } void CMARGBGen2A1controller::SetMode(unsigned int mode_value, unsigned char speed, unsigned char brightness, RGBColor color, bool random) @@ -228,7 +257,7 @@ void CMARGBGen2A1controller::SetMode(unsigned int mode_value, unsigned char spee software_mode_activated = false; - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); } /*---------------------------------------------*\ @@ -240,16 +269,20 @@ void CMARGBGen2A1controller::SetMode(unsigned int mode_value, unsigned char spee usb_buf[2] = CM_ARGB_GEN2_A1_HW_MODE_SETUP; usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - usb_buf[4] = 0xFF; - usb_buf[5] = 0xFF; + usb_buf[4] = CM_ARGB_GEN2_A1_CHANNEL_ALL; + usb_buf[5] = CM_ARGB_GEN2_A1_SUBCHANNEL_ALL; usb_buf[6] = mode_value; - bool is_custom_mode = mode_value == CM_ARGB_GEN2_A1_CUSTOM_MODE; + bool is_custom_mode = (mode_value == CM_ARGB_GEN2_A1_CUSTOM_MODE); if(is_custom_mode) { - usb_buf[8] = 0xFF; + usb_buf[7] = CM_ARGB_GEN2_A1_SPEED_MAX; + usb_buf[8] = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; + usb_buf[9] = 0xFF; // R + usb_buf[10] = 0xFF; // G + usb_buf[11] = 0xFF; // B } else { @@ -261,10 +294,9 @@ void CMARGBGen2A1controller::SetMode(unsigned int mode_value, unsigned char spee usb_buf[12] = random; } - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); if(is_custom_mode) { @@ -289,83 +321,58 @@ std::vector CMARGBGen2A1controller::CreateColorData(std::vector colors) -{ - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - /*---------------------------------------------*\ - | Create the color data array | - \*---------------------------------------------*/ - std::vector color_data = CreateColorData(colors); - - std::vector::iterator it = color_data.begin(); - - unsigned char packet_start[5] = - { - CM_ARGB_GEN2_A1_COMMAND, 0x00, 0x01, 0x02, 0x83 - }; - - /*---------------------------------------------*\ - | Send the 5 packets of colors | - \*---------------------------------------------*/ - for(unsigned int p = 0; p < 5; p++) - { - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = packet_start[p]; - - /*----------------------------------------------*\ - | This part isnt well understood | - | 1st packet starts with CM_ARGB_GEN2_A1_COMMAND | - | Looks like it is a read command | - \*----------------------------------------------*/ - usb_buf[2] = p == 0 ? 0x06 : 0x08; // 0x08 custom data, 0x06 sizes? - usb_buf[3] = p == 0 ? 0x01 : 0x02; // read/write has no meaning here - - usb_buf[4] = 1 << zone_id; - - unsigned int offset = 6; - - while(p > 0 && offset < CM_ARGB_GEN2_A1_PACKET_LENGTH && it != color_data.end()) - { - usb_buf[offset] = *it; - offset++; - it++; - } - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } - -} - void CMARGBGen2A1controller::SetCustomSequence(unsigned int zone_id) { unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - const unsigned char static_seq = 0x01; - /*---------------------------------------------*\ - | Set the mode sequence to full static | - | (01 for static) | + | Set custom speed for sequence mode | \*---------------------------------------------*/ memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_CUSTOM_SPEED; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[4] = 1 << zone_id; // CHANNEL + usb_buf[5] = 0x32; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_SHORT)); + + SetPipelineStaticSequence(zone_id); +} + +void CMARGBGen2A1controller::SetPipelineStaticSequence(unsigned int zone_id) +{ + /*------------------------------------------------*\ + | Set the mode sequence to full static | + | All steps on the effect pipeline to 0x01 STATIC | + \*------------------------------------------------*/ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + memset(usb_buf, CM_ARGB_GEN2_A1_STATIC_MODE, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[0] = 0x00; usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; usb_buf[2] = CM_ARGB_GEN2_A1_CUSTOM_SEQUENCES; usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; usb_buf[4] = 1 << zone_id; - usb_buf[5] = static_seq; - usb_buf[6] = static_seq; - usb_buf[7] = static_seq; - usb_buf[8] = static_seq; - usb_buf[9] = static_seq; - usb_buf[10] = static_seq; + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); +} + +void CMARGBGen2A1controller::ResetDevice() +{ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_RESET; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); } diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h index 365d4e56..d7d5feba 100644 --- a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h @@ -4,6 +4,7 @@ | Driver for Cooler Master ARGB Gen 2 A1 controller | | | | Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | @@ -16,9 +17,13 @@ #include "RGBController.h" #define CM_ARGB_GEN2_A1_PACKET_LENGTH 65 -#define CM_ARGB_GEN2_A1_CHANNEL_MAX_SIZE 48 +#define CM_ARGB_GEN2_A1_CHANNEL_MAX_SIZE 72 #define CM_ARGB_GEN2_A1_CHANNEL_COUNT 3 -#define CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL 3 +#define CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL 2 + +#define CM_ARGB_GEN2_A1_SLEEP_SHORT 5 +#define CM_ARGB_GEN2_A1_SLEEP_MEDIUM 45 +#define CM_ARGB_GEN2_A1_SLEEP_LONG 70 enum { @@ -41,12 +46,15 @@ enum CM_ARGB_GEN2_A1_BRIGHTNESS_MAX = 0xFF, CM_ARGB_GEN2_A1_BRIGHTNESS_MIN = 0x00, CM_ARGB_GEN2_A1_SPEED_MAX = 0x04, + CM_ARGB_GEN2_A1_SPEED_HALF = 0x02, CM_ARGB_GEN2_A1_SPEED_MIN = 0x00, }; enum { CM_ARGB_GEN2_A1_COMMAND = 0x80, + CM_ARGB_GEN2_A1_COMMAND_EXTRA_1 = 0x81, + CM_ARGB_GEN2_A1_COMMAND_EXTRA_2 = 0x82, CM_ARGB_GEN2_A1_READ = 0x01, CM_ARGB_GEN2_A1_WRITE = 0x02, CM_ARGB_GEN2_A1_RESPONSE = 0x03 @@ -55,13 +63,24 @@ enum enum { CM_ARGB_GEN2_A1_SIZES = 0x06, + CM_ARGB_GEN2_A1_SET_RGB_VALUES = 0x08, CM_ARGB_GEN2_A1_FLASH = 0x0B, CM_ARGB_GEN2_A1_IDENTIFY = 0x0A, CM_ARGB_GEN2_A1_LIGHTNING_CONTROL = 0x01, CM_ARGB_GEN2_A1_HW_MODE_SETUP = 0x03, CM_ARGB_GEN2_A1_CUSTOM_SEQUENCES = 0x10, - CM_ARGB_GEN2_A1_CUSTOM_SPEED = 0x11 + CM_ARGB_GEN2_A1_CUSTOM_SPEED = 0x11, + CM_ARGB_GEN2_A1_RESET = 0xC0, + CM_ARGB_GEN2_A1_APPLY_CHANGES = 0xB0 +}; +enum +{ + CM_ARGB_GEN2_A1_CHANNEL_A = 0x01, + CM_ARGB_GEN2_A1_CHANNEL_B = 0x02, + CM_ARGB_GEN2_A1_CHANNEL_C = 0x04, + CM_ARGB_GEN2_A1_CHANNEL_ALL = 0xFF, + CM_ARGB_GEN2_A1_SUBCHANNEL_ALL = 0xFF }; class CMARGBGen2A1controller @@ -73,7 +92,7 @@ public: std::string GetSerialString(); std::string GetDeviceLocation(); - void SendDirectChannel(unsigned int zone_id, std::vector colors); + void SendChannelColors(unsigned int zone_id, unsigned int subchannel_id, std::vector colors); void SetupZoneSize(unsigned int zone_id, unsigned int size); void SetupDirectMode(); void SetMode(unsigned int mode_value, unsigned char speed, unsigned char brightness, RGBColor color, bool random); @@ -86,5 +105,7 @@ private: hid_device* dev; void SetCustomSequence(unsigned int zone_id); + void SetPipelineStaticSequence(unsigned int zone_id); std::vector CreateColorData(std::vector colors); + void ResetDevice(); }; diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp index 91c1f930..d0540662 100644 --- a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp @@ -4,6 +4,7 @@ | Driver for Cooler Master ARGB Gen 2 A1 controller | | | | Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | @@ -21,9 +22,14 @@ @direct :white_check_mark: @effects :white_check_mark: @detectors DetectCoolerMasterARGBGen2A1 - @comment This device does not have Gen 2 support in OpenRGB yet. + @comment OpenRGB partially supports Gen 2 protocol for this device. - Gen2 has auto-resize feature and parallel to serial magical stuff.< + Gen2 has auto-resize feature and parallel to serial magical stuff, + Strip size is auto detected by the controller but not reported + back to OpenRGB. Configure zones and segments for each channel + to allow individual addressing. + Take note that this controller is extremely slow, using fast + update rates may introduce color artifacts.< \*-------------------------------------------------------------------*/ RGBController_CMARGBGen2A1Controller::RGBController_CMARGBGen2A1Controller(CMARGBGen2A1controller* controller_ptr) @@ -217,7 +223,6 @@ void RGBController_CMARGBGen2A1Controller::ResizeZone(int zone, int new_size) { zones[zone].leds_count = new_size; - // todo: refactor with above code unsigned int total_leds = 0; for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) @@ -241,7 +246,18 @@ void RGBController_CMARGBGen2A1Controller::DeviceUpdateLEDs() { for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel ++) { - UpdateZoneLEDs(channel); + if (zones[channel].segments.size() > 0) + { + unsigned int i = 0; + for(std::vector::iterator it = zones[channel].segments.begin(); it != zones[channel].segments.end(); it++) + { + UpdateSegmentLEDs(channel, i++); + } + } + else + { + UpdateSegmentLEDs(channel, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL); + } } } @@ -254,17 +270,40 @@ void RGBController_CMARGBGen2A1Controller::UpdateZoneLEDs(int zone) std::vector zone_colors(colors.begin() + start , colors.begin() + end); - if(modes[active_mode].value == CM_ARGB_GEN2_A1_DIRECT_MODE) - { - controller->SendDirectChannel(zone, zone_colors); - } - else - { - controller->SetCustomColors(zone, zone_colors); - } + controller->SendChannelColors(zone, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL, zone_colors); } } +void RGBController_CMARGBGen2A1Controller::UpdateSegmentLEDs(int zone, int subchannel) +{ + if(zones[zone].leds_count <= 0) + { + return; + } + + unsigned int start = zones[zone].start_idx; + unsigned int end = start + zones[zone].leds_count; + bool use_direct_mode = modes[active_mode].value == CM_ARGB_GEN2_A1_DIRECT_MODE || modes[active_mode].value == CM_ARGB_GEN2_A1_CUSTOM_MODE; + + std::vector color_vector(colors.begin() + start, colors.begin() + start + end); + + if(use_direct_mode) + { + if(zones[zone].segments.size() > 0) + { + start += zones[zone].segments[subchannel].start_idx; + end += zones[zone].segments[subchannel].start_idx + zones[zone].segments[subchannel].leds_count; + + color_vector = std::vector(colors.begin() + start , colors.begin() + end); + } + + controller->SendChannelColors(zone, subchannel, color_vector); + return; + } + + controller->SendChannelColors(zone, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL, color_vector); +} + void RGBController_CMARGBGen2A1Controller::UpdateSingleLED(int /*led*/) { DeviceUpdateLEDs(); diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h index b214da4c..269ee6c3 100644 --- a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h @@ -4,6 +4,7 @@ | Driver for Cooler Master ARGB Gen 2 A1 controller | | | | Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | @@ -25,6 +26,7 @@ public: void ResizeZone(int zone, int new_size); void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); + void UpdateSegmentLEDs(int zone, int subchannel); void UpdateSingleLED(int led); void SetCustomMode(); void DeviceUpdateMode();