From 516aefeaa614a74eb99d95c010d65cf37267e024 Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Sun, 11 Apr 2021 21:02:36 -0500 Subject: [PATCH] Make Razer Chroma ARGB controller outputs resizable --- .../RGBController_RazerAddressable.cpp | 286 ++++++++++++++++++ .../RGBController_RazerAddressable.h | 43 +++ .../RazerController/RazerControllerDetect.cpp | 5 +- OpenRGB.pro | 2 + 4 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 Controllers/RazerController/RGBController_RazerAddressable.cpp create mode 100644 Controllers/RazerController/RGBController_RazerAddressable.h diff --git a/Controllers/RazerController/RGBController_RazerAddressable.cpp b/Controllers/RazerController/RGBController_RazerAddressable.cpp new file mode 100644 index 00000000..71de8d0f --- /dev/null +++ b/Controllers/RazerController/RGBController_RazerAddressable.cpp @@ -0,0 +1,286 @@ +#include "RGBController_RazerAddressable.h" +#include "RazerDevices.h" + +#include + +RGBController_RazerAddressable::RGBController_RazerAddressable(RazerController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Razer"; + type = controller->GetDeviceType(); + description = "Razer Addressable Device"; + location = controller->GetDeviceLocation(); + version = controller->GetFirmwareString(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = RAZER_ADDRESSABLE_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = RAZER_ADDRESSABLE_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = RAZER_ADDRESSABLE_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = RAZER_ADDRESSABLE_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 2; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = RAZER_ADDRESSABLE_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = 0; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + // Wave disabled until proper detection + //mode Wave; + //Wave.name = "Wave"; + //Wave.value = RAZER_ADDRESSABLE_MODE_WAVE; + //Wave.flags = 0; + //Wave.color_mode = MODE_COLORS_NONE; + //modes.push_back(Wave); + + // Reactive disabled, not yet implemented + //mode Reactive; + //Reactive.name = "Reactive"; + //Reactive.value = RAZER_ADDRESSABLE_MODE_REACTIVE; + //Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + //Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + //Reactive.colors_min = 1; + //Reactive.colors_max = 1; + //Reactive.colors.resize(1); + //modes.push_back(Reactive); + + SetupZones(); +} + +RGBController_RazerAddressable::~RGBController_RazerAddressable() +{ + delete controller; +} + +void RGBController_RazerAddressable::SetupZones() +{ + unsigned int device_index = controller->GetDeviceIndex(); + unsigned int zone_count = 0; + + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + } + + /*-------------------------------------------------*\ + | Count the number of zones for this device | + \*-------------------------------------------------*/ + for(unsigned int zone_id = 0; zone_id < RAZER_MAX_ZONES; zone_id++) + { + if(device_list[device_index]->zones[zone_id] != NULL) + { + zone_count++; + } + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + zones.resize(zone_count); + + /*---------------------------------------------------------*\ + | Fill in zone information based on device table | + \*---------------------------------------------------------*/ + zone_count = 0; + + for(unsigned int zone_id = 0; zone_id < RAZER_MAX_ZONES; zone_id++) + { + if(device_list[device_index]->zones[zone_id] != NULL) + { + zones[zone_count].name = device_list[device_index]->zones[zone_id]->name; + zones[zone_count].type = device_list[device_index]->zones[zone_id]->type; + + zones[zone_count].leds_min = 0; + zones[zone_count].leds_max = device_list[device_index]->zones[zone_id]->rows * device_list[device_index]->zones[zone_id]->cols; + + if(first_run) + { + zones[zone_count].leds_count = 0; + } + + if(zones[zone_count].type == ZONE_TYPE_MATRIX) + { + matrix_map_type * new_map = new matrix_map_type; + zones[zone_count].matrix_map = new_map; + + new_map->height = device_list[device_index]->zones[zone_id]->rows; + new_map->width = device_list[device_index]->zones[zone_id]->cols; + + new_map->map = new unsigned int[new_map->height * new_map->width]; + + for(unsigned int y = 0; y < new_map->height; y++) + { + for(unsigned int x = 0; x < new_map->width; x++) + { + new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x; + } + } + } + else + { + zones[zone_count].matrix_map = NULL; + } + + zone_count++; + } + } + + for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++) + { + for(unsigned int led_id = 0; led_id < zones[zone_id].leds_count; led_id++) + { + led new_led; + new_led.name = "Channel " + std::to_string(zone_id + 1) + ", LED " + std::to_string(led_id + 1); + + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_RazerAddressable::ResizeZone(int zone, int new_size) +{ + /*---------------------------------------------------------*\ + | Only the Razer Chroma Addressable RGB Controller supports | + | zone resizing | + \*---------------------------------------------------------*/ + 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_RazerAddressable::DeviceUpdateLEDs() +{ + /*---------------------------------------------------------*\ + | Only the Razer Chroma Addressable RGB Controller supports | + | zone resizing | + \*---------------------------------------------------------*/ + RGBColor colors_buf[80 * 6]; + + for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++) + { + memcpy(&colors_buf[(80 * zone_id)], zones[zone_id].colors, sizeof(RGBColor) * zones[zone_id].leds_count); + } + + controller->SetLEDs(&colors_buf[0]); +} + +void RGBController_RazerAddressable::UpdateZoneLEDs(int zone) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RazerAddressable::UpdateSingleLED(int led) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RazerAddressable::SetCustomMode() +{ + active_mode = 0; +} + +void RGBController_RazerAddressable::DeviceUpdateMode() +{ + switch(modes[active_mode].value) + { + case RAZER_ADDRESSABLE_MODE_OFF: + controller->SetModeOff(); + break; + + case RAZER_ADDRESSABLE_MODE_STATIC: + if(modes[active_mode].colors.size() == 1) + { + unsigned char red = RGBGetRValue(modes[active_mode].colors[0]); + unsigned char grn = RGBGetGValue(modes[active_mode].colors[0]); + unsigned char blu = RGBGetBValue(modes[active_mode].colors[0]); + + controller->SetModeStatic(red, grn, blu); + } + break; + + case RAZER_ADDRESSABLE_MODE_BREATHING: + if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) + { + controller->SetModeBreathingRandom(); + } + else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + if(modes[active_mode].colors.size() == 1) + { + unsigned char red = RGBGetRValue(modes[active_mode].colors[0]); + unsigned char grn = RGBGetGValue(modes[active_mode].colors[0]); + unsigned char blu = RGBGetBValue(modes[active_mode].colors[0]); + + controller->SetModeBreathingOneColor(red, grn, blu); + } + else if(modes[active_mode].colors.size() == 2) + { + unsigned char red1 = RGBGetRValue(modes[active_mode].colors[0]); + unsigned char grn1 = RGBGetGValue(modes[active_mode].colors[0]); + unsigned char blu1 = RGBGetBValue(modes[active_mode].colors[0]); + unsigned char red2 = RGBGetRValue(modes[active_mode].colors[1]); + unsigned char grn2 = RGBGetGValue(modes[active_mode].colors[1]); + unsigned char blu2 = RGBGetBValue(modes[active_mode].colors[1]); + + controller->SetModeBreathingTwoColors(red1, grn1, blu1, red2, grn2, blu2); + } + } + break; + + case RAZER_ADDRESSABLE_MODE_SPECTRUM_CYCLE: + controller->SetModeSpectrumCycle(); + break; + + case RAZER_ADDRESSABLE_MODE_WAVE: + controller->SetModeWave(); + break; + } +} diff --git a/Controllers/RazerController/RGBController_RazerAddressable.h b/Controllers/RazerController/RGBController_RazerAddressable.h new file mode 100644 index 00000000..b76e3d53 --- /dev/null +++ b/Controllers/RazerController/RGBController_RazerAddressable.h @@ -0,0 +1,43 @@ +/*-----------------------------------------*\ +| RGBController_RazerAddressable.h | +| | +| Generic RGB Interface for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 4/11/2021 | +\*-----------------------------------------*/ + +#pragma once +#include "RGBController.h" +#include "RazerController.h" + +enum +{ + RAZER_ADDRESSABLE_MODE_DIRECT, + RAZER_ADDRESSABLE_MODE_OFF, + RAZER_ADDRESSABLE_MODE_STATIC, + RAZER_ADDRESSABLE_MODE_BREATHING, + RAZER_ADDRESSABLE_MODE_SPECTRUM_CYCLE, + RAZER_ADDRESSABLE_MODE_WAVE, + RAZER_ADDRESSABLE_MODE_REACTIVE, +}; + +class RGBController_RazerAddressable : public RGBController +{ +public: + RGBController_RazerAddressable(RazerController* controller_ptr); + ~RGBController_RazerAddressable(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void DeviceUpdateMode(); + +private: + RazerController* controller; +}; diff --git a/Controllers/RazerController/RazerControllerDetect.cpp b/Controllers/RazerController/RazerControllerDetect.cpp index a1698dfc..518670d4 100644 --- a/Controllers/RazerController/RazerControllerDetect.cpp +++ b/Controllers/RazerController/RazerControllerDetect.cpp @@ -5,6 +5,7 @@ #include "ResourceManager.h" #include "RGBController.h" #include "RGBController_Razer.h" +#include "RGBController_RazerAddressable.h" #include "RGBController_RazerKraken.h" #include @@ -116,8 +117,8 @@ void DetectRazerARGBControllers(hid_device_info* info, const std::string& name) } if(dev_interface_0 && dev_interface_1) { - RazerController* controller = new RazerController(dev_interface_0, dev_interface_1, info->path, info->product_id, name); - RGBController_Razer* rgb_controller = new RGBController_Razer(controller); + RazerController* controller = new RazerController(dev_interface_0, dev_interface_1, info->path, info->product_id, name); + RGBController_RazerAddressable* rgb_controller = new RGBController_RazerAddressable(controller); ResourceManager::get()->RegisterRGBController(rgb_controller); } else diff --git a/OpenRGB.pro b/OpenRGB.pro index 814d4f92..3199b187 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -300,6 +300,7 @@ HEADERS += Controllers/RazerController/RazerKrakenController.h \ Controllers/RazerController/RazerDevices.h \ Controllers/RazerController/RGBController_Razer.h \ + Controllers/RazerController/RGBController_RazerAddressable.h \ Controllers/RazerController/RGBController_RazerKraken.h \ Controllers/RedragonController/RedragonM711Controller.h \ Controllers/RedragonController/RGBController_RedragonM711.h \ @@ -569,6 +570,7 @@ SOURCES += Controllers/RazerController/RazerKrakenController.cpp \ Controllers/RazerController/RazerControllerDetect.cpp \ Controllers/RazerController/RGBController_Razer.cpp \ + Controllers/RazerController/RGBController_RazerAddressable.cpp \ Controllers/RazerController/RGBController_RazerKraken.cpp \ Controllers/RedragonController/RedragonM711Controller.cpp \ Controllers/RedragonController/RedragonControllerDetect.cpp \