diff --git a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp index e669c9e8..32a3bf69 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp +++ b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp @@ -1,83 +1,140 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2DRAMController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion 2 | -| DRAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/7/2020 | -\*-----------------------------------------*/ - -#include "GigabyteRGBFusion2DRAMController.h" - -#include -#include -#include - -RGBFusion2DRAMController::RGBFusion2DRAMController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) -{ - /*-----------------------------------------------------*\ - | Initialize pointers | - \*-----------------------------------------------------*/ - this->bus = bus; - this->dev = dev; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(led_data, 0, sizeof(led_data)); - - /*-----------------------------------------------------*\ - | Initialize controller with 6 LEDs and mask 0x3B | - | This is hard coded for Aorus RGB RAM | - \*-----------------------------------------------------*/ - led_data[RGB_FUSION_2_DRAM_LED_EN_MASK] = 0x3B; - led_count = 6; - - /*-----------------------------------------------------*\ - | Initialize brightness to 100% | - \*-----------------------------------------------------*/ - led_data[RGB_FUSION_2_DRAM_IDX_BRIGHTNESS] = 0x64; -} - -RGBFusion2DRAMController::~RGBFusion2DRAMController() -{ - -} - -unsigned int RGBFusion2DRAMController::GetLEDCount() -{ - return(led_count); -} - -std::string RGBFusion2DRAMController::GetDeviceLocation() -{ - std::string return_string(bus->device_name); - char addr[5]; - snprintf(addr, 5, "0x%02X", dev); - return_string.append(", address "); - return_string.append(addr); - return("I2C: " + return_string); -} - -void RGBFusion2DRAMController::Apply() -{ - bus->i2c_smbus_write_byte_data(dev, RGB_FUSION_2_DRAM_APPLY_ADDR, RGB_FUSION_2_DRAM_ACTION_APPLY); -} - -void RGBFusion2DRAMController::SetLEDEffect - ( - unsigned int /*led*/, - int mode, - unsigned int /*speed*/, - unsigned char red, - unsigned char green, - unsigned char blue - ) -{ - led_data[RGB_FUSION_2_DRAM_IDX_MODE] = mode; - led_data[RGB_FUSION_2_DRAM_IDX_RED] = red; - led_data[RGB_FUSION_2_DRAM_IDX_GREEN] = green; - led_data[RGB_FUSION_2_DRAM_IDX_BLUE] = blue; - - bus->i2c_smbus_write_block_data(dev, RGB_FUSION_2_DRAM_LED_START_ADDR, 32, led_data); -} +/*-----------------------------------------*\ +| GigabyteRGBFusion2DRAMController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 | +| DRAM lighting controller | +| | +| Adam Honse (CalcProgrammer1) 6/7/2020 | +\*-----------------------------------------*/ + +#include "GigabyteRGBFusion2DRAMController.h" + +#include +#include +#include + +RGBFusion2DRAMController::RGBFusion2DRAMController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) +{ + /*-----------------------------------------------------*\ + | Initialize pointers | + \*-----------------------------------------------------*/ + this->bus = bus; + this->dev = dev; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(led_data, 0, sizeof(led_data)); + + /*-----------------------------------------------------*\ + | Initialize controller with 6 LEDs | + | This is hard coded for Aorus RGB RAM | + \*-----------------------------------------------------*/ + led_count = 6; + + direct_initialized = false; +} + +RGBFusion2DRAMController::~RGBFusion2DRAMController() +{ + +} + +unsigned int RGBFusion2DRAMController::GetLEDCount() +{ + return(led_count); +} + +std::string RGBFusion2DRAMController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +void RGBFusion2DRAMController::Apply() +{ + bus->i2c_smbus_write_byte_data(dev, RGB_FUSION_2_DRAM_APPLY_ADDR, RGB_FUSION_2_DRAM_ACTION_APPLY); +} + +void RGBFusion2DRAMController::SetLEDEffect + ( + unsigned int led, + int mode, + unsigned int brightness, + unsigned int /*speed*/, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + bool truncate_packet = false; + + if(mode == RGB_FUSION_2_DRAM_MODE_DIRECT) + { + /*-----------------------------------------------------*\ + | In Direct mode, set one LED at a time | + \*-----------------------------------------------------*/ + led_data[RGB_FUSION_2_DRAM_LED_EN_MASK] = (1 << led); + + /*-----------------------------------------------------*\ + | Hack for Direct mode | + \*-----------------------------------------------------*/ + led_data[16] = 1; + led_data[22] = 2; + led_data[29] = 1; + led_data[30] = 1; + + /*-----------------------------------------------------*\ + | If bytes 15-31 have already been set, we can speed up | + | repeat direct mode packets by only sending the portion| + | that changes, in this case bytes 0-14. If direct mode| + | has already been initialized, truncate the packet by | + | only sending the first 15 bytes. | + \*-----------------------------------------------------*/ + if(direct_initialized) + { + truncate_packet = true; + } + + direct_initialized = true; + + /*-----------------------------------------------------*\ + | Direct mode is implemented using Pulse mode | + \*-----------------------------------------------------*/ + mode = RGB_FUSION_2_DRAM_MODE_PULSE; + } + else + { + /*-----------------------------------------------------*\ + | In all other modes, set all LEDs at once | + \*-----------------------------------------------------*/ + led_data[RGB_FUSION_2_DRAM_LED_EN_MASK] = 0x3F; + + /*-----------------------------------------------------*\ + | Clear direct mode initialized flag when setting a non-| + | Direct mode | + \*-----------------------------------------------------*/ + direct_initialized = false; + } + + led_data[RGB_FUSION_2_DRAM_IDX_MODE] = mode; + led_data[RGB_FUSION_2_DRAM_IDX_BRIGHTNESS] = brightness; + led_data[RGB_FUSION_2_DRAM_IDX_RED] = red; + led_data[RGB_FUSION_2_DRAM_IDX_GREEN] = green; + led_data[RGB_FUSION_2_DRAM_IDX_BLUE] = blue; + + if(truncate_packet) + { + bus->i2c_smbus_write_block_data(dev, RGB_FUSION_2_DRAM_LED_START_ADDR, 15, led_data); + } + else + { + bus->i2c_smbus_write_block_data(dev, RGB_FUSION_2_DRAM_LED_START_ADDR, 32, led_data); + } + + Apply(); +} diff --git a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h index e00f34c4..8e6d0a5c 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h +++ b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h @@ -1,72 +1,83 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2DRAMController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion 2 DRAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/7/2020 | -\*-----------------------------------------*/ - -#include -#include "i2c_smbus.h" - -#pragma once - -typedef unsigned char rgb_fusion_dev_id; - -enum -{ - RGB_FUSION_2_DRAM_LED_EN_MASK = 0x00, /* LED enable bitfield */ - RGB_FUSION_2_DRAM_IDX_MODE = 0x09, /* Mode index */ - RGB_FUSION_2_DRAM_IDX_BRIGHTNESS = 0x0A, /* Brightness index */ - RGB_FUSION_2_DRAM_IDX_BLUE = 0x0C, /* Blue index */ - RGB_FUSION_2_DRAM_IDX_GREEN = 0x0D, /* Green index */ - RGB_FUSION_2_DRAM_IDX_RED = 0x0E, /* Red index */ -// RGB_FUSION_2_DRAM_TIMER_1_LSB = 0x08, /* Timer 1 LSB. Valid timer values [0-65535] */ -// RGB_FUSION_2_DRAM_TIMER_1_MSB = 0x09, /* Timer 1 MSB. Timer unis are milliseconds */ -// RGB_FUSION_2_DRAM_TIMER_2_LSB = 0x0A, /* Timer 2 LSB */ -// RGB_FUSION_2_DRAM_TIMER_2_MSB = 0x0B, /* Timer 2 MSB */ -// RGB_FUSION_2_DRAM_TIMER_3_LSB = 0x0C, /* Timer 3 LSB */ -// RGB_FUSION_2_DRAM_TIMER_3_MSB = 0x0D, /* Timer 3 MSB */ -// RGB_FUSION_2_DRAM_IDX_OPT_1 = 0x0E, /* Option 1. Use case varies by mode */ -// RGB_FUSION_2_DRAM_IDX_OPT_2 = 0x0F, /* Option 2. Use case varies by mode */ -}; - -enum -{ - RGB_FUSION_2_DRAM_LED_START_ADDR = 0x20, - RGB_FUSION_2_DRAM_APPLY_ADDR = 0x28, -}; - -enum -{ - RGB_FUSION_2_DRAM_ACTION_APPLY = 0x0F, -}; - -class RGBFusion2DRAMController -{ -public: - RGBFusion2DRAMController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev); - ~RGBFusion2DRAMController(); - - std::string GetDeviceLocation(); - unsigned int GetLEDCount(); - void Apply(); - - void SetLEDEffect - ( - unsigned int led, - int mode, - unsigned int speed, - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - unsigned int led_count; - i2c_smbus_interface* bus; - rgb_fusion_dev_id dev; - - unsigned char led_data[32]; -}; \ No newline at end of file +/*-----------------------------------------*\ +| GigabyteRGBFusion2DRAMController.h | +| | +| Definitions and types for Gigabyte Aorus | +| RGB Fusion 2 DRAM lighting controller | +| | +| Adam Honse (CalcProgrammer1) 6/7/2020 | +\*-----------------------------------------*/ + +#include +#include "i2c_smbus.h" + +#pragma once + +typedef unsigned char rgb_fusion_dev_id; + +enum +{ + RGB_FUSION_2_DRAM_LED_EN_MASK = 0x00, /* LED enable bitfield */ + RGB_FUSION_2_DRAM_IDX_MODE = 0x09, /* Mode index */ + RGB_FUSION_2_DRAM_IDX_BRIGHTNESS = 0x0A, /* Brightness index */ + RGB_FUSION_2_DRAM_IDX_BLUE = 0x0C, /* Blue index */ + RGB_FUSION_2_DRAM_IDX_GREEN = 0x0D, /* Green index */ + RGB_FUSION_2_DRAM_IDX_RED = 0x0E, /* Red index */ +// RGB_FUSION_2_DRAM_TIMER_1_LSB = 0x08, /* Timer 1 LSB. Valid timer values [0-65535] */ +// RGB_FUSION_2_DRAM_TIMER_1_MSB = 0x09, /* Timer 1 MSB. Timer unis are milliseconds */ +// RGB_FUSION_2_DRAM_TIMER_2_LSB = 0x0A, /* Timer 2 LSB */ +// RGB_FUSION_2_DRAM_TIMER_2_MSB = 0x0B, /* Timer 2 MSB */ +// RGB_FUSION_2_DRAM_TIMER_3_LSB = 0x0C, /* Timer 3 LSB */ +// RGB_FUSION_2_DRAM_TIMER_3_MSB = 0x0D, /* Timer 3 MSB */ +// RGB_FUSION_2_DRAM_IDX_OPT_1 = 0x0E, /* Option 1. Use case varies by mode */ +// RGB_FUSION_2_DRAM_IDX_OPT_2 = 0x0F, /* Option 2. Use case varies by mode */ +}; + +enum +{ + RGB_FUSION_2_DRAM_LED_START_ADDR = 0x20, + RGB_FUSION_2_DRAM_APPLY_ADDR = 0x28, +}; + +enum +{ + RGB_FUSION_2_DRAM_ACTION_APPLY = 0x0F, +}; + +enum +{ + RGB_FUSION_2_DRAM_MODE_OFF = 0x00, /* Off mode */ + RGB_FUSION_2_DRAM_MODE_STATIC = 0x01, /* Static mode */ + RGB_FUSION_2_DRAM_MODE_PULSE = 0x02, /* Pulsing mode */ + RGB_FUSION_2_DRAM_MODE_FLASH = 0x03, /* Flashing mode */ + RGB_FUSION_2_DRAM_MODE_DIRECT = 0xFF /* Dummy mode, implements per LED using Pulse */ +}; + +class RGBFusion2DRAMController +{ +public: + RGBFusion2DRAMController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev); + ~RGBFusion2DRAMController(); + + std::string GetDeviceLocation(); + unsigned int GetLEDCount(); + void Apply(); + + void SetLEDEffect + ( + unsigned int led, + int mode, + unsigned int brightness, + unsigned int speed, + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + unsigned int led_count; + i2c_smbus_interface* bus; + rgb_fusion_dev_id dev; + bool direct_initialized; + + unsigned char led_data[32]; +}; diff --git a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp index cad19dd3..5ad3ee7d 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp @@ -1,4 +1,5 @@ #include "Detector.h" +#include "LogManager.h" #include "GigabyteRGBFusion2DRAMController.h" #include "RGBController.h" #include "RGBController_GigabyteRGBFusion2DRAM.h" @@ -23,16 +24,26 @@ bool TestForGigabyteRGBFusion2DRAMController(i2c_smbus_interface* bus, unsigned bool pass = false; int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); - if (res >= 0) + + if(res >= 0) { - pass = true; + bus->i2c_smbus_write_byte_data(address, 0xE1, 0x01); - // res = bus->i2c_smbus_read_byte_data(address, 0xF2); + res = bus->i2c_smbus_read_word_data(address, 0xED); - // if (res != 0xC4) - // { - // pass = false; - // } + LOG_TRACE("[Gigabyte RGB Fusion 2 DRAM] Read from 0xED: 0x%04X", res); + + if(res == 0x3282) + { + res = bus->i2c_smbus_read_word_data(address, 0xEB); + + LOG_TRACE("[Gigabyte RGB Fusion 2 DRAM] Read from 0xEB: 0x%04X", res); + + if(res == 0x0800) + { + pass = true; + } + } } return(pass); @@ -69,5 +80,4 @@ void DetectGigabyteRGBFusion2DRAMControllers(std::vector& } /* DetectGigabyteRGBFusion2DRAMControllers() */ -// This detector is disabled as proper detection isn't implemented -//REGISTER_I2C_DETECTOR("Gigabyte RGB Fusion 2 DRAM", DetectGigabyteRGBFusion2DRAMControllers); +REGISTER_I2C_DETECTOR("Gigabyte RGB Fusion 2 DRAM", DetectGigabyteRGBFusion2DRAMControllers); diff --git a/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp b/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp index f64e58f6..53d3e5e5 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp +++ b/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp @@ -20,11 +20,43 @@ RGBController_RGBFusion2DRAM::RGBController_RGBFusion2DRAM(RGBFusion2DRAMControl type = DEVICE_TYPE_DRAM; + /*-----------------------------------------------------*\ + | Direct mode is achieved through bit of a hack. Use | + | pulse mode but set the configuration such that it does| + | not actually pulse. This allows each LED to be set | + | independently. | + | See this Discord conversation: | + | https://discord.com/channels/699861463375937578/ | + | 699861463887773729/719700736845414453 | + \*-----------------------------------------------------*/ + mode Direct; + Direct.name = "Direct"; + Direct.value = RGB_FUSION_2_DRAM_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 100; + Direct.brightness = 100; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = RGB_FUSION_2_DRAM_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + mode Static; - Static.name = "Static"; - Static.value = 1; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Static.color_mode = MODE_COLORS_PER_LED; + Static.name = "Static"; + Static.value = RGB_FUSION_2_DRAM_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.brightness_min = 0; + Static.brightness_max = 100; + Static.brightness = 100; modes.push_back(Static); SetupZones(); @@ -41,22 +73,25 @@ void RGBController_RGBFusion2DRAM::SetupZones() | Search through all LEDs and create zones for each channel | | type | \*---------------------------------------------------------*/ - zone* new_zone = new zone(); + zone* new_zone = new zone(); // Set zone name to channel name - new_zone->name = "DRAM Zone"; - new_zone->leds_min = 1; - new_zone->leds_max = 1; - new_zone->leds_count = 1; + new_zone->name = "DRAM"; + new_zone->leds_min = controller->GetLEDCount(); + new_zone->leds_max = controller->GetLEDCount(); + new_zone->leds_count = controller->GetLEDCount(); // Push new zone to zones vector zones.push_back(*new_zone); - led* new_led = new led(); - new_led->name = "DRAM LED"; + for(unsigned int led_idx = 0; led_idx < controller->GetLEDCount(); led_idx++) + { + led* new_led = new led(); + new_led->name = "DRAM LED"; - // Push new LED to LEDs vector - leds.push_back(*new_led); + // Push new LED to LEDs vector + leds.push_back(*new_led); + } SetupColors(); } @@ -70,36 +105,60 @@ void RGBController_RGBFusion2DRAM::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_RGBFusion2DRAM::DeviceUpdateLEDs() { - RGBColor color = colors[0]; - unsigned char red = RGBGetRValue(color); - unsigned char grn = RGBGetGValue(color); - unsigned char blu = RGBGetBValue(color); + /*---------------------------------------------------------*\ + | Loop through all LEDs and set effect parameters. Must | + | apply after every effect set | + \*---------------------------------------------------------*/ + for(unsigned int led_idx = 0; led_idx < colors.size(); led_idx++) + { + RGBColor color = 0; - int mode = modes[active_mode].value; - unsigned int speed = modes[active_mode].speed; + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + color = colors[led_idx]; + } + else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + color = modes[active_mode].colors[0]; + } - controller->SetLEDEffect(0, mode, speed, red, grn, blu); + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); - controller->Apply(); + int mode = modes[active_mode].value; + unsigned int speed = modes[active_mode].speed; + unsigned int brightness = modes[active_mode].brightness; + + controller->SetLEDEffect(led_idx, mode, brightness, speed, red, grn, blu); + + /*---------------------------------------------------------*\ + | Only update once unless in direct mode | + \*---------------------------------------------------------*/ + if(modes[active_mode].value != RGB_FUSION_2_DRAM_MODE_DIRECT) + { + break; + } + } } void RGBController_RGBFusion2DRAM::UpdateZoneLEDs(int /*zone*/) { - UpdateLEDs(); + DeviceUpdateLEDs(); } void RGBController_RGBFusion2DRAM::UpdateSingleLED(int /*led*/) { - UpdateLEDs(); + DeviceUpdateLEDs(); } void RGBController_RGBFusion2DRAM::SetCustomMode() { - + active_mode = 0; } void RGBController_RGBFusion2DRAM::DeviceUpdateMode() { - + DeviceUpdateLEDs(); }