diff --git a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp index 694b5050..c0aedd79 100644 --- a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp +++ b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp @@ -9,52 +9,221 @@ #include "RGBController_ZalmanZSync.h" + RGBController_ZalmanZSync::RGBController_ZalmanZSync(ZalmanZSyncController* controller_ptr) { - controller = controller_ptr; - type = DEVICE_TYPE_LEDSTRIP; - name = "Zalman Z Sync Device"; - description = "Zalman Z Sync Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + controller = controller_ptr; + + name = "Zalman Z Sync Device"; + vendor = "Zalman"; + description = "Zalman Z Sync Device"; + type = DEVICE_TYPE_LEDSTRIP; + version = controller->GetFirmwareString(); + location = controller->GetLocationString(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; - Direct.value = 0; + Direct.value = 0xFFFF; Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = ZALMAN_Z_SYNC_MODE_RAINBOW_WAVE; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + RainbowWave.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + RainbowWave.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + RainbowWave.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + RainbowWave.direction = MODE_DIRECTION_RIGHT; + RainbowWave.color_mode = MODE_COLORS_NONE; + modes.push_back(RainbowWave); + + mode ColorShift; + ColorShift.name = "Color Shift"; + ColorShift.value = ZALMAN_Z_SYNC_MODE_COLOR_SHIFT; + ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + ColorShift.colors_min = 2; + ColorShift.colors_max = 2; + ColorShift.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + ColorShift.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + ColorShift.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorShift.colors.resize(2); + modes.push_back(ColorShift); + + mode ColorPulse; + ColorPulse.name = "Color Pulse"; + ColorPulse.value = ZALMAN_Z_SYNC_MODE_COLOR_PULSE; + ColorPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + ColorPulse.colors_min = 2; + ColorPulse.colors_max = 2; + ColorPulse.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + ColorPulse.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + ColorPulse.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + ColorPulse.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorPulse.colors.resize(2); + modes.push_back(ColorPulse); + + mode ColorWave; + ColorWave.name = "Color Wave"; + ColorWave.value = ZALMAN_Z_SYNC_MODE_COLOR_WAVE; + ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + ColorWave.colors_min = 2; + ColorWave.colors_max = 2; + ColorWave.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + ColorWave.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + ColorWave.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + ColorWave.direction = MODE_DIRECTION_RIGHT; + ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorWave.colors.resize(2); + modes.push_back(ColorWave); + + mode Static; + Static.name = "Static"; + Static.value = ZALMAN_Z_SYNC_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Temperature; + Temperature.name = "Temperature"; + Temperature.value = ZALMAN_Z_SYNC_MODE_TEMPERATURE; + Temperature.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Temperature.colors_min = 3; + Temperature.colors_max = 3; + Temperature.color_mode = MODE_COLORS_MODE_SPECIFIC; + Temperature.colors.resize(3); + modes.push_back(Temperature); + + mode Visor; + Visor.name = "Visor"; + Visor.value = ZALMAN_Z_SYNC_MODE_VISOR; + Visor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Visor.colors_min = 2; + Visor.colors_max = 2; + Visor.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Visor.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Visor.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Visor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Visor.colors.resize(2); + modes.push_back(Visor); + + mode Marquee; + Marquee.name = "Marquee"; + Marquee.value = ZALMAN_Z_SYNC_MODE_MARQUEE; + Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Marquee.colors_min = 1; + Marquee.colors_max = 1; + Marquee.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Marquee.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Marquee.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Marquee.direction = MODE_DIRECTION_RIGHT; + Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + Marquee.colors.resize(1); + modes.push_back(Marquee); + + mode Blink; + Blink.name = "Blink"; + Blink.value = ZALMAN_Z_SYNC_MODE_BLINK; + Blink.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Blink.colors_min = 2; + Blink.colors_max = 2; + Blink.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Blink.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Blink.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Blink.color_mode = MODE_COLORS_MODE_SPECIFIC; + Blink.colors.resize(2); + modes.push_back(Blink); + + mode Sequential; + Sequential.name = "Sequential"; + Sequential.value = ZALMAN_Z_SYNC_MODE_SEQUENTIAL; + Sequential.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Sequential.colors_min = 1; + Sequential.colors_max = 1; + Sequential.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Sequential.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Sequential.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Sequential.direction = MODE_DIRECTION_RIGHT; + Sequential.color_mode = MODE_COLORS_MODE_SPECIFIC; + Sequential.colors.resize(1); + modes.push_back(Sequential); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = ZALMAN_Z_SYNC_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED; + Rainbow.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Rainbow.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Rainbow.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Rainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(Rainbow); + SetupZones(); } -RGBController_ZalmanZSync::~RGBController_ZalmanZSync() -{ - -} - void RGBController_ZalmanZSync::SetupZones() { - for(unsigned int zone_idx = 0; zone_idx < 8; zone_idx++) + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) { - zone new_zone; + first_run = true; + } - new_zone.name = "Channel " + std::to_string(zone_idx + 1); - new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_min = 24; - new_zone.leds_max = 24; - new_zone.leds_count = 24; - new_zone.matrix_map = NULL; + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + zones.resize(ZALMAN_Z_SYNC_NUM_CHANNELS); - zones.push_back(new_zone); + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + for (unsigned int channel_idx = 0; channel_idx < ZALMAN_Z_SYNC_NUM_CHANNELS; channel_idx++) + { + char ch_idx_string[2]; + sprintf(ch_idx_string, "%d", channel_idx + 1); - for(unsigned int led_idx = 0; led_idx < 24; led_idx++) + zones[channel_idx].name = "Channel "; + zones[channel_idx].name.append(ch_idx_string); + zones[channel_idx].type = ZONE_TYPE_LINEAR; + + /*-------------------------------------------------*\ + | I did some experimenting and determined that the | + | maximum number of LEDs the Corsair Commander Pro | + | can support is 200. | + \*-------------------------------------------------*/ + zones[channel_idx].leds_min = 0; + zones[channel_idx].leds_max = 204; + + if(first_run) { - led new_led; + zones[channel_idx].leds_count = 0; + } - new_led.name = "LED " + std::to_string(led_idx + 1); + zones[channel_idx].matrix_map = NULL; + + for (unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) + { + char led_idx_string[4]; + sprintf(led_idx_string, "%d", led_ch_idx + 1); + + led new_led; + new_led.name = "LED "; + new_led.name.append(led_idx_string); leds.push_back(new_led); + leds_channel.push_back(channel_idx); } } @@ -63,33 +232,89 @@ void RGBController_ZalmanZSync::SetupZones() void RGBController_ZalmanZSync::ResizeZone(int zone, int new_size) { + if((size_t) zone >= zones.size()) + { + return; + } + if(((unsigned int)new_size >= zones[zone].leds_min) && ((unsigned int)new_size <= zones[zone].leds_max)) + { + zones[zone].leds_count = new_size; + + SetupZones(); + } } void RGBController_ZalmanZSync::DeviceUpdateLEDs() { - for(unsigned int zone_idx = 0; zone_idx < 8; zone_idx++) + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetLEDs(zone_idx, zones[zone_idx].colors); + controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } void RGBController_ZalmanZSync::UpdateZoneLEDs(int zone) { - controller->SetLEDs(zone, zones[zone].colors); + controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); } void RGBController_ZalmanZSync::UpdateSingleLED(int led) { - DeviceUpdateLEDs(); + unsigned int channel = leds_channel[led]; + + controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); } void RGBController_ZalmanZSync::SetCustomMode() { - + active_mode = 0; } void RGBController_ZalmanZSync::DeviceUpdateMode() { + if(modes[active_mode].value == 0xFFFF) + { + DeviceUpdateLEDs(); + } + else + { + for(int channel = 0; channel < ZALMAN_Z_SYNC_NUM_CHANNELS; channel++) + { + unsigned int direction = 0; + bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); -} \ No newline at end of file + if(modes[active_mode].direction == MODE_DIRECTION_RIGHT) + { + direction = 1; + } + + unsigned char mode_colors[9]; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + for(std::size_t i = 0; i < modes[active_mode].colors.size(); i++) + { + mode_colors[(3 * i) + 0] = RGBGetRValue(modes[active_mode].colors[i]); + mode_colors[(3 * i) + 1] = RGBGetGValue(modes[active_mode].colors[i]); + mode_colors[(3 * i) + 2] = RGBGetBValue(modes[active_mode].colors[i]); + } + } + + controller->SetChannelEffect(channel, + zones[channel].leds_count, + modes[active_mode].value, + modes[active_mode].speed, + direction, + random, + mode_colors[0], + mode_colors[1], + mode_colors[2], + mode_colors[3], + mode_colors[4], + mode_colors[5], + mode_colors[6], + mode_colors[7], + mode_colors[8]); + } + } +} diff --git a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h index 7ad7bc6e..7e984baa 100644 --- a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h +++ b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h @@ -15,12 +15,11 @@ class RGBController_ZalmanZSync : public RGBController { public: RGBController_ZalmanZSync(ZalmanZSyncController* controller_ptr); - ~RGBController_ZalmanZSync(); void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); @@ -29,5 +28,7 @@ public: void DeviceUpdateMode(); private: - ZalmanZSyncController* controller; -}; \ No newline at end of file + ZalmanZSyncController* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp b/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp index b70915c2..6fcc0065 100644 --- a/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp +++ b/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp @@ -1,80 +1,470 @@ +/*-----------------------------------------*\ +| ZalmanZSyncController.cpp | +| | +| Definitions and types for Zalman Z Sync | +| lighting controller | +| | +| The Zalman Z Sync device uses the same | +| protocol as the Corsair Lighting Node | +| devices except supports 8 channels. | +| | +| This code copied from the | +| CorsairLightingNodeController files | +| | +| Adam Honse (CalcProgrammer1) 1/30/2021 | +\*-----------------------------------------*/ + #include "ZalmanZSyncController.h" +#include +#include +#include +#include + +using namespace std::chrono_literals; + ZalmanZSyncController::ZalmanZSyncController(hid_device* dev_handle, const char* path) { dev = dev_handle; location = path; + + SendFirmwareRequest(); + + /*-----------------------------------------------------*\ + | The Corsair Lighting Node Pro requires a packet within| + | 20 seconds of sending the lighting change in order | + | to not revert back into rainbow mode. Start a thread | + | to continuously send a keepalive packet every 5s | + \*-----------------------------------------------------*/ + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&ZalmanZSyncController::KeepaliveThread, this); } ZalmanZSyncController::~ZalmanZSyncController() { - + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; } -std::string ZalmanZSyncController::GetDeviceLocation() +void ZalmanZSyncController::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::seconds(5)) + { + SendCommit(); + } + std::this_thread::sleep_for(1s); + } +} + +std::string ZalmanZSyncController::GetFirmwareString() +{ + return(firmware_version); +} + +std::string ZalmanZSyncController::GetLocationString() { return("HID: " + location); } std::string ZalmanZSyncController::GetSerialString() { - return(""); + wchar_t serial_string[128]; + hid_get_serial_number_string(dev, serial_string, 128); + + std::wstring return_wstring = serial_string; + std::string return_string(return_wstring.begin(), return_wstring.end()); + + return(return_string); } -void ZalmanZSyncController::SetLEDs(unsigned char channel, RGBColor* colors) +void ZalmanZSyncController::SetChannelEffect(unsigned char channel, + unsigned char num_leds, + unsigned char mode, + unsigned char speed, + unsigned char direction, + bool random, + unsigned char red1, + unsigned char grn1, + unsigned char blu1, + unsigned char red2, + unsigned char grn2, + unsigned char blu2, + unsigned char red3, + unsigned char grn3, + unsigned char blu3 + ) { - SendDirectFrame(channel, ZALMAN_Z_SYNC_COLOR_CHANNEL_RED, colors); - SendDirectFrame(channel, ZALMAN_Z_SYNC_COLOR_CHANNEL_GREEN, colors); - SendDirectFrame(channel, ZALMAN_Z_SYNC_COLOR_CHANNEL_BLUE, colors); + /*-----------------------------------------------------*\ + | Send Reset packet | + \*-----------------------------------------------------*/ + SendReset(channel); - SendApply(); + /*-----------------------------------------------------*\ + | Send Begin packet | + \*-----------------------------------------------------*/ + SendBegin(channel); + + /*-----------------------------------------------------*\ + | Set Port State packet | + \*-----------------------------------------------------*/ + SendPortState(channel, ZALMAN_Z_SYNC_PORT_STATE_HARDWARE); + + /*-----------------------------------------------------*\ + | Set Effect Configuration packet | + \*-----------------------------------------------------*/ + SendEffectConfig + ( + channel, + 0, + num_leds, + mode, + speed, + direction, + random, + red1, + grn1, + blu1, + red2, + grn2, + blu2, + red3, + grn3, + blu3, + 0, + 0, + 0 + ); + + /*-----------------------------------------------------*\ + | Send Commit packet | + \*-----------------------------------------------------*/ + SendCommit(); } -void ZalmanZSyncController::SendApply() +void ZalmanZSyncController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) { - unsigned char usb_buf[65]; + unsigned char red_color_data[50]; + unsigned char grn_color_data[50]; + unsigned char blu_color_data[50]; + unsigned char pkt_offset = 0; + unsigned char pkt_size = 0; + unsigned int colors_remaining = num_colors; - usb_buf[0] = 0x00; - usb_buf[1] = 0x33; - usb_buf[2] = 0xFF; + /*-----------------------------------------------------*\ + | Send Port State packet | + \*-----------------------------------------------------*/ + SendPortState(channel, ZALMAN_Z_SYNC_PORT_STATE_SOFTWARE); - hid_write(dev, usb_buf, 65); -} - -void ZalmanZSyncController::SendDirectFrame(unsigned char channel, unsigned char color_channel, RGBColor* colors) -{ - unsigned char usb_buf[65]; - - usb_buf[0] = 0x00; - usb_buf[1] = 0x32; - usb_buf[2] = channel; - usb_buf[3] = 0x00; - usb_buf[4] = 0x18; - usb_buf[5] = color_channel; - - switch(color_channel) + /*-----------------------------------------------------*\ + | Loop through colors and send 50 at a time | + \*-----------------------------------------------------*/ + while(colors_remaining > 0) { - case ZALMAN_Z_SYNC_COLOR_CHANNEL_RED: - for(unsigned int color_idx = 0; color_idx < 24; color_idx++) - { - usb_buf[6 + color_idx] = RGBGetRValue(colors[color_idx]); - } - break; + if(colors_remaining < 50) + { + pkt_size = colors_remaining; + } + else + { + pkt_size = 50; + } + + for(int color_idx = 0; color_idx < pkt_size; color_idx++) + { + red_color_data[color_idx] = RGBGetRValue(colors[pkt_offset + color_idx]); + grn_color_data[color_idx] = RGBGetGValue(colors[pkt_offset + color_idx]); + blu_color_data[color_idx] = RGBGetBValue(colors[pkt_offset + color_idx]); + } - case ZALMAN_Z_SYNC_COLOR_CHANNEL_GREEN: - for(unsigned int color_idx = 0; color_idx < 24; color_idx++) - { - usb_buf[6 + color_idx] = RGBGetGValue(colors[color_idx]); - } - break; + SendDirect(channel, pkt_offset, pkt_size, ZALMAN_Z_SYNC_DIRECT_CHANNEL_RED, red_color_data); + SendDirect(channel, pkt_offset, pkt_size, ZALMAN_Z_SYNC_DIRECT_CHANNEL_GREEN, grn_color_data); + SendDirect(channel, pkt_offset, pkt_size, ZALMAN_Z_SYNC_DIRECT_CHANNEL_BLUE, blu_color_data); - case ZALMAN_Z_SYNC_COLOR_CHANNEL_BLUE: - for(unsigned int color_idx = 0; color_idx < 24; color_idx++) - { - usb_buf[6 + color_idx] = RGBGetBValue(colors[color_idx]); - } - break; + colors_remaining -= pkt_size; + pkt_offset += pkt_size; } + /*-----------------------------------------------------*\ + | Send Commit packet | + \*-----------------------------------------------------*/ + SendCommit(); +} + +/*-------------------------------------------------------------------------------------------------*\ +| Private packet sending functions. | +\*-------------------------------------------------------------------------------------------------*/ + +void ZalmanZSyncController::SendFirmwareRequest() +{ + int actual; + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Firmware Version Request packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_FIRMWARE; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ hid_write(dev, usb_buf, 65); -} \ No newline at end of file + actual = hid_read(dev, usb_buf, 17); + + if(actual > 0) + { + firmware_version = std::to_string(usb_buf[0x01]) + "." + std::to_string(usb_buf[0x02]) + "." + std::to_string(usb_buf[0x03]); + } +} + +void ZalmanZSyncController::SendDirect + ( + unsigned char channel, + unsigned char start, + unsigned char count, + unsigned char color_channel, + unsigned char* color_data + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Direct packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_DIRECT; + usb_buf[0x02] = channel; + usb_buf[0x03] = start; + usb_buf[0x04] = count; + usb_buf[0x05] = color_channel; + + /*-----------------------------------------------------*\ + | Copy in color data bytes | + \*-----------------------------------------------------*/ + memcpy(&usb_buf[0x06], color_data, count); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 17); +} + +void ZalmanZSyncController::SendCommit() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Update last commit time | + \*-----------------------------------------------------*/ + last_commit_time = std::chrono::steady_clock::now(); + + /*-----------------------------------------------------*\ + | Set up Commit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_COMMIT; + usb_buf[0x02] = 0xFF; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 17); +} + +void ZalmanZSyncController::SendBegin + ( + unsigned char channel + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Begin packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_BEGIN; + usb_buf[0x02] = channel; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 17); +} + +void ZalmanZSyncController::SendEffectConfig + ( + unsigned char channel, + unsigned char count, + unsigned char led_type, + unsigned char mode, + unsigned char speed, + unsigned char direction, + unsigned char change_style, + unsigned char color_0_red, + unsigned char color_0_green, + unsigned char color_0_blue, + unsigned char color_1_red, + unsigned char color_1_green, + unsigned char color_1_blue, + unsigned char color_2_red, + unsigned char color_2_green, + unsigned char color_2_blue, + unsigned short temperature_0, + unsigned short temperature_1, + unsigned short temperature_2 + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Effect Config packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_EFFECT_CONFIG; + usb_buf[0x02] = channel; + usb_buf[0x03] = count; + usb_buf[0x04] = led_type; + + /*-----------------------------------------------------*\ + | Set up mode parameters | + \*-----------------------------------------------------*/ + usb_buf[0x05] = mode; + usb_buf[0x06] = speed; + usb_buf[0x07] = direction; + usb_buf[0x08] = change_style; + usb_buf[0x09] = 0; + + /*-----------------------------------------------------*\ + | Set up mode colors | + \*-----------------------------------------------------*/ + usb_buf[0x0A] = color_0_red; + usb_buf[0x0B] = color_0_green; + usb_buf[0x0C] = color_0_blue; + usb_buf[0x0D] = color_1_red; + usb_buf[0x0E] = color_1_green; + usb_buf[0x0F] = color_1_blue; + usb_buf[0x10] = color_2_red; + usb_buf[0x11] = color_2_green; + usb_buf[0x12] = color_2_blue; + + /*-----------------------------------------------------*\ + | Set up temperatures | + \*-----------------------------------------------------*/ + usb_buf[0x13] = (temperature_0 >> 8); + usb_buf[0x14] = (temperature_0 & 0xFF); + usb_buf[0x15] = (temperature_1 >> 8); + usb_buf[0x16] = (temperature_1 & 0xFF); + usb_buf[0x17] = (temperature_2 >> 8); + usb_buf[0x18] = (temperature_2 & 0xFF); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 17); +} + +void ZalmanZSyncController::SendTemperature() +{ + +} + +void ZalmanZSyncController::SendReset + ( + unsigned char channel + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Reset packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_RESET; + usb_buf[0x02] = channel; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 17); +} + +void ZalmanZSyncController::SendPortState + ( + unsigned char channel, + unsigned char state + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Port State packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = ZALMAN_Z_SYNC_PACKET_ID_PORT_STATE; + usb_buf[0x02] = channel; + usb_buf[0x03] = state; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 17); +} + +void ZalmanZSyncController::SendBrightness() +{ + +} + +void ZalmanZSyncController::SendLEDCount() +{ + +} + +void ZalmanZSyncController::SendProtocol() +{ + +} diff --git a/Controllers/ZalmanZSyncController/ZalmanZSyncController.h b/Controllers/ZalmanZSyncController/ZalmanZSyncController.h index 4880a1dd..d81f7abd 100644 --- a/Controllers/ZalmanZSyncController/ZalmanZSyncController.h +++ b/Controllers/ZalmanZSyncController/ZalmanZSyncController.h @@ -4,21 +4,92 @@ | Definitions and types for Zalman Z Sync | | lighting controller | | | +| The Zalman Z Sync device uses the same | +| protocol as the Corsair Lighting Node | +| devices except supports 8 channels. | +| | +| This code copied from the | +| CorsairLightingNodeController files | +| | | Adam Honse (CalcProgrammer1) 1/30/2021 | \*-----------------------------------------*/ #include "RGBController.h" - -#include +#include +#include #include #pragma once enum { - ZALMAN_Z_SYNC_COLOR_CHANNEL_RED = 0x00, - ZALMAN_Z_SYNC_COLOR_CHANNEL_GREEN = 0x01, - ZALMAN_Z_SYNC_COLOR_CHANNEL_BLUE = 0x02, + ZALMAN_Z_SYNC_PACKET_ID_FIRMWARE = 0x02, /* Get firmware version */ + ZALMAN_Z_SYNC_PACKET_ID_DIRECT = 0x32, /* Direct mode LED update packet */ + ZALMAN_Z_SYNC_PACKET_ID_COMMIT = 0x33, /* Commit changes packet */ + ZALMAN_Z_SYNC_PACKET_ID_BEGIN = 0x34, /* Begin effect packet */ + ZALMAN_Z_SYNC_PACKET_ID_EFFECT_CONFIG = 0x35, /* Effect mode configuration packet */ + ZALMAN_Z_SYNC_PACKET_ID_TEMPERATURE = 0x36, /* Update temperature value packet */ + ZALMAN_Z_SYNC_PACKET_ID_RESET = 0x37, /* Reset channel packet */ + ZALMAN_Z_SYNC_PACKET_ID_PORT_STATE = 0x38, /* Set port state packet */ + ZALMAN_Z_SYNC_PACKET_ID_BRIGHTNESS = 0x39, /* Set brightness packet */ + ZALMAN_Z_SYNC_PACKET_ID_LED_COUNT = 0x3A, /* Set LED count packet */ + ZALMAN_Z_SYNC_PACKET_ID_PROTOCOL = 0x3B, /* Set protocol packet */ +}; + +enum +{ + ZALMAN_Z_SYNC_DIRECT_CHANNEL_RED = 0x00, /* Red channel for direct update */ + ZALMAN_Z_SYNC_DIRECT_CHANNEL_GREEN = 0x01, /* Green channel for direct update */ + ZALMAN_Z_SYNC_DIRECT_CHANNEL_BLUE = 0x02, /* Blue channel for direct update */ +}; + +enum +{ + ZALMAN_Z_SYNC_PORT_STATE_HARDWARE = 0x01, /* Effect hardware control of channel */ + ZALMAN_Z_SYNC_PORT_STATE_SOFTWARE = 0x02, /* Direct software control of channel */ +}; + +enum +{ + ZALMAN_Z_SYNC_LED_TYPE_LED_STRIP = 0x0A, /* Corsair LED Strip Type */ + ZALMAN_Z_SYNC_LED_TYPE_HD_FAN = 0x0C, /* Corsair HD-series Fan Type */ + ZALMAN_Z_SYNC_LED_TYPE_SP_FAN = 0x01, /* Corsair SP-series Fan Type */ + ZALMAN_Z_SYNC_LED_TYPE_ML_FAN = 0x02, /* Corsair ML-series Fan Type */ +}; + +enum +{ + ZALMAN_Z_SYNC_CHANNEL_1 = 0x00, /* Channel 1 */ + ZALMAN_Z_SYNC_CHANNEL_2 = 0x01, /* Channel 2 */ + ZALMAN_Z_SYNC_CHANNEL_3 = 0x02, /* Channel 3 */ + ZALMAN_Z_SYNC_CHANNEL_4 = 0x03, /* Channel 4 */ + ZALMAN_Z_SYNC_CHANNEL_5 = 0x04, /* Channel 5 */ + ZALMAN_Z_SYNC_CHANNEL_6 = 0x05, /* Channel 6 */ + ZALMAN_Z_SYNC_CHANNEL_7 = 0x06, /* Channel 7 */ + ZALMAN_Z_SYNC_CHANNEL_8 = 0x07, /* Channel 8 */ + ZALMAN_Z_SYNC_NUM_CHANNELS = 0x08, /* Number of channels */ +}; + +enum +{ + ZALMAN_Z_SYNC_SPEED_FAST = 0x00, /* Fast speed */ + ZALMAN_Z_SYNC_SPEED_MEDIUM = 0x01, /* Medium speed */ + ZALMAN_Z_SYNC_SPEED_SLOW = 0x02, /* Slow speed */ +}; + +enum +{ + ZALMAN_Z_SYNC_MODE_RAINBOW_WAVE = 0x00, /* Rainbow Wave mode */ + ZALMAN_Z_SYNC_MODE_COLOR_SHIFT = 0x01, /* Color Shift mode */ + ZALMAN_Z_SYNC_MODE_COLOR_PULSE = 0x02, /* Color Pulse mode */ + ZALMAN_Z_SYNC_MODE_COLOR_WAVE = 0x03, /* Color Wave mode */ + ZALMAN_Z_SYNC_MODE_STATIC = 0x04, /* Static mode */ + ZALMAN_Z_SYNC_MODE_TEMPERATURE = 0x05, /* Temperature mode */ + ZALMAN_Z_SYNC_MODE_VISOR = 0x06, /* Visor mode */ + ZALMAN_Z_SYNC_MODE_MARQUEE = 0x07, /* Marquee mode */ + ZALMAN_Z_SYNC_MODE_BLINK = 0x08, /* Blink mode */ + ZALMAN_Z_SYNC_MODE_SEQUENTIAL = 0x09, /* Sequential mode */ + ZALMAN_Z_SYNC_MODE_RAINBOW = 0x0A, /* Rainbow mode */ }; class ZalmanZSyncController @@ -27,15 +98,98 @@ public: ZalmanZSyncController(hid_device* dev_handle, const char* path); ~ZalmanZSyncController(); - std::string GetDeviceLocation(); - std::string GetSerialString(); + std::string GetFirmwareString(); + std::string GetLocationString(); + std::string GetSerialString(); - void SetLEDs(unsigned char channel, RGBColor* colors); + unsigned int GetStripsOnChannel(unsigned int channel); + + void SetChannelEffect(unsigned char channel, + unsigned char num_leds, + unsigned char mode, + unsigned char speed, + unsigned char direction, + bool random, + unsigned char red1, + unsigned char grn1, + unsigned char blu1, + unsigned char red2, + unsigned char grn2, + unsigned char blu2, + unsigned char red3, + unsigned char grn3, + unsigned char blu3 + ); + + void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + + void KeepaliveThread(); private: hid_device* dev; + std::string firmware_version; std::string location; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_commit_time; - void SendApply(); - void SendDirectFrame(unsigned char channel, unsigned char color_channel, RGBColor* colors); + void SendFirmwareRequest(); + + void SendDirect + ( + unsigned char channel, + unsigned char start, + unsigned char count, + unsigned char color_channel, + unsigned char* color_data + ); + + void SendCommit(); + + void SendBegin + ( + unsigned char channel + ); + + void SendEffectConfig + ( + unsigned char channel, + unsigned char count, + unsigned char led_type, + unsigned char mode, + unsigned char speed, + unsigned char direction, + unsigned char change_style, + unsigned char color_0_red, + unsigned char color_0_green, + unsigned char color_0_blue, + unsigned char color_1_red, + unsigned char color_1_green, + unsigned char color_1_blue, + unsigned char color_2_red, + unsigned char color_2_green, + unsigned char color_2_blue, + unsigned short temperature_0, + unsigned short temperature_1, + unsigned short temperature_2 + ); + + void SendTemperature(); + + void SendReset + ( + unsigned char channel + ); + + void SendPortState + ( + unsigned char channel, + unsigned char state + ); + + void SendBrightness(); + + void SendLEDCount(); + + void SendProtocol(); };