Publish curated LumaOps source from c85ee9ef8f1454f5c305398902afbb9e6738de40
Managed validation / full (push) Failing after 8s

This commit is contained in:
Public Source Publisher committed 2026-09-30 00:26:45 +00:00
1 parent 91f8b3e3c1
commit def7920856
2271 files changed
+501225 -501178

No files matched your search

@@ -1,356 +1,356 @@
/*---------------------------------------------------------*\
| KingstonFuryDRAMController.cpp |
| |
| Driver for Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| Milan Cermak (krysmanta) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <vector>
#include "KingstonFuryDRAMController.h"
#include "RGBController.h"
#include "LogManager.h"
KingstonFuryDRAMController::KingstonFuryDRAMController(i2c_smbus_interface* bus, unsigned char base_addr, std::vector<int> slots, std::string dev_name)
{
this->bus = bus;
this->base_addr = base_addr;
this->slots = slots;
this->name = dev_name;
reg_cache.resize(slots.size());
}
std::string KingstonFuryDRAMController::GetDeviceLocation()
{
std::string return_string(bus->device_name);
return_string.append(", addresses [");
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
char addr[5];
snprintf(addr, 5, "0x%02X", base_addr + slots[idx]);
return_string.append(addr);
if(idx < slots.size() - 1)
{
return_string.append(",");
}
else
{
return_string.append("]");
}
}
return("I2C: " + return_string);
}
std::string KingstonFuryDRAMController::GetDeviceName()
{
return(name);
}
unsigned int KingstonFuryDRAMController::GetLEDCount()
{
return(GetLEDPerDIMM() * (unsigned int)slots.size());
}
unsigned int KingstonFuryDRAMController::GetSlotCount()
{
return((unsigned int)slots.size());
}
unsigned char KingstonFuryDRAMController::GetMode()
{
unsigned char mode = 0;
CachedRead(0, FURY_REG_MODE, &mode);
return mode;
}
bool KingstonFuryDRAMController::SmbusRead(int slot_idx, unsigned char reg, unsigned char *val)
{
if(val == NULL)
{
return false;
}
unsigned char device_addr = base_addr + slots[slot_idx];
int res;
for(int retries = 1; retries <= 5; retries++)
{
res = bus->i2c_smbus_read_word_data(device_addr, reg);
if(res >= 0)
{
*val = (res >> 8) & 0xFF;
LOG_DEBUG("[%s] %02X reading register &%02X=%02X; res=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, *val, res);
return true;
}
else
{
std::this_thread::sleep_for(3 * retries * FURY_DELAY);
}
}
return false;
}
bool KingstonFuryDRAMController::SmbusWrite(int slot_idx, unsigned char reg, unsigned char val)
{
unsigned char device_addr = base_addr + slots[slot_idx];
int res;
for(int retries = 1; retries <= 5; retries++)
{
res = bus->i2c_smbus_write_byte_data(device_addr,
reg, val);
LOG_DEBUG("[%s] %02X setting register &%02X=%02X; res=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, val, res);
if(res >= 0)
{
return true;
}
else
{
std::this_thread::sleep_for(3 * retries * FURY_DELAY);
}
}
return false;
}
// returns whether a read was successful
bool KingstonFuryDRAMController::CachedRead(int slot_idx, unsigned char reg, unsigned char *val)
{
if(val == NULL)
{
return false;
}
unsigned char device_addr = base_addr + slots[slot_idx];
if(reg_cache[slot_idx].find(reg) == reg_cache[slot_idx].end())
{
if(SmbusRead(slot_idx, reg, val))
{
reg_cache[slot_idx][reg] = *val;
return true;
}
LOG_ERROR("[%s] %02X failed to get register &%02X",
FURY_CONTROLLER_NAME, device_addr, reg);
return false;
}
else
{
*val = reg_cache[slot_idx][reg];
return true;
}
}
// returns whether a write was actually performed
bool KingstonFuryDRAMController::CachedWrite(int slot_idx, unsigned char reg, unsigned char val)
{
unsigned char device_addr = base_addr + slots[slot_idx];
if(reg_cache[slot_idx].find(reg) == reg_cache[slot_idx].end() ||
reg_cache[slot_idx][reg] != val)
{
if(SmbusWrite(slot_idx, reg, val))
{
reg_cache[slot_idx][reg] = val;
return true;
}
LOG_ERROR("[%s] %02X failed to set register &%02X=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, val);
return false;
}
else
{
LOG_DEBUG("[%s] %02X register already set &%02X=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, val);
return false;
}
}
void KingstonFuryDRAMController::SendPreamble(bool /*synchronize*/)
{
SendBegin();
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
char written_index = 0;
#ifdef FURY_SYNC
if(!synchronize)
{
// some modes set all indices to 0 so that the
// individual sticks don't sync with each other
written_index = 0;
}
else
{
/*--------------------------------------------------------------*\
| The index tells physical location of the RAM slot |
| from the border to the CPU slot. On most motherboards, |
| the address relates to the slot location, |
| but there are exceptions. |
| The official software writes the indices in decreasing order. |
| |
| Hardware effects seem to support only up to 4 sticks. |
| So we give the first 4 and last 4 sticks separate numbering. |
\*--------------------------------------------------------------*/
written_index = idx % 4;
}
#endif
LOG_DEBUG("[%s] %02X writing index %d",
FURY_CONTROLLER_NAME, base_addr + slots[idx],
written_index);
SmbusWrite((int)idx, FURY_REG_INDEX, written_index);
}
// The RGB controller is a bit slow and requires delay;
// however, we can delay once for all of the sticks instead of
// delaying individually for each stick.
std::this_thread::sleep_for(FURY_DELAY);
SendApply();
}
void KingstonFuryDRAMController::SendBegin()
{
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
LOG_DEBUG("[%s] %02X beginning transaction",
FURY_CONTROLLER_NAME, base_addr + slots[idx]);
SmbusWrite((int)idx, FURY_REG_APPLY, FURY_BEGIN_TRNSFER);
}
std::this_thread::sleep_for(FURY_DELAY);
}
void KingstonFuryDRAMController::SendApply()
{
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
LOG_DEBUG("[%s] %02X ending transaction",
FURY_CONTROLLER_NAME, base_addr + slots[idx]);
SmbusWrite((int)idx, FURY_REG_APPLY, FURY_END_TRNSFER);
}
std::this_thread::sleep_for(FURY_DELAY);
}
void KingstonFuryDRAMController::SetMode(unsigned char val)
{
SetRegister(FURY_REG_MODE, val);
}
void KingstonFuryDRAMController::SetNumSlots()
{
if(slots.size() <= 4)
{
SetRegister(FURY_REG_NUM_SLOTS, (unsigned char)slots.size());
}
else
{
// hardware effects seem to only support at most 4 slots;
// if there are >= 4 slots, then essentially the first 4 slots
// run their effects independent of the last 4 slots
SetRegister(FURY_REG_NUM_SLOTS, 4);
}
}
void KingstonFuryDRAMController::SetRegister(int reg, unsigned char val)
{
bool write_occurred = false;
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
write_occurred = CachedWrite((int)idx, reg, val) || write_occurred;
}
if(write_occurred)
{
std::this_thread::sleep_for(FURY_DELAY);
}
}
void KingstonFuryDRAMController::SetRegister(int reg, std::vector<unsigned char> vals)
{
bool write_occurred = false;
if(vals.size() < slots.size())
{
LOG_ERROR("[%s] vector of values has wrong size when setting register &%02X",
FURY_CONTROLLER_NAME, reg);
return;
}
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
write_occurred = CachedWrite((int)idx, reg, vals[idx]) || write_occurred;
}
if(write_occurred)
{
std::this_thread::sleep_for(FURY_DELAY);
}
}
void KingstonFuryDRAMController::SetModeColors(std::vector<RGBColor> colors)
{
if(colors.empty() || (colors.size() > FURY_MAX_MODE_COLORS))
{
return;
}
SetRegister(FURY_REG_NUM_COLORS, (unsigned char)colors.size());
for(std::size_t idx = 0; idx < colors.size(); idx++)
{
RGBColor color = colors[idx];
unsigned char red = RGBGetRValue(color);
unsigned char green = RGBGetGValue(color);
unsigned char blue = RGBGetBValue(color);
int red_idx = FURY_REG_MODE_BASE_RED + (int)idx * 3;
int green_idx = FURY_REG_MODE_BASE_GREEN + (int)idx * 3;
int blue_idx = FURY_REG_MODE_BASE_BLUE + (int)idx * 3;
SetRegister(red_idx, red);
SetRegister(green_idx, green);
SetRegister(blue_idx, blue);
}
}
void KingstonFuryDRAMController::SetLEDColors(std::vector<RGBColor> colors)
{
if(colors.size() != GetLEDCount())
{
return;
}
unsigned int led_per_dimm = GetLEDPerDIMM();
for(unsigned int led_idx = 0; led_idx < led_per_dimm; led_idx++)
{
int red_register = FURY_REG_BASE_RED + 3 * led_idx;
int green_register = FURY_REG_BASE_GREEN + 3 * led_idx;
int blue_register = FURY_REG_BASE_BLUE + 3 * led_idx;
std::vector<unsigned char> reds, greens, blues;
for(std::size_t slot_idx = 0; slot_idx < GetSlotCount(); slot_idx++)
{
RGBColor color = colors[slot_idx * led_per_dimm + led_idx];
unsigned char red = RGBGetRValue(color);
unsigned char green = RGBGetGValue(color);
unsigned char blue = RGBGetBValue(color);
reds.push_back(red);
greens.push_back(green);
blues.push_back(blue);
}
SetRegister(red_register, reds);
SetRegister(blue_register, blues);
SetRegister(green_register, greens);
}
}
unsigned int KingstonFuryDRAMController::GetLEDPerDIMM()
{
if(base_addr == FURY_BASE_ADDR_DDR4)
{
return(FURY_LEDS_PER_DIMM_DDR4);
}
return(FURY_LEDS_PER_DIMM_DDR5);
}
/*---------------------------------------------------------*\
| KingstonFuryDRAMController.cpp |
| |
| Driver for Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| Milan Cermak (krysmanta) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <cstring>
#include <vector>
#include "KingstonFuryDRAMController.h"
#include "RGBController.h"
#include "LogManager.h"
KingstonFuryDRAMController::KingstonFuryDRAMController(i2c_smbus_interface* bus, unsigned char base_addr, std::vector<int> slots, std::string dev_name)
{
this->bus = bus;
this->base_addr = base_addr;
this->slots = slots;
this->name = dev_name;
reg_cache.resize(slots.size());
}
std::string KingstonFuryDRAMController::GetDeviceLocation()
{
std::string return_string(bus->device_name);
return_string.append(", addresses [");
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
char addr[5];
snprintf(addr, 5, "0x%02X", base_addr + slots[idx]);
return_string.append(addr);
if(idx < slots.size() - 1)
{
return_string.append(",");
}
else
{
return_string.append("]");
}
}
return("I2C: " + return_string);
}
std::string KingstonFuryDRAMController::GetDeviceName()
{
return(name);
}
unsigned int KingstonFuryDRAMController::GetLEDCount()
{
return(GetLEDPerDIMM() * (unsigned int)slots.size());
}
unsigned int KingstonFuryDRAMController::GetSlotCount()
{
return((unsigned int)slots.size());
}
unsigned char KingstonFuryDRAMController::GetMode()
{
unsigned char mode = 0;
CachedRead(0, FURY_REG_MODE, &mode);
return mode;
}
bool KingstonFuryDRAMController::SmbusRead(int slot_idx, unsigned char reg, unsigned char *val)
{
if(val == NULL)
{
return false;
}
unsigned char device_addr = base_addr + slots[slot_idx];
int res;
for(int retries = 1; retries <= 5; retries++)
{
res = bus->i2c_smbus_read_word_data(device_addr, reg);
if(res >= 0)
{
*val = (res >> 8) & 0xFF;
LOG_DEBUG("[%s] %02X reading register &%02X=%02X; res=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, *val, res);
return true;
}
else
{
std::this_thread::sleep_for(3 * retries * FURY_DELAY);
}
}
return false;
}
bool KingstonFuryDRAMController::SmbusWrite(int slot_idx, unsigned char reg, unsigned char val)
{
unsigned char device_addr = base_addr + slots[slot_idx];
int res;
for(int retries = 1; retries <= 5; retries++)
{
res = bus->i2c_smbus_write_byte_data(device_addr,
reg, val);
LOG_DEBUG("[%s] %02X setting register &%02X=%02X; res=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, val, res);
if(res >= 0)
{
return true;
}
else
{
std::this_thread::sleep_for(3 * retries * FURY_DELAY);
}
}
return false;
}
// returns whether a read was successful
bool KingstonFuryDRAMController::CachedRead(int slot_idx, unsigned char reg, unsigned char *val)
{
if(val == NULL)
{
return false;
}
unsigned char device_addr = base_addr + slots[slot_idx];
if(reg_cache[slot_idx].find(reg) == reg_cache[slot_idx].end())
{
if(SmbusRead(slot_idx, reg, val))
{
reg_cache[slot_idx][reg] = *val;
return true;
}
LOG_ERROR("[%s] %02X failed to get register &%02X",
FURY_CONTROLLER_NAME, device_addr, reg);
return false;
}
else
{
*val = reg_cache[slot_idx][reg];
return true;
}
}
// returns whether a write was actually performed
bool KingstonFuryDRAMController::CachedWrite(int slot_idx, unsigned char reg, unsigned char val)
{
unsigned char device_addr = base_addr + slots[slot_idx];
if(reg_cache[slot_idx].find(reg) == reg_cache[slot_idx].end() ||
reg_cache[slot_idx][reg] != val)
{
if(SmbusWrite(slot_idx, reg, val))
{
reg_cache[slot_idx][reg] = val;
return true;
}
LOG_ERROR("[%s] %02X failed to set register &%02X=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, val);
return false;
}
else
{
LOG_DEBUG("[%s] %02X register already set &%02X=%02X",
FURY_CONTROLLER_NAME, device_addr, reg, val);
return false;
}
}
void KingstonFuryDRAMController::SendPreamble(bool /*synchronize*/)
{
SendBegin();
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
char written_index = 0;
#ifdef FURY_SYNC
if(!synchronize)
{
// some modes set all indices to 0 so that the
// individual sticks don't sync with each other
written_index = 0;
}
else
{
/*--------------------------------------------------------------*\
| The index tells physical location of the RAM slot |
| from the border to the CPU slot. On most motherboards, |
| the address relates to the slot location, |
| but there are exceptions. |
| The official software writes the indices in decreasing order. |
| |
| Hardware effects seem to support only up to 4 sticks. |
| So we give the first 4 and last 4 sticks separate numbering. |
\*--------------------------------------------------------------*/
written_index = idx % 4;
}
#endif
LOG_DEBUG("[%s] %02X writing index %d",
FURY_CONTROLLER_NAME, base_addr + slots[idx],
written_index);
SmbusWrite((int)idx, FURY_REG_INDEX, written_index);
}
// The RGB controller is a bit slow and requires delay;
// however, we can delay once for all of the sticks instead of
// delaying individually for each stick.
std::this_thread::sleep_for(FURY_DELAY);
SendApply();
}
void KingstonFuryDRAMController::SendBegin()
{
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
LOG_DEBUG("[%s] %02X beginning transaction",
FURY_CONTROLLER_NAME, base_addr + slots[idx]);
SmbusWrite((int)idx, FURY_REG_APPLY, FURY_BEGIN_TRNSFER);
}
std::this_thread::sleep_for(FURY_DELAY);
}
void KingstonFuryDRAMController::SendApply()
{
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
LOG_DEBUG("[%s] %02X ending transaction",
FURY_CONTROLLER_NAME, base_addr + slots[idx]);
SmbusWrite((int)idx, FURY_REG_APPLY, FURY_END_TRNSFER);
}
std::this_thread::sleep_for(FURY_DELAY);
}
void KingstonFuryDRAMController::SetMode(unsigned char val)
{
SetRegister(FURY_REG_MODE, val);
}
void KingstonFuryDRAMController::SetNumSlots()
{
if(slots.size() <= 4)
{
SetRegister(FURY_REG_NUM_SLOTS, (unsigned char)slots.size());
}
else
{
// hardware effects seem to only support at most 4 slots;
// if there are >= 4 slots, then essentially the first 4 slots
// run their effects independent of the last 4 slots
SetRegister(FURY_REG_NUM_SLOTS, 4);
}
}
void KingstonFuryDRAMController::SetRegister(int reg, unsigned char val)
{
bool write_occurred = false;
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
write_occurred = CachedWrite((int)idx, reg, val) || write_occurred;
}
if(write_occurred)
{
std::this_thread::sleep_for(FURY_DELAY);
}
}
void KingstonFuryDRAMController::SetRegister(int reg, std::vector<unsigned char> vals)
{
bool write_occurred = false;
if(vals.size() < slots.size())
{
LOG_ERROR("[%s] vector of values has wrong size when setting register &%02X",
FURY_CONTROLLER_NAME, reg);
return;
}
for(std::size_t idx = 0; idx < slots.size(); idx++)
{
write_occurred = CachedWrite((int)idx, reg, vals[idx]) || write_occurred;
}
if(write_occurred)
{
std::this_thread::sleep_for(FURY_DELAY);
}
}
void KingstonFuryDRAMController::SetModeColors(std::vector<RGBColor> colors)
{
if(colors.empty() || (colors.size() > FURY_MAX_MODE_COLORS))
{
return;
}
SetRegister(FURY_REG_NUM_COLORS, (unsigned char)colors.size());
for(std::size_t idx = 0; idx < colors.size(); idx++)
{
RGBColor color = colors[idx];
unsigned char red = RGBGetRValue(color);
unsigned char green = RGBGetGValue(color);
unsigned char blue = RGBGetBValue(color);
int red_idx = FURY_REG_MODE_BASE_RED + (int)idx * 3;
int green_idx = FURY_REG_MODE_BASE_GREEN + (int)idx * 3;
int blue_idx = FURY_REG_MODE_BASE_BLUE + (int)idx * 3;
SetRegister(red_idx, red);
SetRegister(green_idx, green);
SetRegister(blue_idx, blue);
}
}
void KingstonFuryDRAMController::SetLEDColors(std::vector<RGBColor> colors)
{
if(colors.size() != GetLEDCount())
{
return;
}
unsigned int led_per_dimm = GetLEDPerDIMM();
for(unsigned int led_idx = 0; led_idx < led_per_dimm; led_idx++)
{
int red_register = FURY_REG_BASE_RED + 3 * led_idx;
int green_register = FURY_REG_BASE_GREEN + 3 * led_idx;
int blue_register = FURY_REG_BASE_BLUE + 3 * led_idx;
std::vector<unsigned char> reds, greens, blues;
for(std::size_t slot_idx = 0; slot_idx < GetSlotCount(); slot_idx++)
{
RGBColor color = colors[slot_idx * led_per_dimm + led_idx];
unsigned char red = RGBGetRValue(color);
unsigned char green = RGBGetGValue(color);
unsigned char blue = RGBGetBValue(color);
reds.push_back(red);
greens.push_back(green);
blues.push_back(blue);
}
SetRegister(red_register, reds);
SetRegister(blue_register, blues);
SetRegister(green_register, greens);
}
}
unsigned int KingstonFuryDRAMController::GetLEDPerDIMM()
{
if(base_addr == FURY_BASE_ADDR_DDR4)
{
return(FURY_LEDS_PER_DIMM_DDR4);
}
return(FURY_LEDS_PER_DIMM_DDR5);
}
@@ -1,159 +1,159 @@
/*---------------------------------------------------------*\
| KingstonFuryDRAMController.h |
| |
| Driver for Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| Milan Cermak (krysmanta) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <map>
#include <vector>
#include "i2c_smbus.h"
#include "RGBController.h"
#define FURY_CONTROLLER_NAME "Kingston Fury DDR4/5 DRAM"
#define FURY_BASE_ADDR_DDR4 0x58
#define FURY_BASE_ADDR_DDR5 0x60
#define FURY_DELAY std::chrono::milliseconds(10)
#define FURY_LEDS_PER_DIMM_DDR4 10
#define FURY_LEDS_PER_DIMM_DDR5 12
#define FURY_MAX_MODE_COLORS 10
#define FURY_DEFAULT_BG_COLOR ToRGBColor(16,16,16)
#define FURY_ALT_DIRECTIONS {\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM,\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM,\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM,\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM}
enum
{
FURY_MODEL_BEAST_DDR5 = 0x10,
FURY_MODEL_RENEGADE_DDR5 = 0x11,
FURY_MODEL_BEAST_RGB_WHITE_DDR5 = 0x12,
FURY_MODEL_BEAST2_DDR5 = 0x15,
FURY_MODEL_BEAST_WHITE_DDR4 = 0x21,
FURY_MODEL_BEAST_DDR4 = 0x23,
};
enum
{
FURY_REG_MODEL = 0x06,
FURY_REG_APPLY = 0x08,
FURY_REG_MODE = 0x09,
FURY_REG_INDEX = 0x0B,
FURY_REG_DIRECTION = 0x0C,
FURY_REG_DELAY = 0x0D,
FURY_REG_SPEED = 0x0E,
FURY_REG_DYNAMIC_HOLD_A = 0x12,
FURY_REG_DYNAMIC_HOLD_B = 0x13,
FURY_REG_DYNAMIC_FADE_A = 0x14,
FURY_REG_DYNAMIC_FADE_B = 0x15,
FURY_REG_BREATH_MIN_TO_MID = 0x16,
FURY_REG_BREATH_MID_TO_MAX = 0x17,
FURY_REG_BREATH_MAX_TO_MID = 0x18,
FURY_REG_BREATH_MID_TO_MIN = 0x19,
FURY_REG_BREATH_MIN_HOLD = 0x1A,
FURY_REG_BREATH_MAX_BRIGHTNESS = 0x1B,
FURY_REG_BREATH_MID_BRIGHTNESS = 0x1C,
FURY_REG_BREATH_MIN_BRIGHTNESS = 0x1D,
FURY_REG_BRIGHTNESS = 0x20,
FURY_REG_BG_RED = 0x23,
FURY_REG_BG_GREEN = 0x24,
FURY_REG_BG_BLUE = 0x25,
FURY_REG_LENGTH = 0x26,
FURY_REG_NUM_SLOTS = 0x27,
FURY_REG_NUM_COLORS = 0x30,
FURY_REG_MODE_BASE_RED = 0x31,
FURY_REG_MODE_BASE_GREEN = 0x32,
FURY_REG_MODE_BASE_BLUE = 0x33,
FURY_REG_BASE_RED = 0x50,
FURY_REG_BASE_GREEN = 0x51,
FURY_REG_BASE_BLUE = 0x52,
};
enum
{
FURY_BEGIN_TRNSFER = 0x53,
FURY_END_TRNSFER = 0x44,
};
// Differentiate modes which use the same written value using the upper bytes.
// The lowest order byte is generally the value written to the mode register.
enum
{
FURY_MODE_STATIC = 0x00,
FURY_MODE_RAINBOW = 0x001,
FURY_MODE_SPECTRUM = 0x101,
FURY_MODE_RHYTHM = 0x02,
FURY_MODE_BREATH = 0x03,
FURY_MODE_DYNAMIC = 0x04,
FURY_MODE_SLIDE = 0x005,
FURY_MODE_SLITHER = 0x105,
FURY_MODE_TELEPORT = 0x205,
FURY_MODE_WIND = 0x305,
FURY_MODE_COMET = 0x006,
FURY_MODE_RAIN = 0x106,
FURY_MODE_FIREWORK = 0x206,
FURY_MODE_VOLTAGE = 0x07,
FURY_MODE_COUNTDOWN = 0x08,
FURY_MODE_FLAME = 0x09,
FURY_MODE_TWILIGHT = 0x0A,
FURY_MODE_FURY = 0x0B,
FURY_MODE_DIRECT = 0x10,
FURY_MODE_PRISM = 0x11,
FURY_MODE_BREATH_DIRECT = 0x13,
};
enum
{
FURY_DIR_BOTTOM_TO_TOP = 0x01,
FURY_DIR_TOP_TO_BOTTOM = 0x02,
};
class KingstonFuryDRAMController
{
public:
KingstonFuryDRAMController(i2c_smbus_interface* bus, unsigned char base_addr, std::vector<int> slots, std::string dev_name);
std::string GetDeviceLocation();
std::string GetDeviceName();
unsigned int GetLEDCount();
unsigned int GetLEDPerDIMM();
unsigned int GetSlotCount();
unsigned char GetMode();
void SendPreamble(bool synchronize);
void SendBegin();
void SendApply();
void SetMode(unsigned char val);
void SetNumSlots();
void SetRegister(int reg, unsigned char val);
void SetRegister(int reg, std::vector<unsigned char> vals);
void SetModeColors(std::vector<RGBColor> colors);
void SetLEDColors(std::vector<RGBColor> colors);
private:
bool CachedRead(int slot_idx, unsigned char reg, unsigned char *val);
bool CachedWrite(int slot_idx, unsigned char reg, unsigned char val);
bool SmbusRead(int slot_idx, unsigned char reg, unsigned char *val);
bool SmbusWrite(int slot_idx, unsigned char reg, unsigned char val);
i2c_smbus_interface* bus;
std::vector<int> slots;
unsigned char base_addr;
std::string name;
std::vector<std::map<unsigned char, unsigned char>> reg_cache;
};
/*---------------------------------------------------------*\
| KingstonFuryDRAMController.h |
| |
| Driver for Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| Milan Cermak (krysmanta) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include <map>
#include <vector>
#include "i2c_smbus.h"
#include "RGBController.h"
#define FURY_CONTROLLER_NAME "Kingston Fury DDR4/5 DRAM"
#define FURY_BASE_ADDR_DDR4 0x58
#define FURY_BASE_ADDR_DDR5 0x60
#define FURY_DELAY std::chrono::milliseconds(10)
#define FURY_LEDS_PER_DIMM_DDR4 10
#define FURY_LEDS_PER_DIMM_DDR5 12
#define FURY_MAX_MODE_COLORS 10
#define FURY_DEFAULT_BG_COLOR ToRGBColor(16,16,16)
#define FURY_ALT_DIRECTIONS {\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM,\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM,\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM,\
FURY_DIR_BOTTOM_TO_TOP,\
FURY_DIR_TOP_TO_BOTTOM}
enum
{
FURY_MODEL_BEAST_DDR5 = 0x10,
FURY_MODEL_RENEGADE_DDR5 = 0x11,
FURY_MODEL_BEAST_RGB_WHITE_DDR5 = 0x12,
FURY_MODEL_BEAST2_DDR5 = 0x15,
FURY_MODEL_BEAST_WHITE_DDR4 = 0x21,
FURY_MODEL_BEAST_DDR4 = 0x23,
};
enum
{
FURY_REG_MODEL = 0x06,
FURY_REG_APPLY = 0x08,
FURY_REG_MODE = 0x09,
FURY_REG_INDEX = 0x0B,
FURY_REG_DIRECTION = 0x0C,
FURY_REG_DELAY = 0x0D,
FURY_REG_SPEED = 0x0E,
FURY_REG_DYNAMIC_HOLD_A = 0x12,
FURY_REG_DYNAMIC_HOLD_B = 0x13,
FURY_REG_DYNAMIC_FADE_A = 0x14,
FURY_REG_DYNAMIC_FADE_B = 0x15,
FURY_REG_BREATH_MIN_TO_MID = 0x16,
FURY_REG_BREATH_MID_TO_MAX = 0x17,
FURY_REG_BREATH_MAX_TO_MID = 0x18,
FURY_REG_BREATH_MID_TO_MIN = 0x19,
FURY_REG_BREATH_MIN_HOLD = 0x1A,
FURY_REG_BREATH_MAX_BRIGHTNESS = 0x1B,
FURY_REG_BREATH_MID_BRIGHTNESS = 0x1C,
FURY_REG_BREATH_MIN_BRIGHTNESS = 0x1D,
FURY_REG_BRIGHTNESS = 0x20,
FURY_REG_BG_RED = 0x23,
FURY_REG_BG_GREEN = 0x24,
FURY_REG_BG_BLUE = 0x25,
FURY_REG_LENGTH = 0x26,
FURY_REG_NUM_SLOTS = 0x27,
FURY_REG_NUM_COLORS = 0x30,
FURY_REG_MODE_BASE_RED = 0x31,
FURY_REG_MODE_BASE_GREEN = 0x32,
FURY_REG_MODE_BASE_BLUE = 0x33,
FURY_REG_BASE_RED = 0x50,
FURY_REG_BASE_GREEN = 0x51,
FURY_REG_BASE_BLUE = 0x52,
};
enum
{
FURY_BEGIN_TRNSFER = 0x53,
FURY_END_TRNSFER = 0x44,
};
// Differentiate modes which use the same written value using the upper bytes.
// The lowest order byte is generally the value written to the mode register.
enum
{
FURY_MODE_STATIC = 0x00,
FURY_MODE_RAINBOW = 0x001,
FURY_MODE_SPECTRUM = 0x101,
FURY_MODE_RHYTHM = 0x02,
FURY_MODE_BREATH = 0x03,
FURY_MODE_DYNAMIC = 0x04,
FURY_MODE_SLIDE = 0x005,
FURY_MODE_SLITHER = 0x105,
FURY_MODE_TELEPORT = 0x205,
FURY_MODE_WIND = 0x305,
FURY_MODE_COMET = 0x006,
FURY_MODE_RAIN = 0x106,
FURY_MODE_FIREWORK = 0x206,
FURY_MODE_VOLTAGE = 0x07,
FURY_MODE_COUNTDOWN = 0x08,
FURY_MODE_FLAME = 0x09,
FURY_MODE_TWILIGHT = 0x0A,
FURY_MODE_FURY = 0x0B,
FURY_MODE_DIRECT = 0x10,
FURY_MODE_PRISM = 0x11,
FURY_MODE_BREATH_DIRECT = 0x13,
};
enum
{
FURY_DIR_BOTTOM_TO_TOP = 0x01,
FURY_DIR_TOP_TO_BOTTOM = 0x02,
};
class KingstonFuryDRAMController
{
public:
KingstonFuryDRAMController(i2c_smbus_interface* bus, unsigned char base_addr, std::vector<int> slots, std::string dev_name);
std::string GetDeviceLocation();
std::string GetDeviceName();
unsigned int GetLEDCount();
unsigned int GetLEDPerDIMM();
unsigned int GetSlotCount();
unsigned char GetMode();
void SendPreamble(bool synchronize);
void SendBegin();
void SendApply();
void SetMode(unsigned char val);
void SetNumSlots();
void SetRegister(int reg, unsigned char val);
void SetRegister(int reg, std::vector<unsigned char> vals);
void SetModeColors(std::vector<RGBColor> colors);
void SetLEDColors(std::vector<RGBColor> colors);
private:
bool CachedRead(int slot_idx, unsigned char reg, unsigned char *val);
bool CachedWrite(int slot_idx, unsigned char reg, unsigned char val);
bool SmbusRead(int slot_idx, unsigned char reg, unsigned char *val);
bool SmbusWrite(int slot_idx, unsigned char reg, unsigned char val);
i2c_smbus_interface* bus;
std::vector<int> slots;
unsigned char base_addr;
std::string name;
std::vector<std::map<unsigned char, unsigned char>> reg_cache;
};
@@ -1,201 +1,201 @@
/*---------------------------------------------------------*\
| KingstonFuryDRAMControllerDetect.cpp |
| |
| Detection of Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| Milan Cermak (krysmanta) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "Detector.h"
#include "KingstonFuryDRAMController.h"
#include "LogManager.h"
#include "RGBController_KingstonFuryDRAM.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
using namespace std::chrono_literals;
typedef enum
{
RESULT_PASS = 0,
RESULT_FAIL = 1,
RESULT_ERROR = 2
} TestResult;
bool TestDDR4Models(char code)
{
return (code == FURY_MODEL_BEAST_WHITE_DDR4 ||
code == FURY_MODEL_BEAST_DDR4);
}
bool TestDDR5Models(char code)
{
return (code == FURY_MODEL_BEAST_DDR5 ||
code == FURY_MODEL_BEAST2_DDR5 ||
code == FURY_MODEL_RENEGADE_DDR5 ||
code == FURY_MODEL_BEAST_RGB_WHITE_DDR5);
}
// Checking Fury signature in the RGB address space
TestResult TestForFurySignature(i2c_smbus_interface *bus, unsigned int slot_addr, bool (*modelChecker)(char))
{
bool passed = true;
char test_str[] = "FURY";
int res;
LOG_DEBUG("[%s] looking at 0x%02X",
FURY_CONTROLLER_NAME, slot_addr);
// Start transaction
res = bus->i2c_smbus_write_byte_data(slot_addr, FURY_REG_APPLY, FURY_BEGIN_TRNSFER);
if(res < 0)
{
LOG_DEBUG("[%s] DIMM not present at 0x%02X",
FURY_CONTROLLER_NAME, slot_addr);
return RESULT_ERROR;
}
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] %02X beginning transaction; res=%02X",
FURY_CONTROLLER_NAME, slot_addr, res);
// Read and check the signature
for(int i = 1; i <= 4; i++)
{
for(int retry = 3; retry > 0; retry--)
{
res = bus->i2c_smbus_read_word_data(slot_addr, i);
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] Testing address %02X register %02X, res=%04X",
FURY_CONTROLLER_NAME, slot_addr, i, res);
// retry when there is an error or the returned value is 0xFFFF
if((res >= 0) && (res < 0xFFFF))
{
break;
}
}
if(res < 0)
{
return RESULT_ERROR;
}
char shifted = (res >> 8) & 0xFF;
if(shifted != test_str[i-1])
{
passed = false;
break;
}
}
if(passed)
{
// Get the model code
res = bus->i2c_smbus_read_word_data(slot_addr, FURY_REG_MODEL);
int model_code = res >> 8;
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] Reading model code at address %02X register %02X, res=%02X",
FURY_CONTROLLER_NAME, slot_addr, FURY_REG_MODEL, res);
if(!modelChecker(model_code))
{
LOG_INFO("[%s] Unknown model code 0x%02X", FURY_CONTROLLER_NAME, model_code);
passed = false;
}
}
// Close transaction
res = bus->i2c_smbus_write_byte_data(slot_addr, FURY_REG_APPLY, FURY_END_TRNSFER);
if(res < 0)
{
return RESULT_ERROR;
}
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] %02X ending transaction; res=%02X",
FURY_CONTROLLER_NAME, slot_addr, res);
return passed ? RESULT_PASS : RESULT_FAIL;
}
void DetectKingstonFuryDRAMControllers(i2c_smbus_interface* bus, std::vector<SPDWrapper*> &slots,
uint8_t fury_base_addr, bool (*modelChecker)(char), std::vector<int> &fury_slots)
{
// Are these the Kingston Fury DRAMs
for(SPDWrapper *slot : slots)
{
TestResult result;
int retries = 0;
result = RESULT_ERROR;
while(retries < 3 && result == RESULT_ERROR)
{
result = TestForFurySignature(bus, fury_base_addr + slot->index(), modelChecker);
if(result == RESULT_PASS)
{
break;
}
if(result == RESULT_ERROR)
{
// I/O error - wait for a bit and retry
retries++;
std::this_thread::sleep_for(FURY_DELAY);
}
}
// RAM module successfully detected in the slot 'slot_index'
if(result == RESULT_PASS)
{
LOG_DEBUG("[%s] detected at slot index %d",
FURY_CONTROLLER_NAME, slot->index());
fury_slots.push_back(slot->index());
}
}
}
/******************************************************************************************\
* *
* DetectKingstonFuryDRAMControllers *
* *
* Detect Kingston Fury DDR4/5 DRAM controllers on the enumerated I2C busses. *
* *
\******************************************************************************************/
void DetectKingstonFuryDDR4Controllers(i2c_smbus_interface* bus, std::vector<SPDWrapper*> &slots, const std::string &name)
{
std::vector<int> fury_slots;
DetectKingstonFuryDRAMControllers(bus, slots, FURY_BASE_ADDR_DDR4, TestDDR4Models, fury_slots);
if(!fury_slots.empty())
{
KingstonFuryDRAMController* controller = new KingstonFuryDRAMController(bus, FURY_BASE_ADDR_DDR4, fury_slots, name);
RGBController_KingstonFuryDRAM* rgb_controller = new RGBController_KingstonFuryDRAM(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectKingstonFuryDDR5Controllers(i2c_smbus_interface* bus, std::vector<SPDWrapper*> &slots, const std::string &name)
{
std::vector<int> fury_slots;
DetectKingstonFuryDRAMControllers(bus, slots, FURY_BASE_ADDR_DDR5, TestDDR5Models, fury_slots);
if(!fury_slots.empty())
{
KingstonFuryDRAMController* controller = new KingstonFuryDRAMController(bus, FURY_BASE_ADDR_DDR5, fury_slots, name);
RGBController_KingstonFuryDRAM* rgb_controller = new RGBController_KingstonFuryDRAM(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR4 DRAM", DetectKingstonFuryDDR4Controllers, JEDEC_KINGSTON, SPD_DDR4_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR4 DRAM", DetectKingstonFuryDDR4Controllers, JEDEC_KINGSTON_2, SPD_DDR4_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON, SPD_DDR5_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON_2, SPD_DDR5_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON_3, SPD_DDR5_SDRAM);
/*---------------------------------------------------------*\
| KingstonFuryDRAMControllerDetect.cpp |
| |
| Detection of Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| Milan Cermak (krysmanta) |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <vector>
#include "Detector.h"
#include "KingstonFuryDRAMController.h"
#include "LogManager.h"
#include "RGBController_KingstonFuryDRAM.h"
#include "i2c_smbus.h"
#include "pci_ids.h"
using namespace std::chrono_literals;
typedef enum
{
RESULT_PASS = 0,
RESULT_FAIL = 1,
RESULT_ERROR = 2
} TestResult;
bool TestDDR4Models(char code)
{
return (code == FURY_MODEL_BEAST_WHITE_DDR4 ||
code == FURY_MODEL_BEAST_DDR4);
}
bool TestDDR5Models(char code)
{
return (code == FURY_MODEL_BEAST_DDR5 ||
code == FURY_MODEL_BEAST2_DDR5 ||
code == FURY_MODEL_RENEGADE_DDR5 ||
code == FURY_MODEL_BEAST_RGB_WHITE_DDR5);
}
// Checking Fury signature in the RGB address space
TestResult TestForFurySignature(i2c_smbus_interface *bus, unsigned int slot_addr, bool (*modelChecker)(char))
{
bool passed = true;
char test_str[] = "FURY";
int res;
LOG_DEBUG("[%s] looking at 0x%02X",
FURY_CONTROLLER_NAME, slot_addr);
// Start transaction
res = bus->i2c_smbus_write_byte_data(slot_addr, FURY_REG_APPLY, FURY_BEGIN_TRNSFER);
if(res < 0)
{
LOG_DEBUG("[%s] DIMM not present at 0x%02X",
FURY_CONTROLLER_NAME, slot_addr);
return RESULT_ERROR;
}
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] %02X beginning transaction; res=%02X",
FURY_CONTROLLER_NAME, slot_addr, res);
// Read and check the signature
for(int i = 1; i <= 4; i++)
{
for(int retry = 3; retry > 0; retry--)
{
res = bus->i2c_smbus_read_word_data(slot_addr, i);
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] Testing address %02X register %02X, res=%04X",
FURY_CONTROLLER_NAME, slot_addr, i, res);
// retry when there is an error or the returned value is 0xFFFF
if((res >= 0) && (res < 0xFFFF))
{
break;
}
}
if(res < 0)
{
return RESULT_ERROR;
}
char shifted = (res >> 8) & 0xFF;
if(shifted != test_str[i-1])
{
passed = false;
break;
}
}
if(passed)
{
// Get the model code
res = bus->i2c_smbus_read_word_data(slot_addr, FURY_REG_MODEL);
int model_code = res >> 8;
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] Reading model code at address %02X register %02X, res=%02X",
FURY_CONTROLLER_NAME, slot_addr, FURY_REG_MODEL, res);
if(!modelChecker(model_code))
{
LOG_INFO("[%s] Unknown model code 0x%02X", FURY_CONTROLLER_NAME, model_code);
passed = false;
}
}
// Close transaction
res = bus->i2c_smbus_write_byte_data(slot_addr, FURY_REG_APPLY, FURY_END_TRNSFER);
if(res < 0)
{
return RESULT_ERROR;
}
std::this_thread::sleep_for(FURY_DELAY);
LOG_DEBUG("[%s] %02X ending transaction; res=%02X",
FURY_CONTROLLER_NAME, slot_addr, res);
return passed ? RESULT_PASS : RESULT_FAIL;
}
void DetectKingstonFuryDRAMControllers(i2c_smbus_interface* bus, std::vector<SPDWrapper*> &slots,
uint8_t fury_base_addr, bool (*modelChecker)(char), std::vector<int> &fury_slots)
{
// Are these the Kingston Fury DRAMs
for(SPDWrapper *slot : slots)
{
TestResult result;
int retries = 0;
result = RESULT_ERROR;
while(retries < 3 && result == RESULT_ERROR)
{
result = TestForFurySignature(bus, fury_base_addr + slot->index(), modelChecker);
if(result == RESULT_PASS)
{
break;
}
if(result == RESULT_ERROR)
{
// I/O error - wait for a bit and retry
retries++;
std::this_thread::sleep_for(FURY_DELAY);
}
}
// RAM module successfully detected in the slot 'slot_index'
if(result == RESULT_PASS)
{
LOG_DEBUG("[%s] detected at slot index %d",
FURY_CONTROLLER_NAME, slot->index());
fury_slots.push_back(slot->index());
}
}
}
/******************************************************************************************\
* *
* DetectKingstonFuryDRAMControllers *
* *
* Detect Kingston Fury DDR4/5 DRAM controllers on the enumerated I2C busses. *
* *
\******************************************************************************************/
void DetectKingstonFuryDDR4Controllers(i2c_smbus_interface* bus, std::vector<SPDWrapper*> &slots, const std::string &name)
{
std::vector<int> fury_slots;
DetectKingstonFuryDRAMControllers(bus, slots, FURY_BASE_ADDR_DDR4, TestDDR4Models, fury_slots);
if(!fury_slots.empty())
{
KingstonFuryDRAMController* controller = new KingstonFuryDRAMController(bus, FURY_BASE_ADDR_DDR4, fury_slots, name);
RGBController_KingstonFuryDRAM* rgb_controller = new RGBController_KingstonFuryDRAM(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
void DetectKingstonFuryDDR5Controllers(i2c_smbus_interface* bus, std::vector<SPDWrapper*> &slots, const std::string &name)
{
std::vector<int> fury_slots;
DetectKingstonFuryDRAMControllers(bus, slots, FURY_BASE_ADDR_DDR5, TestDDR5Models, fury_slots);
if(!fury_slots.empty())
{
KingstonFuryDRAMController* controller = new KingstonFuryDRAMController(bus, FURY_BASE_ADDR_DDR5, fury_slots, name);
RGBController_KingstonFuryDRAM* rgb_controller = new RGBController_KingstonFuryDRAM(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR4 DRAM", DetectKingstonFuryDDR4Controllers, JEDEC_KINGSTON, SPD_DDR4_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR4 DRAM", DetectKingstonFuryDDR4Controllers, JEDEC_KINGSTON_2, SPD_DDR4_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON, SPD_DDR5_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON_2, SPD_DDR5_SDRAM);
REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON_3, SPD_DDR5_SDRAM);
File diff suppressed because it is too large. Load diff
@@ -1,36 +1,36 @@
/*---------------------------------------------------------*\
| RGBController_KingstonFuryDRAM.h |
| |
| Driver for Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "KingstonFuryDRAMController.h"
class RGBController_KingstonFuryDRAM : public RGBController
{
public:
RGBController_KingstonFuryDRAM(KingstonFuryDRAMController* controller_ptr);
~RGBController_KingstonFuryDRAM();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
unsigned char GetRealModeValue();
KingstonFuryDRAMController* controller;
};
/*---------------------------------------------------------*\
| RGBController_KingstonFuryDRAM.h |
| |
| Driver for Kingston Fury DDR4/5 RAM modules |
| |
| Geofrey Mon (geofbot) 14 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "KingstonFuryDRAMController.h"
class RGBController_KingstonFuryDRAM : public RGBController
{
public:
RGBController_KingstonFuryDRAM(KingstonFuryDRAMController* controller_ptr);
~RGBController_KingstonFuryDRAM();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
unsigned char GetRealModeValue();
KingstonFuryDRAMController* controller;
};