Files
OpenRGB/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp
2023-07-09 21:38:39 +00:00

463 lines
16 KiB
C++

/*-----------------------------------------*\
| RGBController_ZotacV2GPU.cpp |
| |
| Generic RGB Interface for OpenRGB |
| ZOTAC RTX 30/40 series GPU Driver |
| |
| Krzysztof Haładyn (krzys_h) 3/16/2023 |
\*-----------------------------------------*/
#include "RGBController_ZotacV2GPU.h"
#include "LogManager.h"
#include <map>
std::map<std::string, ZotacV2GPUConfig> ZOTAC_V2_GPU_CONFIG =
{
{ "N653E-1013", { 2, false } }, // ZOTAC GAMING GeForce RTX 3070 Ti Trinity OC
{ "N612A-1012", { 2, false } }, // ZOTAC GAMING GeForce RTX 3080 Ti AMP Holo
{ "N618A-1015", { 4, true } }, // ZOTAC GAMING GeForce RTX 3090 AMP Extreme Holo
{ "N675E-1019", { 1, true } }, // ZOTAC GAMING GeForce RTX 4090 Trinity OC
{ "N675A-1019", { 5, true } }, // ZOTAC GAMING GeForce RTX 4090 AMP Extreme AIRO
};
std::vector<std::pair<RGBColor, RGBColor>> ZOTAC_V2_GPU_DUET_PRESETS =
{
{ ToRGBColor(0x32, 0xCF, 0xA7), ToRGBColor(0x93, 0x34, 0xC2) },
{ ToRGBColor(0x00, 0xC9, 0x14), ToRGBColor(0x00, 0x20, 0xF5) },
{ ToRGBColor(0xD1, 0xFC, 0x00), ToRGBColor(0xF1, 0x0C, 0x00) },
{ ToRGBColor(0xFF, 0x68, 0x7C), ToRGBColor(0xD4, 0x00, 0x4D) },
};
/**------------------------------------------------------------------*\
@name ZOTAC 30/40 series GPU
@category GPU
@type I2C
@save :robot:
@direct :x:
@effects :tools:
@detectors DetectZotacV2GPUControllers
@comment
OpenRGB does not support per-zone effect modes, so only
the synchronized mode is supported for now. Sound based
effects are not supported. Idle/active config is not
supported.
\*-------------------------------------------------------------------*/
RGBController_ZotacV2GPU::RGBController_ZotacV2GPU(ZotacV2GPUController* controller_ptr)
{
controller = controller_ptr;
name = "ZOTAC GPU";
vendor = "ZOTAC";
description = "ZOTAC 30/40 series RGB GPU Device (" + controller->GetVersion() + ")";
location = controller->GetDeviceLocation();
type = DEVICE_TYPE_GPU;
config = ZOTAC_V2_GPU_CONFIG.at(controller->GetVersion());
version += std::to_string(config.numberOfZones) + " zones, "
+ (config.supportsExternalLEDStrip ? "with" : "without") + " external LED strip support";
mode STATIC;
STATIC.name = "Static";
STATIC.value = ZOTAC_V2_GPU_MODE_STATIC;
STATIC.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
STATIC.brightness_min = 0;
STATIC.brightness_max = 100;
STATIC.brightness = 100;
STATIC.color_mode = MODE_COLORS_MODE_SPECIFIC;
STATIC.colors_min = 1;
STATIC.colors_max = 1;
STATIC.colors.resize(1);
STATIC.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(STATIC);
mode BREATH;
BREATH.name = "Breath";
BREATH.value = ZOTAC_V2_GPU_MODE_BREATH;
BREATH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
BREATH.brightness_min = 0;
BREATH.brightness_max = 100;
BREATH.brightness = 100;
BREATH.speed_min = 0;
BREATH.speed_max = 100;
BREATH.speed = 20;
BREATH.color_mode = MODE_COLORS_MODE_SPECIFIC;
BREATH.colors_min = 1;
BREATH.colors_max = 1;
BREATH.colors.resize(1);
BREATH.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(BREATH);
mode FADE;
FADE.name = "Fade";
FADE.value = ZOTAC_V2_GPU_MODE_FADE;
FADE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED;
FADE.speed_min = 0;
FADE.speed_max = 100;
FADE.speed = 20;
FADE.color_mode = MODE_COLORS_NONE;
modes.push_back(FADE);
mode WINK;
WINK.name = "Wink";
WINK.value = ZOTAC_V2_GPU_MODE_WINK;
WINK.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
WINK.brightness_min = 0;
WINK.brightness_max = 100;
WINK.brightness = 100;
WINK.speed_min = 0;
WINK.speed_max = 100;
WINK.speed = 20;
WINK.color_mode = MODE_COLORS_MODE_SPECIFIC;
WINK.colors_min = 1;
WINK.colors_max = 1;
WINK.colors.resize(1);
WINK.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(WINK);
if(config.numberOfZones > 1)
{
// This mode is only supported on GPUs with more than one zone,
// because it spans multiple zones.
// It's also supported in synchronized mode only (which is the only
// thing this RGBController supports for now anyway)
mode FLASH;
FLASH.name = "Flash";
FLASH.value = ZOTAC_V2_GPU_MODE_FLASH;
FLASH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED;
FLASH.speed_min = 0;
FLASH.speed_max = 100;
FLASH.speed = 20;
FLASH.color_mode = MODE_COLORS_NONE;
modes.push_back(FLASH);
}
// (Sound activated - not supported)
//mode SHINE;
//SHINE.name = "Shine";
//SHINE.value = ZOTAC_V2_GPU_MODE_SHINE;
//SHINE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
//SHINE.brightness_min = 0;
//SHINE.brightness_max = 100;
//SHINE.brightness = 100;
//SHINE.color_mode = MODE_COLORS_MODE_SPECIFIC;
//SHINE.colors_min = 1;
//SHINE.colors_max = 1;
//SHINE.colors.resize(1);
//SHINE.colors[0] = ToRGBColor(0, 0, 255);
//modes.push_back(SHINE);
mode RANDOM;
RANDOM.name = "Random";
RANDOM.value = ZOTAC_V2_GPU_MODE_RANDOM;
RANDOM.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR;
RANDOM.brightness_min = 0;
RANDOM.brightness_max = 100;
RANDOM.brightness = 100;
RANDOM.speed_min = 0;
RANDOM.speed_max = 100;
RANDOM.speed = 20;
RANDOM.color_mode = MODE_COLORS_MODE_SPECIFIC;
RANDOM.colors_min = 1;
RANDOM.colors_max = 1;
RANDOM.colors.resize(1);
RANDOM.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(RANDOM);
mode SLIDE;
SLIDE.name = "Slide";
SLIDE.value = ZOTAC_V2_GPU_MODE_SLIDE;
SLIDE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR;
SLIDE.brightness_min = 0;
SLIDE.brightness_max = 100;
SLIDE.brightness = 100;
SLIDE.speed_min = 0;
SLIDE.speed_max = 100;
SLIDE.speed = 20;
SLIDE.color_mode = MODE_COLORS_MODE_SPECIFIC;
SLIDE.colors_min = 1;
SLIDE.colors_max = 1;
SLIDE.colors.resize(1);
SLIDE.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(SLIDE);
mode RAINBOW;
RAINBOW.name = "Rainbow";
RAINBOW.value = ZOTAC_V2_GPU_MODE_RAINBOW;
RAINBOW.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
RAINBOW.speed_min = 0;
RAINBOW.speed_max = 100;
RAINBOW.speed = 20;
RAINBOW.color_mode = MODE_COLORS_NONE;
modes.push_back(RAINBOW);
mode RAINBOW_CIRCUIT = RAINBOW;
RAINBOW_CIRCUIT.name = "Rainbow (circuit)";
modes.push_back(RAINBOW_CIRCUIT);
mode MARQUEE;
MARQUEE.name = "Marquee";
MARQUEE.value = ZOTAC_V2_GPU_MODE_MARQUEE;
MARQUEE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR;
MARQUEE.brightness_min = 0;
MARQUEE.brightness_max = 100;
MARQUEE.brightness = 100;
MARQUEE.speed_min = 0;
MARQUEE.speed_max = 100;
MARQUEE.speed = 20;
MARQUEE.color_mode = MODE_COLORS_MODE_SPECIFIC;
MARQUEE.colors_min = 1;
MARQUEE.colors_max = 1;
MARQUEE.colors.resize(1);
MARQUEE.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(MARQUEE);
mode MARQUEE_CIRCUIT = MARQUEE;
MARQUEE_CIRCUIT.name = "Marquee (circuit)";
modes.push_back(MARQUEE_CIRCUIT);
mode DRIP;
DRIP.name = "Drip";
DRIP.value = ZOTAC_V2_GPU_MODE_DRIP;
DRIP.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR;
DRIP.brightness_min = 0;
DRIP.brightness_max = 100;
DRIP.brightness = 100;
DRIP.speed_min = 0;
DRIP.speed_max = 100;
DRIP.speed = 20;
DRIP.color_mode = MODE_COLORS_MODE_SPECIFIC;
DRIP.colors_min = 1;
DRIP.colors_max = 1;
DRIP.colors.resize(1);
DRIP.colors[0] = ToRGBColor(0, 0, 255);
modes.push_back(DRIP);
mode DRIP_CIRCUIT = DRIP;
DRIP_CIRCUIT.name = "Drip (circuit)";
modes.push_back(DRIP_CIRCUIT);
// (Sound activated - not supported)
//mode DANCE;
//DANCE.name = "Dance (sound activated)";
//DANCE.value = ZOTAC_V2_GPU_MODE_DANCE;
//DANCE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR;
//DANCE.brightness_min = 0;
//DANCE.brightness_max = 100;
//DANCE.brightness = 100;
//DANCE.color_mode = MODE_COLORS_MODE_SPECIFIC;
//DANCE.colors_min = 1;
//DANCE.colors_max = 1;
//DANCE.colors.resize(1);
//DANCE.colors[0] = ToRGBColor(0, 0, 255);
//modes.push_back(DANCE);
mode DUET;
DUET.name = "Duet";
DUET.value = ZOTAC_V2_GPU_MODE_DUET;
DUET.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR;
DUET.speed_min = 0;
DUET.speed_max = 100;
DUET.speed = 20;
DUET.color_mode = MODE_COLORS_MODE_SPECIFIC;
DUET.colors_min = 2;
DUET.colors_max = 2;
DUET.colors.resize(2);
DUET.colors[0] = ZOTAC_V2_GPU_DUET_PRESETS[1].first;
DUET.colors[1] = ZOTAC_V2_GPU_DUET_PRESETS[1].second;
modes.push_back(DUET);
mode DUET_CIRCUIT = DUET;
DUET_CIRCUIT.name = "Duet (circuit)";
modes.push_back(DUET_CIRCUIT);
mode PATH;
PATH.name = "Path";
PATH.value = ZOTAC_V2_GPU_MODE_PATH;
PATH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR;
PATH.brightness_min = 0;
PATH.brightness_max = 100;
PATH.brightness = 100;
PATH.speed_min = 0;
PATH.speed_max = 100;
PATH.speed = 20;
PATH.color_mode = MODE_COLORS_NONE;
modes.push_back(PATH);
SetupZones();
}
RGBController_ZotacV2GPU::~RGBController_ZotacV2GPU()
{
delete controller;
}
void RGBController_ZotacV2GPU::SetupZones()
{
led new_led;
new_led.name = "GPU LED";
leds.push_back(new_led);
zone new_zone;
new_zone.name = "GPU Zone";
new_zone.type = ZONE_TYPE_SINGLE;
new_zone.leds_min = 1;
new_zone.leds_max = 1;
new_zone.leds_count = 1;
new_zone.matrix_map = NULL;
zones.push_back(new_zone);
SetupColors();
SetupInitialValues();
}
void RGBController_ZotacV2GPU::SetupInitialValues()
{
/*---------------------------------------------------------*\
| Retrieve current values by reading the device |
\*---------------------------------------------------------*/
bool on;
int syncMode;
ZotacV2GPUZone zoneConfig;
// We don't support anything other than synchronized mode, so read the last
// config used in synchronized mode for idle settings.
int zoneNum = FindSynchronizedZoneNum(ZOTAC_V2_GPU_SYNC_SYNCHRONIZED);
if(!controller->GetMode(zoneNum, ZOTAC_V2_GPU_CONFIG_IDLE, syncMode, zoneConfig, on))
{
return;
}
for(unsigned int i = 0; i < modes.size(); ++i)
{
if(zoneConfig.mode != modes[i].value)
{
continue;
}
if(zoneConfig.mode == ZOTAC_V2_GPU_MODE_RAINBOW ||
zoneConfig.mode == ZOTAC_V2_GPU_MODE_MARQUEE ||
zoneConfig.mode == ZOTAC_V2_GPU_MODE_DRIP ||
zoneConfig.mode == ZOTAC_V2_GPU_MODE_DUET)
{
if((zoneConfig.circuit == ZOTAC_V2_GPU_CIRCUIT_ON) != (modes[i].name.find("(circuit)") != std::string::npos))
{
continue;
}
}
active_mode = i;
}
colors[0] = zoneConfig.color1;
if(modes[active_mode].colors.size() >= 1)
{
modes[active_mode].colors[0] = zoneConfig.color1;
}
if(modes[active_mode].colors.size() >= 2)
{
modes[active_mode].colors[1] = zoneConfig.color2;
}
modes[active_mode].speed = zoneConfig.speed;
modes[active_mode].brightness = zoneConfig.brightness;
modes[active_mode].direction = zoneConfig.direction;
SignalUpdate();
}
void RGBController_ZotacV2GPU::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_ZotacV2GPU::DeviceUpdateLEDs()
{
DeviceUpdateMode();
}
void RGBController_ZotacV2GPU::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateMode();
}
void RGBController_ZotacV2GPU::UpdateSingleLED(int /*led*/)
{
DeviceUpdateMode();
}
void RGBController_ZotacV2GPU::DeviceUpdateMode()
{
ZotacV2GPUZone zoneConfig;
zoneConfig.mode = modes[active_mode].value;
zoneConfig.color1 = modes[active_mode].colors.size() >= 1 ? modes[active_mode].colors[0] : ToRGBColor(0, 0, 0);
zoneConfig.color2 = modes[active_mode].colors.size() >= 2 ? modes[active_mode].colors[1] : ToRGBColor(0, 0, 0);
// This is probably not strictly neccessary
zoneConfig.colorPreset = 0;
if(zoneConfig.mode == ZOTAC_V2_GPU_MODE_DUET)
{
zoneConfig.colorPreset = ZOTAC_V2_GPU_DUET_PRESETS.size(); // custom
for(size_t i = 0; i < ZOTAC_V2_GPU_DUET_PRESETS.size(); ++i)
{
if(zoneConfig.color1 == ZOTAC_V2_GPU_DUET_PRESETS[i].first &&
zoneConfig.color2 == ZOTAC_V2_GPU_DUET_PRESETS[i].second)
{
zoneConfig.colorPreset = i;
}
}
}
zoneConfig.speed = modes[active_mode].speed;
zoneConfig.brightness = modes[active_mode].brightness;
zoneConfig.direction = modes[active_mode].direction == MODE_DIRECTION_RIGHT ? ZOTAC_V2_GPU_DIR_RIGHT : ZOTAC_V2_GPU_DIR_LEFT;
if(zoneConfig.mode == ZOTAC_V2_GPU_MODE_RAINBOW ||
zoneConfig.mode == ZOTAC_V2_GPU_MODE_MARQUEE ||
zoneConfig.mode == ZOTAC_V2_GPU_MODE_DRIP ||
zoneConfig.mode == ZOTAC_V2_GPU_MODE_DUET)
{
zoneConfig.circuit = modes[active_mode].name.find("(circuit)") != std::string::npos ? ZOTAC_V2_GPU_CIRCUIT_ON : ZOTAC_V2_GPU_CIRCUIT_OFF;
}
else
{
zoneConfig.circuit = 0;
}
int zoneNum = FindSynchronizedZoneNum(ZOTAC_V2_GPU_SYNC_SYNCHRONIZED);
controller->TurnOnOff(true);
controller->SetMode(zoneNum, ZOTAC_V2_GPU_CONFIG_IDLE, ZOTAC_V2_GPU_SYNC_SYNCHRONIZED, zoneConfig);
controller->SetMode(zoneNum, ZOTAC_V2_GPU_CONFIG_ACTIVE, ZOTAC_V2_GPU_SYNC_SYNCHRONIZED, zoneConfig);
}
int RGBController_ZotacV2GPU::FindSynchronizedZoneNum(int syncMode)
{
// Figure out the index of the zone used for ZOTAC_V2_GPU_SYNC_SYNCHRONIZED
// or ZOTAC_V2_GPU_SYNC_SYNCHRONIZED_WITH_EXTERNAL settings based on the GPU
// zone config
int lastRealZone = config.numberOfZones - 1;
if(config.supportsExternalLEDStrip)
{
lastRealZone += 1;
}
if(syncMode == ZOTAC_V2_GPU_SYNC_SYNCHRONIZED)
{
return lastRealZone + 1;
}
else if(syncMode == ZOTAC_V2_GPU_SYNC_SYNCHRONIZED_WITH_EXTERNAL)
{
assert(config.supportsExternalLEDStrip);
return lastRealZone + 2;
}
else
{
assert(false);
return 0;
}
}