From 0102fc67d2f936592b725b490911a90a42c15e18 Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Sat, 26 Jun 2021 02:20:30 +0000 Subject: [PATCH] HyperXAlloyOriginsCore Keyboard: added support for Breathing and Swipe modes Commits squashed by Adam Honse --- .../HyperXAlloyOriginsCoreController.cpp | 123 +++++++++++++++++- .../HyperXAlloyOriginsCoreController.h | 39 +++++- .../RGBController_HyperXAlloyOriginsCore.cpp | 57 ++++++-- 3 files changed, 197 insertions(+), 22 deletions(-) diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp index 9dcfa5f8e..81dbb4080 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp @@ -9,7 +9,6 @@ \*------------------------------------------*/ #include "HyperXAlloyOriginsCoreController.h" - #include // Skip these indices in the color output @@ -30,6 +29,17 @@ HyperXAlloyOriginsCoreController::HyperXAlloyOriginsCoreController(hid_device* d sprintf(fw_version_buf, "%.2X.%.2X", (version & 0xFF00) >> 8, version & 0x00FF); firmware_version = fw_version_buf; + isDimming = false; + cur_color = color0 = color1 = 0; + memset(&hsv, 0, sizeof(hsv_t)); + column = speed = direction = 0; + brightness_lower_bound = brightness_upper_bound = 0; + for (int i=0; i<87; i++) + colors_.push_back(0); + memset(buf, 0x00, sizeof(buf)); + color_end = false; + iteration = 0; + data = nullptr; } HyperXAlloyOriginsCoreController::~HyperXAlloyOriginsCoreController() @@ -63,15 +73,77 @@ std::string HyperXAlloyOriginsCoreController::GetFirmwareVersion() return(firmware_version); } -void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector colors) +void HyperXAlloyOriginsCoreController::SetLEDs(std::vector colors, unsigned char mode) { + if (mode == HYPERX_AOC_MODE_SWIPE) + { + if (iteration < (HYPERX_AOC_SPEED_MAX - speed)) + { + iteration++; + return; + } + + if (direction == MODE_DIRECTION_LEFT) + { + if (column == 19) + { + column = 0; + color_end = !color_end; + } + } + else + { + if (column < 0) + { + column = 18; + color_end = !color_end; + } + } + cur_color = color_end ? color1 : color0; + + unsigned int index; + for (int i=0; i<6; i++) + { + index = data[i][column]; + if (index != 0xFFFFFFFF) + colors_[index] = cur_color; + } + direction == MODE_DIRECTION_LEFT ? column++ : column--; + colors = colors_; + iteration = 0; + } + else + { + memset(buf, 0x00, sizeof(buf)); + } + for(unsigned int skip_cnt = 0; skip_cnt < (sizeof(skip_idx) / sizeof(skip_idx[0])); skip_cnt++) { colors.insert(colors.begin() + skip_idx[skip_cnt], 0x00000000); } - unsigned char buf[380]; - memset(buf, 0x00, sizeof(buf)); + if (mode == HYPERX_AOC_MODE_BREATHING) + { + if (isDimming) + { + hsv.value -= (4 * speed); + if (hsv.value <= brightness_lower_bound) + { + hsv.value = 1; + isDimming = false; + } + } + else + { + hsv.value += (4 * speed); + if (hsv.value >= brightness_upper_bound) + { + hsv.value = 255; + isDimming = true; + } + } + color0 = hsv2rgb(&hsv); + } int offset = 0; int rowPos = 0; @@ -84,9 +156,19 @@ void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector color rowPos = 0; } - buf[rowPos + offset] = RGBGetGValue(colors[color_idx]); - buf[rowPos + offset + 16] = RGBGetRValue(colors[color_idx]); - buf[rowPos + offset + 32] = RGBGetBValue(colors[color_idx]); + + if (mode == HYPERX_AOC_MODE_BREATHING) + { + buf[rowPos + offset] = RGBGetGValue(color0); + buf[rowPos + offset + 16] = RGBGetRValue(color0); + buf[rowPos + offset + 32] = RGBGetBValue(color0); + } + else + { + buf[rowPos + offset] = RGBGetGValue(colors[color_idx]); + buf[rowPos + offset + 16] = RGBGetRValue(colors[color_idx]); + buf[rowPos + offset + 32] = RGBGetBValue(colors[color_idx]); + } rowPos++; } @@ -116,3 +198,30 @@ void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector color sentBytes += payloadSize; } } + +void HyperXAlloyOriginsCoreController::SetMode(unsigned char mode_value, unsigned char direction, unsigned char speed, std::vector colors, matrix_map_type* matrix_map) +{ + memset(buf, 0, sizeof(buf)); + switch (mode_value) + { + case HYPERX_AOC_MODE_DIRECT: + break; + case HYPERX_AOC_MODE_BREATHING: + color0 = colors[0]; + rgb2hsv(color0, &hsv); + this->speed = speed; + brightness_lower_bound = 255 % (4 * speed); + brightness_upper_bound = 255 - brightness_lower_bound; + break; + case HYPERX_AOC_MODE_SWIPE: + this->speed = speed; + color0 = colors[0]; + cur_color = color0; + color1 = colors[1]; + this->direction = direction; + column = 0; + data = (unsigned int (*)[19])matrix_map->map; + break; + } +} + diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h index 91ba44f64..c0e606778 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h @@ -9,12 +9,26 @@ \*------------------------------------------*/ #include "RGBController.h" +#include "hsv.h" #include #include #pragma once +enum +{ + HYPERX_AOC_MODE_DIRECT = 0x00, + HYPERX_AOC_MODE_BREATHING = 0x01, + HYPERX_AOC_MODE_SWIPE = 0x02, +}; + +enum +{ + HYPERX_AOC_SPEED_MIN = 0x01, + HYPERX_AOC_SPEED_MAX = 0x07, +}; + class HyperXAlloyOriginsCoreController { public: @@ -25,10 +39,27 @@ public: std::string GetSerialString(); std::string GetFirmwareVersion(); - void SetLEDsDirect(std::vector colors); + void SetLEDs(std::vector colors, unsigned char mode); + void SetMode(unsigned char mode_value, unsigned char direction, unsigned char speed, + std::vector colors, matrix_map_type* matrix_map); private: - hid_device* dev; - std::string location; - std::string firmware_version; + hid_device* dev; + std::string location; + std::string firmware_version; + RGBColor color0; + RGBColor color1; + RGBColor cur_color; + hsv_t hsv; + bool isDimming; + int column; + unsigned char speed; + unsigned char direction; + unsigned char brightness_upper_bound; + unsigned char brightness_lower_bound; + std::vector colors_; + bool color_end; + int iteration; + unsigned int(*data)[19]; + unsigned char buf[380]; }; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp index 5fd509e64..fb64cc5be 100644 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp +++ b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp @@ -159,18 +159,45 @@ RGBController_HyperXAlloyOriginsCore::RGBController_HyperXAlloyOriginsCore(Hyper mode Direct; Direct.name = "Direct"; - Direct.value = 0xFFFF; + Direct.value = HYPERX_AOC_MODE_DIRECT; Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = HYPERX_AOC_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed_min = HYPERX_AOC_SPEED_MIN; + Breathing.speed_max = HYPERX_AOC_SPEED_MAX; + Breathing.speed = 3; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Swipe; + Swipe.name = "Swipe"; + Swipe.value = HYPERX_AOC_MODE_SWIPE; + Swipe.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + Swipe.colors_min = 1; + Swipe.colors_max = 2; + Swipe.color_mode = MODE_COLORS_MODE_SPECIFIC; + Swipe.speed_min = HYPERX_AOC_SPEED_MIN; + Swipe.speed_max = HYPERX_AOC_SPEED_MAX; + Swipe.speed = 3; + Swipe.direction = MODE_DIRECTION_LEFT; + Swipe.colors.resize(2); + modes.push_back(Swipe); + SetupZones(); /*-----------------------------------------------------*\ | The HyperX Origins Core requires a packet within few | | seconds of sending the lighting change in order to | | not revert back into current profile. Start a thread | - | to continuously send color values each 10ms | + | to continuously send color values every 25ms | \*-----------------------------------------------------*/ keepalive_thread_run = 1; keepalive_thread = new std::thread(&RGBController_HyperXAlloyOriginsCore::KeepaliveThread, this); @@ -244,7 +271,8 @@ void RGBController_HyperXAlloyOriginsCore::ResizeZone(int /*zone*/, int /*new_si void RGBController_HyperXAlloyOriginsCore::DeviceUpdateLEDs() { - hyperx->SetLEDsDirect(colors); + last_update_time = std::chrono::steady_clock::now(); + hyperx->SetLEDs(colors, modes[active_mode].value); } void RGBController_HyperXAlloyOriginsCore::UpdateZoneLEDs(int /*zone*/) @@ -259,25 +287,32 @@ void RGBController_HyperXAlloyOriginsCore::UpdateSingleLED(int /*led*/) void RGBController_HyperXAlloyOriginsCore::SetCustomMode() { - + active_mode = 0; } void RGBController_HyperXAlloyOriginsCore::DeviceUpdateMode() { - + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + hyperx->SetMode(modes[active_mode].value, modes[active_mode].direction, + modes[active_mode].speed, modes[active_mode].colors, zones[0].matrix_map); + } + else + { + std::vector temp_colors; + hyperx->SetMode(modes[active_mode].value, modes[active_mode].direction, modes[active_mode].speed, + temp_colors, zones[0].matrix_map); + } } void RGBController_HyperXAlloyOriginsCore::KeepaliveThread() { while(keepalive_thread_run.load()) { - if(active_mode == 0) + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) - { - DeviceUpdateLEDs(); - } + DeviceUpdateLEDs(); } - std::this_thread::sleep_for(10ms); + std::this_thread::sleep_for(25ms); } }