refactors, goodbye post codes...

This commit is contained in:
rawhide kobayashi 2025-03-19 21:39:57 -05:00
parent 0d35fb76e0
commit 2d8a698e7b
No known key found for this signature in database
GPG Key ID: 7789B80FB28A85D4
21 changed files with 1368 additions and 939 deletions

View File

@ -0,0 +1,264 @@
digraph bios
{
//compound = true
node [shape = "box"]
style = dashed
color = red
//rankdir = "LR"
//VALUES ARE DEFAULT VALUES FROM A FRESHLY CLEARED CMOS
//THIS FILE IS NOT TO BE MODIFIED EXCEPT FOR BREAKING BIOS UPDATES
subgraph cluster_headers
{
"EZ Mode"
"Main"
"Ai Tweaker"
subgraph cluster_ai_tweaker
{
"Ai Overclock Tuner"
"DOCP"
"BCLK Frequency"
"Memory Frequency"
"FCLK Frequency"
"Core tunings Configuration for gaming"
"Core Performance Boost"
"CPU Core Ratio"
"CPU Core Ratio (Per CCX)"
"Turbo Game Mode"
"Gaming Adaptive CCD Parker"
"AI Cache Boost"
"DRAM Timing Control"
// "Precision Boost Overdrive" skip over this, not using it
"DIGI + VRM"
subgraph cluster_vrm
{
"DIGI + VRM (Enter subfolder)"
"VRM Initialization Check"
"Voltage training" [option_type = "list" value = "Auto" options = "Auto,Disabled,Enabled" traversal_key = "ArrowDown"]
"CPU Load-line Calibration" [option_type = "list" value = "Auto" options = "Auto,Level 1,Level 2,Level 3,Level 4,Level 5,Level 6,Level 7,Level 8" traversal_key = "ArrowDown"]
"CPU Current Capability" [option_type = "list" value = "Auto" options = "Auto,100%,110%,120%,130%,140%" traversal_key = "ArrowDown"]
"CPU VRM Switching Frequency"
"Fixed CPU VRM Switching Frequency(KHz)" [option_type = "field" value = "600"]
"CPU Power Duty Control"
"CPU Power Phase Control" [option_type = "list" value = "Auto" options = "Auto,Standard,Optimized,Extreme,Manual" traversal_key = "ArrowDown"]
"VDDSOC Current Capability" [option_type = "list" value = "Auto" options = "Auto,100%,110%,120%,130%,140%" traversal_key = "ArrowDown"]
"VDDSOC Switching Frequency"
"Fixed VDDSOC Switching Frequency(KHz)" [option_type = "field" value = "600"]
"VDDSOC Power Duty Control"
"VDDSOC Power Phase Control" [option_type = "list" value = "Auto" options = "Auto,Standard,Optimized,Extreme,Manual" traversal_key = "ArrowDown"]
}
"Performance Bias"
"Tweaker's Paradise"
"Core Flex"
"AI Features"
"CPU Core Voltage"
"CPU SOC Voltage"
"VDDSOC Voltage Override" [option_type = "field" value = "Auto"]
"CPU VDDIO/MC Voltage"
"Misc Voltage"
"VDDP Voltage"
"High DRAM Voltage Mode"
"DRAM VDD Voltage"
"DRAM VDDQ Voltage"
"VDDG CCD Voltage"
"VDDG IOD Voltage"
"Advanced Memory Voltages"
}
"Advanced"
subgraph cluster_advanced
{
"Trusted Computing"
// unimportant
// "AMD fTPM Configuration"
// "UEFI Variable Protection"
// "CPU Configuration"
// "PCI Subsystem Settings"
// "USB Configuration"
// "Network Stack Configuration"
// "NVMe Configuration"
// "HDD/SSD SMART Information"
// "SATA Configuration"
// "APM Configuration"
"Onboard Devices Configuration"
"NB Configuration"
subgraph cluster_nb_config
{
"NB Configuration (Enter subfolder)"
"Primary Video Device"
"Integrated Graphics" [option_type = "list" value = "Auto" options = "Auto,Force,Disabled" traversal_key = "ArrowUp"]
"UMA Frame Buffer Size"
}
"AMD CBS"
subgraph cluster_amd_cbs
{
// why in the name of all that is unholy is this list in reverse?!
// this is probably the only option that matters
"ACPI SRAT L3 Cache As NUMA Domain" [option_type = "list" value = "Auto" options = "Auto,Enabled,Disabled" traversal_key = "ArrowUp"]
}
"AMD PBS"
"AMD Overclocking"
subgraph cluster_amd_overclocking
{
"AMD Overclocking Subfolder"
"Manual CPU Overclocking"
"DDR and Infinity Fabric Frequency/Timings"
"Precision Boost Overdrive"
subgraph cluster_pbo
{
"Precision Boost Overdrive (Enter subfolder)"
"Precision Boost Overdrive (Setting)"
"PBO Limits" [option_type = "list" value = "Auto" options = "Auto,Disable,Motherboard,Manual" traversal_key = "ArrowDown"]
"Precision Boost Overdrive Scalar Ctrl"
"Precision Boost Overdrive Scalar" [option_type = "list" value = "1X" options = "1X,2X,3X,4X,5X,6X,7X,8X,9X,10X" traversal_key = "ArrowDown"]
"CPU Boost Clock Override"
"Max CPU Boost Clock Override(+)" [option_type = "field" value = "25"]
"Platform Thermal Throttle Ctrl"
"GFX Curve Optimizer"
"Curve Optimizer"
"Curve Shaper"
}
}
}
"Monitor"
"Boot"
"Tool"
subgraph cluster_tool
{
// nothing else here matters
"Download & Install ASUS DriverHub app" [option_type = "list" value = "Enabled" options = "Enabled,Disabled" traversal_key = "ArrowUp"]
}
"Exit"
}
"Monitor"
"Boot"
"Exit"
"Save Changes and Exit"
"EZ Mode" -> "Main" [keypath = "F7"]
"Main" -> "Ai Tweaker" [keypath = "ArrowRight"]
"Ai Tweaker" -> "Advanced" [keypath = "ArrowRight"]
"Advanced" -> "Tool" [keypath = "ArrowRight"]
"Tool" -> "Monitor" [keypath = "ArrowRight"]
"Monitor" -> "Boot" [keypath = "ArrowRight"]
"Boot" -> "Exit" [keypath = "ArrowRight"]
"Exit" -> "Boot" [keypath = "ArrowLeft"]
"Boot" -> "Monitor" [keypath = "ArrowLeft"]
"Monitor" -> "Tool" [keypath = "ArrowLeft"]
"Tool" -> "Advanced" [keypath = "ArrowLeft"]
"Advanced" -> "Ai Tweaker" [keypath = "ArrowLeft"]
"Ai Tweaker" -> "Ai Overclock Tuner" [keypath = "Home" initial_keypath = "Home,Enter,ArrowDown,ArrowDown,ArrowDown,ArrowDown,Enter" visited = "false"]
"Ai Overclock Tuner" -> "DOCP" [keypath = "ArrowDown"]
"DOCP" -> "BCLK Frequency" [keypath = "ArrowDown"]
"BCLK Frequency" -> "Memory Frequency" [keypath = "ArrowDown"]
"Memory Frequency" -> "FCLK Frequency" [keypath = "ArrowDown"]
"FCLK Frequency" -> "Core tunings Configuration for gaming" [keypath = "ArrowDown"]
"Core tunings Configuration for gaming" -> "Core Performance Boost" [keypath = "ArrowDown"]
"Core Performance Boost" -> "CPU Core Ratio" [keypath = "ArrowDown"]
"CPU Core Ratio" -> "CPU Core Ratio (Per CCX)" [keypath = "ArrowDown"]
"CPU Core Ratio (Per CCX)" -> "Turbo Game Mode" [keypath = "ArrowDown"]
"Turbo Game Mode" -> "Gaming Adaptive CCD Parker" [keypath = "ArrowDown"]
"Gaming Adaptive CCD Parker" -> "AI Cache Boost" [keypath = "ArrowDown"]
"AI Cache Boost" -> "DRAM Timing Control" [keypath = "ArrowDown"]
// skip over PBO menu here, it's bad
"DRAM Timing Control" -> "DIGI + VRM" [keypath = "ArrowDown,ArrowDown"]
"DIGI + VRM" -> "DIGI + VRM (Enter subfolder)" [keypath = "Enter,Home"]
"DIGI + VRM (Enter subfolder)" -> "VRM Initialization Check" [keypath = "ArrowDown"]
"VRM Initialization Check" -> "Voltage training" [keypath = "ArrowDown"]
"Voltage training" -> "CPU Load-line Calibration" [keypath = "ArrowDown"]
"CPU Load-line Calibration" -> "CPU Current Capability" [keypath = "ArrowDown"]
"CPU Current Capability" -> "CPU VRM Switching Frequency" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"CPU VRM Switching Frequency" -> "Fixed CPU VRM Switching Frequency(KHz)" [keypath = "ArrowDown"]
"Fixed CPU VRM Switching Frequency(KHz)" -> "CPU Power Duty Control" [keypath = "ArrowDown"]
"CPU Power Duty Control" -> "CPU Power Phase Control" [keypath = "ArrowDown"]
"CPU Power Phase Control" -> "VDDSOC Current Capability" [keypath = "ArrowDown"]
"VDDSOC Current Capability" -> "VDDSOC Switching Frequency" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"VDDSOC Switching Frequency" -> "Fixed VDDSOC Switching Frequency(KHz)" [keypath = "ArrowDown"]
"Fixed VDDSOC Switching Frequency(KHz)" -> "VDDSOC Power Duty Control" [keypath = "ArrowDown"]
"VDDSOC Power Duty Control" -> "VDDSOC Power Phase Control" [keypath = "ArrowDown"]
"DIGI + VRM (Enter subfolder)", "VRM Initialization Check", "Voltage training", "CPU Load-line Calibration", "CPU Current Capability", "CPU VRM Switching Frequency", "CPU Power Duty Control", "CPU Power Phase Control", "VDDSOC Current Capability", "VDDSOC Switching Frequency", "VDDSOC Power Duty Control", "VDDSOC Power Phase Control" -> "DIGI + VRM" [keypath = "Escape"]
"DIGI + VRM" -> "Performance Bias" [keypath = "ArrowDown"]
"Performance Bias" -> "Tweaker's Paradise" [keypath = "ArrowDown"]
"Tweaker's Paradise" -> "Core Flex" [keypath = "ArrowDown"]
"Core Flex" -> "AI Features" [keypath = "ArrowDown"]
"AI Features" -> "CPU Core Voltage" [keypath = "ArrowDown"]
"CPU Core Voltage" -> "CPU SOC Voltage" [keypath = "ArrowDown", initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"CPU SOC Voltage" -> "VDDSOC Voltage Override" [keypath = "ArrowDown"]
"VDDSOC Voltage Override" -> "CPU VDDIO/MC Voltage" [keypath = "ArrowDown"]
"CPU VDDIO/MC Voltage" -> "Misc Voltage" [keypath = "ArrowDown"]
"Misc Voltage" -> "VDDP Voltage" [keypath = "ArrowDown"]
"VDDP Voltage" -> "High DRAM Voltage Mode" [keypath = "ArrowDown"]
"High DRAM Voltage Mode" -> "DRAM VDD Voltage" [keypath = "ArrowDown"]
"DRAM VDD Voltage" -> "DRAM VDDQ Voltage" [keypath = "ArrowDown"]
"DRAM VDDQ Voltage" -> "VDDG CCD Voltage" [keypath = "ArrowDown"]
"VDDG CCD Voltage" -> "VDDG IOD Voltage" [keypath = "ArrowDown"]
"VDDG IOD Voltage" -> "Advanced Memory Voltages" [keypath = "ArrowDown"]
"Ai Overclock Tuner", "DOCP", "BCLK Frequency", "Memory Frequency", "FCLK Frequency", "Core tunings Configuration for gaming", "Core Performance Boost", "CPU Core Ratio", "CPU Core Ratio (Per CCX)", "Turbo Game Mode", "Gaming Adaptive CCD Parker", "AI Cache Boost", "DRAM Timing Control", "DIGI + VRM", "Performance Bias", "Tweaker's Paradise", "Core Flex", "AI Features", "CPU Core Voltage", "CPU SOC Voltage", "CPU VDDIO/MC Voltage", "Misc Voltage", "VDDP Voltage", "High DRAM Voltage Mode", "DRAM VDD Voltage", "DRAM VDDQ Voltage", "VDDG CCD Voltage", "VDDG IOD Voltage", "Advanced Memory Voltages" -> "Ai Tweaker" [keypath = "Home"]
"Advanced" -> "Trusted Computing" [keypath = "Home"]
"Trusted Computing" -> "Onboard Devices Configuration" [keypath = "ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown"]
"Onboard Devices Configuration" -> "NB Configuration" [keypath = "ArrowDown"]
"NB Configuration" -> "NB Configuration (Enter subfolder)" [keypath = "Enter,Home"]
"NB Configuration (Enter subfolder)" -> "Primary Video Device" [keypath = "ArrowDown"]
"Primary Video Device" -> "Integrated Graphics" [keypath = "ArrowDown"]
"Integrated Graphics" -> "UMA Frame Buffer Size" [keypath = "ArrowDown"]
"NB Configuration (Enter subfolder)", "Primary Video Device", "Integrated Graphics", "UMA Frame Buffer Size" -> "NB Configuration" [keypath = "Escape"]
"NB Configuration" -> "AMD CBS" [keypath = "ArrowDown"]
"AMD CBS" -> "AMD PBS" [keypath = "ArrowDown"]
"AMD PBS" -> "AMD Overclocking" [keypath = "ArrowDown"]
"Onboard Devices Configuration", "NB Configuration", "AMD CBS", "AMD PBS", "Trusted Computing" -> "Advanced" [keypath = "Home"]
"AMD CBS" -> "ACPI SRAT L3 Cache As NUMA Domain" [keypath = "Enter,Home,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,Enter,Home,ArrowDown,ArrowDown,Enter,Home,ArrowDown"]
"ACPI SRAT L3 Cache As NUMA Domain" -> "AMD CBS" [keypath = "Escape,Escape,Escape"]
"AMD Overclocking" -> "AMD Overclocking Subfolder" [keypath = "Enter,Home,ArrowDown,Enter,Home"]
"AMD Overclocking Subfolder" -> "Manual CPU Overclocking" [keypath = "ArrowDown"]
"Manual CPU Overclocking" -> "DDR and Infinity Fabric Frequency/Timings" [keypath = "ArrowDown"]
"DDR and Infinity Fabric Frequency/Timings" -> "Precision Boost Overdrive" [keypath = "ArrowDown"]
"AMD Overclocking Subfolder", "Manual CPU Overclocking", "DDR and Infinity Fabric Frequency/Timings", "Precision Boost Overdrive" -> "AMD PBS" [keypath = "Escape,Escape"]
"Precision Boost Overdrive" -> "Precision Boost Overdrive (Enter subfolder)" [keypath = "Enter"]
"Precision Boost Overdrive (Enter subfolder)" -> "Precision Boost Overdrive (Setting)" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,ArrowDown,ArrowDown,Enter" visited = "false"]
"Precision Boost Overdrive (Setting)" -> "PBO Limits" [keypath = "ArrowDown"]
"PBO Limits" -> "Precision Boost Overdrive Scalar Ctrl" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"Precision Boost Overdrive Scalar Ctrl" -> "Precision Boost Overdrive Scalar" [keypath = "ArrowDown"]
"Precision Boost Overdrive Scalar" -> "CPU Boost Clock Override" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"CPU Boost Clock Override" -> "Max CPU Boost Clock Override(+)" [keypath = "ArrowDown"]
"Max CPU Boost Clock Override(+)" -> "Platform Thermal Throttle Ctrl" [keypath = "ArrowDown"]
"Platform Thermal Throttle Ctrl" -> "GFX Curve Optimizer" [keypath = "ArrowDown"]
"GFX Curve Optimizer" -> "Curve Optimizer" [keypath = "ArrowDown"]
"Curve Optimizer" -> "Curve Shaper" [keypath = "ArrowDown"]
"Precision Boost Overdrive", "PBO Limits", "Precision Boost Overdrive Scalar Ctrl", "CPU Boost Clock Override", "Platform Thermal Throttle Ctrl" -> "Precision Boost Overdrive (Enter subfolder)" [keypath = "Escape"]
"Precision Boost Overdrive (Enter subfolder)" -> "AMD Overclocking" [keypath = "Escape,Escape"]
"Tool" -> "Download & Install ASUS DriverHub app" [keypath = "Home,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,Enter,Home,ArrowDown"]
"Download & Install ASUS DriverHub app" -> "Tool" [keypath = "Escape"]
"Exit" -> "Save Changes and Exit" [keypath = "Enter,Enter"]
}

View File

@ -9,37 +9,40 @@ void loop() {}
#include <Arduino.h> #include <Arduino.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <USB.h> #include <USB.h>
#include <USBHID.h>
#include <USBHIDMouse.h> #include <USBHIDMouse.h>
#include <USBHIDKeyboard.h> #include <USBHIDKeyboard.h>
#include <USBHIDSystemControl.h> #include <USBHIDSystemControl.h>
USBHID HID;
USBHIDAbsoluteMouse Mouse; USBHIDAbsoluteMouse Mouse;
USBHIDKeyboard Keyboard; USBHIDKeyboard Keyboard;
HardwareSerial &host_serial = Serial; HardwareSerial &host_serial = Serial;
HardwareSerial &mobo_serial = Serial1; // HardwareSerial &mobo_serial = Serial1;
JsonDocument mkb_input; JsonDocument mkb_input;
JsonDocument post_codes; // JsonDocument post_codes;
JsonDocument power_status; JsonDocument power_status;
// put function declarations here: // put function declarations here:
int myFunction(int, int); int myFunction(int, int);
const int8_t pwr_button = 3; const int8_t pwr_button = 46;
const int8_t cmos_button = 46; const int8_t cmos_button = 3;
const int8_t pwr_detect = 8; // const int8_t pwr_detect = 8;
void setup() void setup()
{ {
host_serial.begin(115200); host_serial.begin(115200);
mobo_serial.begin(115200, SERIAL_8N1, 18); // mobo_serial.begin(115200, SERIAL_8N1, 18);
HID.begin();
Mouse.begin(); Mouse.begin();
Keyboard.begin(); Keyboard.begin();
USB.begin(); USB.begin();
pinMode(pwr_button, OUTPUT); pinMode(pwr_button, OUTPUT);
pinMode(cmos_button, OUTPUT); pinMode(cmos_button, OUTPUT);
pinMode(pwr_detect, INPUT); // pinMode(pwr_detect, INPUT);
} }
void loop() void loop()
@ -51,7 +54,7 @@ void loop()
if (cur_loop_timestamp - check_power_status_timestamp >= 100000) if (cur_loop_timestamp - check_power_status_timestamp >= 100000)
{ {
if (analogRead(pwr_detect) > 1000) /* if (analogRead(pwr_detect) > 1000)
{ {
power_status["pwr"] = true; power_status["pwr"] = true;
} }
@ -59,6 +62,16 @@ void loop()
else else
{ {
power_status["pwr"] = false; power_status["pwr"] = false;
} */
if (HID.ready())
{
power_status["usb"] = true;
}
else
{
power_status["usb"] = false;
} }
serializeJson(power_status, host_serial); serializeJson(power_status, host_serial);
@ -66,12 +79,12 @@ void loop()
check_power_status_timestamp = esp_timer_get_time(); check_power_status_timestamp = esp_timer_get_time();
} }
while (mobo_serial.available()) /* while (mobo_serial.available())
{ {
post_codes["post_code"] = mobo_serial.read(); post_codes["post_code"] = mobo_serial.read();
serializeJson(post_codes, host_serial); serializeJson(post_codes, host_serial);
host_serial.write('\n'); host_serial.write('\n');
} } */
if (host_serial.available()) if (host_serial.available())
{ {

View File

@ -1,254 +1,268 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.1.2 (0) <!-- Generated by graphviz version 12.2.1 (0)
--> -->
<!-- Pages: 1 --> <!-- Pages: 1 -->
<svg width="1856pt" height="543pt" <svg width="1745pt" height="637pt"
viewBox="0.00 0.00 1856.00 543.32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> viewBox="0.00 0.00 1744.50 636.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 539.32)"> <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 632.5)">
<polygon fill="white" stroke="none" points="-4,4 -4,-539.32 1852,-539.32 1852,4 -4,4"/> <polygon fill="white" stroke="none" points="-4,4 -4,-632.5 1740.5,-632.5 1740.5,4 -4,4"/>
<text text-anchor="middle" x="924" y="-4.95" font-family="Times,serif" font-size="14.00">State Machine</text> <text text-anchor="middle" x="868.25" y="-4.95" font-family="Times,serif" font-size="14.00">State Machine</text>
<!-- PoweredOff --> <!-- PoweredOff -->
<g id="node1" class="node"> <g id="node1" class="node">
<title>PoweredOff</title> <title>PoweredOff</title>
<path fill="white" stroke="black" d="M422.38,-349.07C422.38,-349.07 365.12,-349.07 365.12,-349.07 359.12,-349.07 353.12,-343.07 353.12,-337.07 353.12,-337.07 353.12,-325.07 353.12,-325.07 353.12,-319.07 359.12,-313.07 365.12,-313.07 365.12,-313.07 422.38,-313.07 422.38,-313.07 428.38,-313.07 434.38,-319.07 434.38,-325.07 434.38,-325.07 434.38,-337.07 434.38,-337.07 434.38,-343.07 428.38,-349.07 422.38,-349.07"/> <path fill="white" stroke="black" d="M69.25,-258.25C69.25,-258.25 12,-258.25 12,-258.25 6,-258.25 0,-252.25 0,-246.25 0,-246.25 0,-234.25 0,-234.25 0,-228.25 6,-222.25 12,-222.25 12,-222.25 69.25,-222.25 69.25,-222.25 75.25,-222.25 81.25,-228.25 81.25,-234.25 81.25,-234.25 81.25,-246.25 81.25,-246.25 81.25,-252.25 75.25,-258.25 69.25,-258.25"/>
<text text-anchor="start" x="361.12" y="-324.89" font-family="Times,serif" font-size="14.00">PoweredOff</text> <text text-anchor="start" x="8" y="-234.07" font-family="Times,serif" font-size="14.00">PoweredOff</text>
</g> </g>
<!-- POST --> <!-- POST -->
<g id="node2" class="node"> <g id="node2" class="node">
<title>POST</title> <title>POST</title>
<path fill="white" stroke="black" d="M676.88,-296.07C676.88,-296.07 646.88,-296.07 646.88,-296.07 640.88,-296.07 634.88,-290.07 634.88,-284.07 634.88,-284.07 634.88,-272.07 634.88,-272.07 634.88,-266.07 640.88,-260.07 646.88,-260.07 646.88,-260.07 676.88,-260.07 676.88,-260.07 682.88,-260.07 688.88,-266.07 688.88,-272.07 688.88,-272.07 688.88,-284.07 688.88,-284.07 688.88,-290.07 682.88,-296.07 676.88,-296.07"/> <path fill="white" stroke="black" d="M268,-295.25C268,-295.25 238,-295.25 238,-295.25 232,-295.25 226,-289.25 226,-283.25 226,-283.25 226,-271.25 226,-271.25 226,-265.25 232,-259.25 238,-259.25 238,-259.25 268,-259.25 268,-259.25 274,-259.25 280,-265.25 280,-271.25 280,-271.25 280,-283.25 280,-283.25 280,-289.25 274,-295.25 268,-295.25"/>
<text text-anchor="start" x="642.88" y="-271.89" font-family="Times,serif" font-size="14.00">POST</text> <text text-anchor="start" x="234" y="-271.07" font-family="Times,serif" font-size="14.00">POST</text>
</g> </g>
<!-- PoweredOff&#45;&gt;POST --> <!-- PoweredOff&#45;&gt;POST -->
<g id="edge1" class="edge"> <g id="edge1" class="edge">
<title>PoweredOff&#45;&gt;POST</title> <title>PoweredOff&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M422.41,-312.63C433.95,-305.86 447.77,-298.86 461.25,-294.82 515.83,-278.45 582.3,-276.17 623.1,-276.65"/> <path fill="none" stroke="black" d="M81.48,-251.24C87.41,-252.7 93.47,-254.09 99.25,-255.25 138.26,-263.11 183.42,-269.26 214.46,-273.03"/>
<polygon fill="black" stroke="black" points="622.82,-280.15 632.88,-276.84 622.95,-273.15 622.82,-280.15"/> <polygon fill="black" stroke="black" points="213.78,-276.47 224.13,-274.18 214.61,-269.52 213.78,-276.47"/>
<text text-anchor="middle" x="502.88" y="-295.77" font-family="Times,serif" font-size="14.00">power_on</text> <text text-anchor="middle" x="140.88" y="-269.8" font-family="Times,serif" font-size="14.00">power_on</text>
</g> </g>
<!-- POST&#45;&gt;PoweredOff --> <!-- POST&#45;&gt;PoweredOff -->
<g id="edge14" class="edge"> <g id="edge15" class="edge">
<title>POST&#45;&gt;PoweredOff</title> <title>POST&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M634.73,-285.95C611.28,-292.8 575.83,-302.62 544.5,-309.07 511.9,-315.78 474.89,-321.24 445.82,-325.04"/> <path fill="none" stroke="black" d="M227.68,-258.92C214.94,-250.46 198.66,-241.34 182.5,-237 153.45,-229.2 119.82,-229.64 92.7,-232.2"/>
<polygon fill="black" stroke="black" points="445.67,-321.53 436.2,-326.27 446.56,-328.47 445.67,-321.53"/> <polygon fill="black" stroke="black" points="92.58,-228.7 83.01,-233.25 93.33,-235.66 92.58,-228.7"/>
<text text-anchor="middle" x="502.88" y="-323.63" font-family="Times,serif" font-size="14.00">hard_shutdown</text> <text text-anchor="middle" x="140.88" y="-237.95" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g> </g>
<!-- EnterBIOS --> <!-- EnterBIOS -->
<g id="node3" class="node"> <g id="node3" class="node">
<title>EnterBIOS</title> <title>EnterBIOS</title>
<path fill="white" stroke="black" d="M975.12,-325.07C975.12,-325.07 923.12,-325.07 923.12,-325.07 917.12,-325.07 911.12,-319.07 911.12,-313.07 911.12,-313.07 911.12,-301.07 911.12,-301.07 911.12,-295.07 917.12,-289.07 923.12,-289.07 923.12,-289.07 975.12,-289.07 975.12,-289.07 981.12,-289.07 987.12,-295.07 987.12,-301.07 987.12,-301.07 987.12,-313.07 987.12,-313.07 987.12,-319.07 981.12,-325.07 975.12,-325.07"/> <path fill="white" stroke="black" d="M594.38,-408.25C594.38,-408.25 542.38,-408.25 542.38,-408.25 536.38,-408.25 530.38,-402.25 530.38,-396.25 530.38,-396.25 530.38,-384.25 530.38,-384.25 530.38,-378.25 536.38,-372.25 542.38,-372.25 542.38,-372.25 594.38,-372.25 594.38,-372.25 600.38,-372.25 606.38,-378.25 606.38,-384.25 606.38,-384.25 606.38,-396.25 606.38,-396.25 606.38,-402.25 600.38,-408.25 594.38,-408.25"/>
<text text-anchor="start" x="919.12" y="-300.89" font-family="Times,serif" font-size="14.00">EnterBIOS</text> <text text-anchor="start" x="538.38" y="-384.07" font-family="Times,serif" font-size="14.00">EnterBIOS</text>
</g> </g>
<!-- POST&#45;&gt;EnterBIOS --> <!-- POST&#45;&gt;EnterBIOS -->
<g id="edge15" class="edge"> <g id="edge16" class="edge">
<title>POST&#45;&gt;EnterBIOS</title> <title>POST&#45;&gt;EnterBIOS</title>
<path fill="none" stroke="black" d="M689.2,-280.75C737.01,-285.61 838.78,-295.95 899.52,-302.13"/> <path fill="none" stroke="black" d="M264.12,-295.51C275.77,-314.61 296.77,-343.79 323.5,-358.25 384.82,-391.44 467.13,-395.31 518.71,-393.76"/>
<polygon fill="black" stroke="black" points="898.92,-305.58 909.22,-303.11 899.62,-298.62 898.92,-305.58"/> <polygon fill="black" stroke="black" points="518.81,-397.26 528.66,-393.37 518.53,-390.26 518.81,-397.26"/>
<text text-anchor="middle" x="828.38" y="-300.24" font-family="Times,serif" font-size="14.00">enter_bios</text> <text text-anchor="middle" x="410.12" y="-394.95" font-family="Times,serif" font-size="14.00">enter_bios</text>
</g>
<!-- IdleWaitingForInput -->
<g id="node5" class="node">
<title>IdleWaitingForInput</title>
<path fill="darksalmon" stroke="red" d="M865.5,-304.25C865.5,-304.25 762.5,-304.25 762.5,-304.25 756.5,-304.25 750.5,-298.25 750.5,-292.25 750.5,-292.25 750.5,-280.25 750.5,-280.25 750.5,-274.25 756.5,-268.25 762.5,-268.25 762.5,-268.25 865.5,-268.25 865.5,-268.25 871.5,-268.25 877.5,-274.25 877.5,-280.25 877.5,-280.25 877.5,-292.25 877.5,-292.25 877.5,-298.25 871.5,-304.25 865.5,-304.25"/>
<path fill="none" stroke="red" d="M869.5,-308.25C869.5,-308.25 758.5,-308.25 758.5,-308.25 752.5,-308.25 746.5,-302.25 746.5,-296.25 746.5,-296.25 746.5,-276.25 746.5,-276.25 746.5,-270.25 752.5,-264.25 758.5,-264.25 758.5,-264.25 869.5,-264.25 869.5,-264.25 875.5,-264.25 881.5,-270.25 881.5,-276.25 881.5,-276.25 881.5,-296.25 881.5,-296.25 881.5,-302.25 875.5,-308.25 869.5,-308.25"/>
<text text-anchor="start" x="758.5" y="-280.07" font-family="Times,serif" font-size="14.00">IdleWaitingForInput</text>
</g>
<!-- POST&#45;&gt;IdleWaitingForInput -->
<g id="edge19" class="edge">
<title>POST&#45;&gt;IdleWaitingForInput</title>
<path fill="none" stroke="black" d="M280.21,-277.67C360.88,-278.97 607.65,-282.94 735.06,-285"/>
<polygon fill="black" stroke="black" points="734.69,-288.49 744.75,-285.15 734.8,-281.49 734.69,-288.49"/>
<text text-anchor="middle" x="568.38" y="-284.03" font-family="Times,serif" font-size="14.00">go_idle</text>
</g> </g>
<!-- WaitingForOS --> <!-- WaitingForOS -->
<g id="node5" class="node"> <g id="node6" class="node">
<title>WaitingForOS</title> <title>WaitingForOS</title>
<path fill="white" stroke="black" d="M984.5,-144.07C984.5,-144.07 913.75,-144.07 913.75,-144.07 907.75,-144.07 901.75,-138.07 901.75,-132.07 901.75,-132.07 901.75,-120.07 901.75,-120.07 901.75,-114.07 907.75,-108.07 913.75,-108.07 913.75,-108.07 984.5,-108.07 984.5,-108.07 990.5,-108.07 996.5,-114.07 996.5,-120.07 996.5,-120.07 996.5,-132.07 996.5,-132.07 996.5,-138.07 990.5,-144.07 984.5,-144.07"/> <path fill="white" stroke="black" d="M603.75,-124.25C603.75,-124.25 533,-124.25 533,-124.25 527,-124.25 521,-118.25 521,-112.25 521,-112.25 521,-100.25 521,-100.25 521,-94.25 527,-88.25 533,-88.25 533,-88.25 603.75,-88.25 603.75,-88.25 609.75,-88.25 615.75,-94.25 615.75,-100.25 615.75,-100.25 615.75,-112.25 615.75,-112.25 615.75,-118.25 609.75,-124.25 603.75,-124.25"/>
<text text-anchor="start" x="909.75" y="-119.89" font-family="Times,serif" font-size="14.00">WaitingForOS</text> <text text-anchor="start" x="529" y="-100.08" font-family="Times,serif" font-size="14.00">WaitingForOS</text>
</g> </g>
<!-- POST&#45;&gt;WaitingForOS --> <!-- POST&#45;&gt;WaitingForOS -->
<g id="edge16" class="edge"> <g id="edge17" class="edge">
<title>POST&#45;&gt;WaitingForOS</title> <title>POST&#45;&gt;WaitingForOS</title>
<path fill="none" stroke="black" d="M675.07,-259.57C693.94,-232.54 732.95,-182.74 779.25,-157.82 789.09,-152.52 845.24,-142.55 890.13,-135.19"/> <path fill="none" stroke="black" d="M263.64,-258.89C280.46,-227.13 314.28,-164.67 323.5,-158 352.68,-136.9 446.96,-121.37 509.38,-113.08"/>
<polygon fill="black" stroke="black" points="890.47,-138.69 899.78,-133.63 889.34,-131.78 890.47,-138.69"/> <polygon fill="black" stroke="black" points="509.68,-116.57 519.14,-111.81 508.77,-109.63 509.68,-116.57"/>
<text text-anchor="middle" x="828.38" y="-158.77" font-family="Times,serif" font-size="14.00">enter_os</text> <text text-anchor="middle" x="410.12" y="-158.95" font-family="Times,serif" font-size="14.00">wait_os</text>
</g> </g>
<!-- BootLoop --> <!-- BootLoop -->
<g id="node11" class="node"> <g id="node12" class="node">
<title>BootLoop</title> <title>BootLoop</title>
<path fill="white" stroke="black" d="M972.88,-417.07C972.88,-417.07 925.38,-417.07 925.38,-417.07 919.38,-417.07 913.38,-411.07 913.38,-405.07 913.38,-405.07 913.38,-393.07 913.38,-393.07 913.38,-387.07 919.38,-381.07 925.38,-381.07 925.38,-381.07 972.88,-381.07 972.88,-381.07 978.88,-381.07 984.88,-387.07 984.88,-393.07 984.88,-393.07 984.88,-405.07 984.88,-405.07 984.88,-411.07 978.88,-417.07 972.88,-417.07"/> <path fill="white" stroke="black" d="M592.12,-178.25C592.12,-178.25 544.62,-178.25 544.62,-178.25 538.62,-178.25 532.62,-172.25 532.62,-166.25 532.62,-166.25 532.62,-154.25 532.62,-154.25 532.62,-148.25 538.62,-142.25 544.62,-142.25 544.62,-142.25 592.12,-142.25 592.12,-142.25 598.12,-142.25 604.12,-148.25 604.12,-154.25 604.12,-154.25 604.12,-166.25 604.12,-166.25 604.12,-172.25 598.12,-178.25 592.12,-178.25"/>
<text text-anchor="start" x="921.38" y="-392.89" font-family="Times,serif" font-size="14.00">BootLoop</text> <text text-anchor="start" x="540.62" y="-154.07" font-family="Times,serif" font-size="14.00">BootLoop</text>
</g> </g>
<!-- POST&#45;&gt;BootLoop --> <!-- POST&#45;&gt;BootLoop -->
<g id="edge17" class="edge"> <g id="edge18" class="edge">
<title>POST&#45;&gt;BootLoop</title> <title>POST&#45;&gt;BootLoop</title>
<path fill="none" stroke="black" d="M686.03,-296.45C708.6,-313.5 744.49,-338.37 779.25,-353.07 820.53,-370.52 834.34,-363.74 877.5,-375.82 885.53,-378.07 894.01,-380.66 902.2,-383.28"/> <path fill="none" stroke="black" d="M264.71,-258.92C276.57,-240.46 297.49,-212.79 323.5,-199 392.11,-162.62 420.3,-189.9 496.75,-176.25 504.66,-174.84 513.02,-173.13 521.11,-171.37"/>
<polygon fill="black" stroke="black" points="901.08,-386.6 911.67,-386.38 903.25,-379.95 901.08,-386.6"/> <polygon fill="black" stroke="black" points="521.83,-174.8 530.82,-169.2 520.3,-167.97 521.83,-174.8"/>
<text text-anchor="middle" x="828.38" y="-376.77" font-family="Times,serif" font-size="14.00">unsuccessful_post</text> <text text-anchor="middle" x="410.12" y="-199.95" font-family="Times,serif" font-size="14.00">unsuccessful_post</text>
</g> </g>
<!-- BIOSSetup --> <!-- BIOSSetup -->
<g id="node4" class="node"> <g id="node4" class="node">
<title>BIOSSetup</title> <title>BIOSSetup</title>
<path fill="white" stroke="black" d="M1215.62,-325.07C1215.62,-325.07 1162.12,-325.07 1162.12,-325.07 1156.12,-325.07 1150.12,-319.07 1150.12,-313.07 1150.12,-313.07 1150.12,-301.07 1150.12,-301.07 1150.12,-295.07 1156.12,-289.07 1162.12,-289.07 1162.12,-289.07 1215.62,-289.07 1215.62,-289.07 1221.62,-289.07 1227.62,-295.07 1227.62,-301.07 1227.62,-301.07 1227.62,-313.07 1227.62,-313.07 1227.62,-319.07 1221.62,-325.07 1215.62,-325.07"/> <path fill="white" stroke="black" d="M840.75,-462.25C840.75,-462.25 787.25,-462.25 787.25,-462.25 781.25,-462.25 775.25,-456.25 775.25,-450.25 775.25,-450.25 775.25,-438.25 775.25,-438.25 775.25,-432.25 781.25,-426.25 787.25,-426.25 787.25,-426.25 840.75,-426.25 840.75,-426.25 846.75,-426.25 852.75,-432.25 852.75,-438.25 852.75,-438.25 852.75,-450.25 852.75,-450.25 852.75,-456.25 846.75,-462.25 840.75,-462.25"/>
<text text-anchor="start" x="1158.12" y="-300.89" font-family="Times,serif" font-size="14.00">BIOSSetup</text> <text text-anchor="start" x="783.25" y="-438.07" font-family="Times,serif" font-size="14.00">BIOSSetup</text>
</g> </g>
<!-- EnterBIOS&#45;&gt;BIOSSetup --> <!-- EnterBIOS&#45;&gt;BIOSSetup -->
<g id="edge2" class="edge"> <g id="edge2" class="edge">
<title>EnterBIOS&#45;&gt;BIOSSetup</title> <title>EnterBIOS&#45;&gt;BIOSSetup</title>
<path fill="none" stroke="black" d="M987.53,-307.07C1028.32,-307.07 1093.74,-307.07 1138.66,-307.07"/> <path fill="none" stroke="black" d="M606.69,-394.55C639.16,-398.7 687.33,-405.86 728.5,-416 740.22,-418.89 752.65,-422.64 764.27,-426.46"/>
<polygon fill="black" stroke="black" points="1138.38,-310.57 1148.38,-307.07 1138.38,-303.57 1138.38,-310.57"/> <polygon fill="black" stroke="black" points="763.08,-429.76 773.67,-429.64 765.32,-423.12 763.08,-429.76"/>
<text text-anchor="middle" x="1065" y="-308.02" font-family="Times,serif" font-size="14.00">start_bios_setup</text> <text text-anchor="middle" x="684.25" y="-416.95" font-family="Times,serif" font-size="14.00">start_bios_setup</text>
</g>
<!-- EnterBIOS&#45;&gt;IdleWaitingForInput -->
<g id="edge3" class="edge">
<title>EnterBIOS&#45;&gt;IdleWaitingForInput</title>
<path fill="none" stroke="black" d="M606.64,-374.34C644.73,-358.08 704.58,-332.53 750.03,-313.13"/>
<polygon fill="black" stroke="black" points="751.16,-316.45 758.99,-309.31 748.42,-310.01 751.16,-316.45"/>
<text text-anchor="middle" x="684.25" y="-360.47" font-family="Times,serif" font-size="14.00">go_idle</text>
</g> </g>
<!-- BIOSSetup&#45;&gt;PoweredOff --> <!-- BIOSSetup&#45;&gt;PoweredOff -->
<g id="edge3" class="edge"> <g id="edge4" class="edge">
<title>BIOSSetup&#45;&gt;PoweredOff</title> <title>BIOSSetup&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1167.93,-325.54C1135.97,-353.74 1070.02,-406.31 1002.75,-426.07 897.77,-456.9 571.58,-377.59 445.35,-344.64"/> <path fill="none" stroke="black" d="M774.97,-454.2C760.51,-457.61 743.84,-461.11 728.5,-463.25 550.01,-488.17 491.43,-508.67 323.5,-443.25 217.43,-401.93 114.54,-311.19 67.8,-266.36"/>
<polygon fill="black" stroke="black" points="446.51,-341.32 435.94,-342.17 444.73,-348.1 446.51,-341.32"/> <polygon fill="black" stroke="black" points="70.44,-264.05 60.83,-259.6 65.57,-269.07 70.44,-264.05"/>
<text text-anchor="middle" x="828.38" y="-430.51" font-family="Times,serif" font-size="14.00">hard_shutdown</text> <text text-anchor="middle" x="410.12" y="-487.27" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g> </g>
<!-- BIOSSetup&#45;&gt;POST --> <!-- BIOSSetup&#45;&gt;POST -->
<g id="edge4" class="edge">
<title>BIOSSetup&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1149.64,-295.97C1112.49,-285.8 1054.3,-271.49 1002.75,-265.82 893.3,-253.77 762.96,-265.78 700.24,-273.19"/>
<polygon fill="black" stroke="black" points="699.99,-269.69 690.48,-274.37 700.83,-276.64 699.99,-269.69"/>
<text text-anchor="middle" x="949.12" y="-266.77" font-family="Times,serif" font-size="14.00">finished_bios_setup</text>
</g>
<!-- WaitingForOS&#45;&gt;PoweredOff -->
<g id="edge5" class="edge"> <g id="edge5" class="edge">
<title>WaitingForOS&#45;&gt;PoweredOff</title> <title>BIOSSetup&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M901.6,-125.18C867.31,-125.53 819.79,-128.14 779.25,-138.07 629.6,-174.72 592.58,-195.51 461.25,-276.07 457.16,-278.58 440.47,-292.38 424.84,-305.53"/> <path fill="none" stroke="black" d="M774.91,-446.46C673.09,-451.63 397.39,-460.7 323.5,-412.25 286.78,-388.18 268.43,-338.29 260.08,-306.36"/>
<polygon fill="black" stroke="black" points="422.9,-302.59 417.51,-311.71 427.41,-307.94 422.9,-302.59"/> <polygon fill="black" stroke="black" points="263.56,-305.86 257.8,-296.97 256.75,-307.51 263.56,-305.86"/>
<text text-anchor="middle" x="661.88" y="-216.91" font-family="Times,serif" font-size="14.00">hard_shutdown</text> <text text-anchor="middle" x="568.38" y="-451.64" font-family="Times,serif" font-size="14.00">finished_bios_setup</text>
</g>
<!-- WaitingForHWInfo -->
<g id="node6" class="node">
<title>WaitingForHWInfo</title>
<path fill="white" stroke="black" d="M1238.5,-137.07C1238.5,-137.07 1139.25,-137.07 1139.25,-137.07 1133.25,-137.07 1127.25,-131.07 1127.25,-125.07 1127.25,-125.07 1127.25,-113.07 1127.25,-113.07 1127.25,-107.07 1133.25,-101.07 1139.25,-101.07 1139.25,-101.07 1238.5,-101.07 1238.5,-101.07 1244.5,-101.07 1250.5,-107.07 1250.5,-113.07 1250.5,-113.07 1250.5,-125.07 1250.5,-125.07 1250.5,-131.07 1244.5,-137.07 1238.5,-137.07"/>
<text text-anchor="start" x="1135.25" y="-112.89" font-family="Times,serif" font-size="14.00">WaitingForHWInfo</text>
</g>
<!-- WaitingForOS&#45;&gt;WaitingForHWInfo -->
<g id="edge6" class="edge">
<title>WaitingForOS&#45;&gt;WaitingForHWInfo</title>
<path fill="none" stroke="black" d="M996.81,-124.7C1030.66,-123.7 1077.07,-122.33 1115.68,-121.2"/>
<polygon fill="black" stroke="black" points="1115.46,-124.7 1125.35,-120.91 1115.25,-117.71 1115.46,-124.7"/>
<text text-anchor="middle" x="1065" y="-124.76" font-family="Times,serif" font-size="14.00">os_booted</text>
</g>
<!-- OCTypeDecision -->
<g id="node7" class="node">
<title>OCTypeDecision</title>
<path fill="white" stroke="black" d="M1478.75,-226.07C1478.75,-226.07 1392.25,-226.07 1392.25,-226.07 1386.25,-226.07 1380.25,-220.07 1380.25,-214.07 1380.25,-214.07 1380.25,-202.07 1380.25,-202.07 1380.25,-196.07 1386.25,-190.07 1392.25,-190.07 1392.25,-190.07 1478.75,-190.07 1478.75,-190.07 1484.75,-190.07 1490.75,-196.07 1490.75,-202.07 1490.75,-202.07 1490.75,-214.07 1490.75,-214.07 1490.75,-220.07 1484.75,-226.07 1478.75,-226.07"/>
<text text-anchor="start" x="1388.25" y="-201.89" font-family="Times,serif" font-size="14.00">OCTypeDecision</text>
</g>
<!-- WaitingForHWInfo&#45;&gt;OCTypeDecision -->
<g id="edge18" class="edge">
<title>WaitingForHWInfo&#45;&gt;OCTypeDecision</title>
<path fill="none" stroke="black" d="M1240.56,-137.51C1279.1,-151.53 1332.29,-170.88 1373.22,-185.77"/>
<polygon fill="black" stroke="black" points="1371.86,-189.01 1382.46,-189.14 1374.26,-182.43 1371.86,-189.01"/>
<text text-anchor="middle" x="1315.38" y="-182.72" font-family="Times,serif" font-size="14.00">hwinfo_available</text>
</g>
<!-- RoughMulticoreUndervolt -->
<g id="node8" class="node">
<title>RoughMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1834.5,-277.07C1834.5,-277.07 1697,-277.07 1697,-277.07 1691,-277.07 1685,-271.07 1685,-265.07 1685,-265.07 1685,-253.07 1685,-253.07 1685,-247.07 1691,-241.07 1697,-241.07 1697,-241.07 1834.5,-241.07 1834.5,-241.07 1840.5,-241.07 1846.5,-247.07 1846.5,-253.07 1846.5,-253.07 1846.5,-265.07 1846.5,-265.07 1846.5,-271.07 1840.5,-277.07 1834.5,-277.07"/>
<text text-anchor="start" x="1693" y="-252.89" font-family="Times,serif" font-size="14.00">RoughMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;RoughMulticoreUndervolt -->
<g id="edge7" class="edge">
<title>OCTypeDecision&#45;&gt;RoughMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1491.03,-210.75C1537.67,-213.69 1606.43,-219.57 1665.5,-230.82 1675.22,-232.67 1685.36,-235.04 1695.29,-237.61"/>
<polygon fill="black" stroke="black" points="1694.36,-240.98 1704.92,-240.2 1696.17,-234.22 1694.36,-240.98"/>
<text text-anchor="middle" x="1587.12" y="-231.77" font-family="Times,serif" font-size="14.00">rough_multicore_undervolt</text>
</g>
<!-- PreciseMulticoreUndervolt -->
<g id="node9" class="node">
<title>PreciseMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1836,-178.07C1836,-178.07 1695.5,-178.07 1695.5,-178.07 1689.5,-178.07 1683.5,-172.07 1683.5,-166.07 1683.5,-166.07 1683.5,-154.07 1683.5,-154.07 1683.5,-148.07 1689.5,-142.07 1695.5,-142.07 1695.5,-142.07 1836,-142.07 1836,-142.07 1842,-142.07 1848,-148.07 1848,-154.07 1848,-154.07 1848,-166.07 1848,-166.07 1848,-172.07 1842,-178.07 1836,-178.07"/>
<text text-anchor="start" x="1691.5" y="-153.89" font-family="Times,serif" font-size="14.00">PreciseMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt -->
<g id="edge8" class="edge">
<title>OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1490.87,-196.96C1496.9,-195.84 1502.95,-194.77 1508.75,-193.82 1562.72,-184.95 1623.38,-176.87 1672.11,-170.84"/>
<polygon fill="black" stroke="black" points="1672.27,-174.35 1681.77,-169.65 1671.42,-167.4 1672.27,-174.35"/>
<text text-anchor="middle" x="1587.12" y="-194.77" font-family="Times,serif" font-size="14.00">precise_multicore_undervolt</text>
</g>
<!-- SingleCoreTuning -->
<g id="node10" class="node">
<title>SingleCoreTuning</title>
<path fill="white" stroke="black" d="M1811.25,-468.07C1811.25,-468.07 1720.25,-468.07 1720.25,-468.07 1714.25,-468.07 1708.25,-462.07 1708.25,-456.07 1708.25,-456.07 1708.25,-444.07 1708.25,-444.07 1708.25,-438.07 1714.25,-432.07 1720.25,-432.07 1720.25,-432.07 1811.25,-432.07 1811.25,-432.07 1817.25,-432.07 1823.25,-438.07 1823.25,-444.07 1823.25,-444.07 1823.25,-456.07 1823.25,-456.07 1823.25,-462.07 1817.25,-468.07 1811.25,-468.07"/>
<text text-anchor="start" x="1716.25" y="-443.89" font-family="Times,serif" font-size="14.00">SingleCoreTuning</text>
</g>
<!-- OCTypeDecision&#45;&gt;SingleCoreTuning -->
<g id="edge9" class="edge">
<title>OCTypeDecision&#45;&gt;SingleCoreTuning</title>
<path fill="none" stroke="black" d="M1461.44,-226.46C1519.62,-269.35 1664.39,-376.08 1730.66,-424.94"/>
<polygon fill="black" stroke="black" points="1728.5,-427.69 1738.63,-430.81 1732.66,-422.06 1728.5,-427.69"/>
<text text-anchor="middle" x="1587.12" y="-372.74" font-family="Times,serif" font-size="14.00">single_core_tuning</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge10" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1757.07,-277.52C1743.54,-307.33 1712.4,-365.22 1665.5,-390.07 1612.58,-418.11 1186.67,-410.6 1127.25,-418.07 1071.25,-425.11 1058.71,-435.75 1002.75,-443.07 896.12,-457.02 868.74,-454.73 761.25,-458.07 627.56,-462.22 570.49,-511.26 461.25,-434.07 435.14,-415.62 416.77,-383.36 406.06,-359.85"/>
<polygon fill="black" stroke="black" points="409.33,-358.6 402.14,-350.81 402.91,-361.38 409.33,-358.6"/>
<text text-anchor="middle" x="1065" y="-441.28" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;POST -->
<g id="edge11" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1684.66,-258.79C1545.83,-258.32 1251.46,-257.4 1002.75,-257.07 903.42,-256.94 878.19,-248.21 779.25,-257.07 752.61,-259.45 722.94,-264.85 700.23,-269.58"/>
<polygon fill="black" stroke="black" points="699.57,-266.14 690.52,-271.65 701.03,-272.98 699.57,-266.14"/>
<text text-anchor="middle" x="1188.88" y="-258.48" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge12" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1737.58,-141.75C1683.02,-106.8 1555.23,-34.07 1436.5,-34.07 827.38,-34.07 827.38,-34.07 827.38,-34.07 709.17,-34.07 662.94,4.26 562.5,-58.07 489.39,-103.44 495.26,-144.04 461.25,-223.07 449.06,-251.39 459.78,-264.04 443.25,-290.07 439.77,-295.56 435.32,-300.69 430.53,-305.34"/>
<polygon fill="black" stroke="black" points="428.54,-302.42 423.4,-311.69 433.19,-307.65 428.54,-302.42"/>
<text text-anchor="middle" x="1065" y="-35.02" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;POST -->
<g id="edge13" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1683.38,-162.44C1584.97,-165.75 1414.35,-172.88 1268.5,-186.07 1050.15,-205.82 994.7,-208.5 779.25,-249.07 752.47,-254.11 722.65,-261.58 699.9,-267.67"/>
<polygon fill="black" stroke="black" points="699.22,-264.23 690.49,-270.23 701.06,-270.99 699.22,-264.23"/>
<text text-anchor="middle" x="1188.88" y="-199.62" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- SingleCoreTuning&#45;&gt;PoweredOff -->
<g id="edge23" class="edge">
<title>SingleCoreTuning&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1712.63,-468.54C1648.51,-489.58 1535.91,-521.07 1436.5,-521.07 660.88,-521.07 660.88,-521.07 660.88,-521.07 568.96,-521.07 532.13,-525.58 461.25,-467.07 428,-439.62 410.06,-391.51 401.46,-360.48"/>
<polygon fill="black" stroke="black" points="404.89,-359.77 398.99,-350.97 398.11,-361.53 404.89,-359.77"/>
<text text-anchor="middle" x="1065" y="-522.02" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- SingleCoreTuning&#45;&gt;POST -->
<g id="edge24" class="edge">
<title>SingleCoreTuning&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1707.81,-446.81C1555.28,-437.12 1125.54,-403.62 779.25,-317.07 752.25,-310.32 722.5,-300.3 699.84,-292.11"/>
<polygon fill="black" stroke="black" points="701.35,-288.94 690.75,-288.78 698.94,-295.51 701.35,-288.94"/>
<text text-anchor="middle" x="1188.88" y="-402.53" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- BootLoop&#45;&gt;PoweredOff -->
<g id="edge19" class="edge">
<title>BootLoop&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M912.98,-416.02C901.89,-420.54 889.42,-424.79 877.5,-427.07 786.56,-444.44 544.18,-450.23 461.25,-409.07 439.33,-398.19 421.77,-376.49 410.21,-358.73"/>
<polygon fill="black" stroke="black" points="413.45,-357.32 405.21,-350.65 407.5,-361 413.45,-357.32"/>
<text text-anchor="middle" x="661.88" y="-441.21" font-family="Times,serif" font-size="14.00">trigger_cmos_reset | hard_shutdown</text>
</g>
<!-- IdleWaitingForInput -->
<g id="node12" class="node">
<title>IdleWaitingForInput</title>
<path fill="darksalmon" stroke="red" d="M119,-279.07C119,-279.07 16,-279.07 16,-279.07 10,-279.07 4,-273.07 4,-267.07 4,-267.07 4,-255.07 4,-255.07 4,-249.07 10,-243.07 16,-243.07 16,-243.07 119,-243.07 119,-243.07 125,-243.07 131,-249.07 131,-255.07 131,-255.07 131,-267.07 131,-267.07 131,-273.07 125,-279.07 119,-279.07"/>
<path fill="none" stroke="red" d="M123,-283.07C123,-283.07 12,-283.07 12,-283.07 6,-283.07 0,-277.07 0,-271.07 0,-271.07 0,-251.07 0,-251.07 0,-245.07 6,-239.07 12,-239.07 12,-239.07 123,-239.07 123,-239.07 129,-239.07 135,-245.07 135,-251.07 135,-251.07 135,-271.07 135,-271.07 135,-277.07 129,-283.07 123,-283.07"/>
<text text-anchor="start" x="12" y="-254.89" font-family="Times,serif" font-size="14.00">IdleWaitingForInput</text>
</g> </g>
<!-- IdleWaitingForInput&#45;&gt;PoweredOff --> <!-- IdleWaitingForInput&#45;&gt;PoweredOff -->
<g id="edge20" class="edge"> <g id="edge22" class="edge">
<title>IdleWaitingForInput&#45;&gt;PoweredOff</title> <title>IdleWaitingForInput&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M135.29,-275.49C196.69,-288.74 286.38,-308.11 342.07,-320.13"/> <path fill="none" stroke="black" d="M782.75,-263.83C770.97,-254.56 757.65,-243.39 746.5,-232.25 684.48,-170.29 701.17,-116.9 622,-79.25 452.13,1.52 376.7,-51.42 200.5,-117.25 153.49,-134.82 138.25,-135.67 99.25,-167.25 83.5,-180 69.34,-197.8 59,-212.62"/>
<polygon fill="black" stroke="black" points="341.09,-323.5 351.6,-322.19 342.56,-316.65 341.09,-323.5"/> <polygon fill="black" stroke="black" points="56.31,-210.35 53.63,-220.6 62.12,-214.27 56.31,-210.35"/>
<text text-anchor="middle" x="239.62" y="-316.9" font-family="Times,serif" font-size="14.00">hard_shutdown | soft_shutdown</text> <text text-anchor="middle" x="410.12" y="-70.19" font-family="Times,serif" font-size="14.00">hard_shutdown | soft_shutdown</text>
</g> </g>
<!-- IdleWaitingForInput&#45;&gt;POST --> <!-- IdleWaitingForInput&#45;&gt;POST -->
<g id="edge21" class="edge"> <g id="edge23" class="edge">
<title>IdleWaitingForInput&#45;&gt;POST</title> <title>IdleWaitingForInput&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M135.3,-262.99C260.06,-266.57 524.71,-274.16 623.04,-276.98"/> <path fill="none" stroke="black" d="M746,-276.08C709.45,-271.04 663.35,-265.51 622,-263 501.29,-255.68 358.06,-266.96 291.49,-273.34"/>
<polygon fill="black" stroke="black" points="622.85,-280.48 632.94,-277.27 623.05,-273.48 622.85,-280.48"/> <polygon fill="black" stroke="black" points="291.46,-269.83 281.85,-274.29 292.15,-276.8 291.46,-269.83"/>
<text text-anchor="middle" x="393.75" y="-272.76" font-family="Times,serif" font-size="14.00">power_on | reboot</text> <text text-anchor="middle" x="568.38" y="-263.95" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- WaitingForHWInfo -->
<g id="node7" class="node">
<title>WaitingForHWInfo</title>
<path fill="white" stroke="black" d="M1127,-304.25C1127,-304.25 1027.75,-304.25 1027.75,-304.25 1021.75,-304.25 1015.75,-298.25 1015.75,-292.25 1015.75,-292.25 1015.75,-280.25 1015.75,-280.25 1015.75,-274.25 1021.75,-268.25 1027.75,-268.25 1027.75,-268.25 1127,-268.25 1127,-268.25 1133,-268.25 1139,-274.25 1139,-280.25 1139,-280.25 1139,-292.25 1139,-292.25 1139,-298.25 1133,-304.25 1127,-304.25"/>
<text text-anchor="start" x="1023.75" y="-280.07" font-family="Times,serif" font-size="14.00">WaitingForHWInfo</text>
</g> </g>
<!-- IdleWaitingForInput&#45;&gt;WaitingForHWInfo --> <!-- IdleWaitingForInput&#45;&gt;WaitingForHWInfo -->
<g id="edge22" class="edge"> <g id="edge24" class="edge">
<title>IdleWaitingForInput&#45;&gt;WaitingForHWInfo</title> <title>IdleWaitingForInput&#45;&gt;WaitingForHWInfo</title>
<path fill="none" stroke="black" d="M89.75,-238.88C138.43,-190.54 263.81,-80.07 392.75,-80.07 392.75,-80.07 392.75,-80.07 950.12,-80.07 1006.27,-80.07 1068.91,-90.79 1115.79,-100.99"/> <path fill="none" stroke="black" d="M881.97,-286.25C919.42,-286.25 966.1,-286.25 1004.33,-286.25"/>
<polygon fill="black" stroke="black" points="1114.75,-104.35 1125.27,-103.1 1116.27,-97.52 1114.75,-104.35"/> <polygon fill="black" stroke="black" points="1003.88,-289.75 1013.88,-286.25 1003.88,-282.75 1003.88,-289.75"/>
<text text-anchor="middle" x="661.88" y="-81.02" font-family="Times,serif" font-size="14.00">begin_automation</text> <text text-anchor="middle" x="948.62" y="-287.2" font-family="Times,serif" font-size="14.00">begin_automation</text>
</g>
<!-- WaitingForOS&#45;&gt;PoweredOff -->
<g id="edge6" class="edge">
<title>WaitingForOS&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M520.53,-103.99C471.03,-102.62 390.94,-103.29 323.5,-117.25 266.23,-129.11 255.1,-143.04 200.5,-164 155.44,-181.3 142.27,-181.38 99.25,-203.25 91.96,-206.95 84.43,-211.34 77.32,-215.77"/>
<polygon fill="black" stroke="black" points="75.74,-212.62 69.21,-220.96 79.52,-218.52 75.74,-212.62"/>
<text text-anchor="middle" x="253" y="-164.95" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- WaitingForOS&#45;&gt;WaitingForHWInfo -->
<g id="edge7" class="edge">
<title>WaitingForOS&#45;&gt;WaitingForHWInfo</title>
<path fill="none" stroke="black" d="M616.16,-122.86C707.79,-155.39 910.9,-227.5 1013.89,-264.07"/>
<polygon fill="black" stroke="black" points="1012.42,-267.26 1023.01,-267.31 1014.76,-260.66 1012.42,-267.26"/>
<text text-anchor="middle" x="814" y="-215.09" font-family="Times,serif" font-size="14.00">os_booted</text>
</g>
<!-- OCTypeDecision -->
<g id="node8" class="node">
<title>OCTypeDecision</title>
<path fill="white" stroke="black" d="M1367.25,-307.25C1367.25,-307.25 1280.75,-307.25 1280.75,-307.25 1274.75,-307.25 1268.75,-301.25 1268.75,-295.25 1268.75,-295.25 1268.75,-283.25 1268.75,-283.25 1268.75,-277.25 1274.75,-271.25 1280.75,-271.25 1280.75,-271.25 1367.25,-271.25 1367.25,-271.25 1373.25,-271.25 1379.25,-277.25 1379.25,-283.25 1379.25,-283.25 1379.25,-295.25 1379.25,-295.25 1379.25,-301.25 1373.25,-307.25 1367.25,-307.25"/>
<text text-anchor="start" x="1276.75" y="-283.07" font-family="Times,serif" font-size="14.00">OCTypeDecision</text>
</g>
<!-- WaitingForHWInfo&#45;&gt;OCTypeDecision -->
<g id="edge20" class="edge">
<title>WaitingForHWInfo&#45;&gt;OCTypeDecision</title>
<path fill="none" stroke="black" d="M1139.47,-287C1175.38,-287.44 1220.78,-288 1257.43,-288.45"/>
<polygon fill="black" stroke="black" points="1256.95,-291.94 1267,-288.56 1257.04,-284.94 1256.95,-291.94"/>
<text text-anchor="middle" x="1203.88" y="-289.31" font-family="Times,serif" font-size="14.00">hwinfo_available</text>
</g>
<!-- RoughMulticoreUndervolt -->
<g id="node9" class="node">
<title>RoughMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1723,-536.25C1723,-536.25 1585.5,-536.25 1585.5,-536.25 1579.5,-536.25 1573.5,-530.25 1573.5,-524.25 1573.5,-524.25 1573.5,-512.25 1573.5,-512.25 1573.5,-506.25 1579.5,-500.25 1585.5,-500.25 1585.5,-500.25 1723,-500.25 1723,-500.25 1729,-500.25 1735,-506.25 1735,-512.25 1735,-512.25 1735,-524.25 1735,-524.25 1735,-530.25 1729,-536.25 1723,-536.25"/>
<text text-anchor="start" x="1581.5" y="-512.08" font-family="Times,serif" font-size="14.00">RoughMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;RoughMulticoreUndervolt -->
<g id="edge8" class="edge">
<title>OCTypeDecision&#45;&gt;RoughMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1351.31,-307.6C1409.89,-348.47 1551.14,-447.01 1617.58,-493.36"/>
<polygon fill="black" stroke="black" points="1615.37,-496.09 1625.58,-498.94 1619.38,-490.35 1615.37,-496.09"/>
<text text-anchor="middle" x="1475.62" y="-445.13" font-family="Times,serif" font-size="14.00">rough_multicore_undervolt</text>
</g>
<!-- PreciseMulticoreUndervolt -->
<g id="node10" class="node">
<title>PreciseMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1724.5,-362.25C1724.5,-362.25 1584,-362.25 1584,-362.25 1578,-362.25 1572,-356.25 1572,-350.25 1572,-350.25 1572,-338.25 1572,-338.25 1572,-332.25 1578,-326.25 1584,-326.25 1584,-326.25 1724.5,-326.25 1724.5,-326.25 1730.5,-326.25 1736.5,-332.25 1736.5,-338.25 1736.5,-338.25 1736.5,-350.25 1736.5,-350.25 1736.5,-356.25 1730.5,-362.25 1724.5,-362.25"/>
<text text-anchor="start" x="1580" y="-338.07" font-family="Times,serif" font-size="14.00">PreciseMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt -->
<g id="edge9" class="edge">
<title>OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1379.52,-293.13C1426.16,-297.05 1494.92,-304.22 1554,-316 1563.57,-317.91 1573.57,-320.28 1583.37,-322.84"/>
<polygon fill="black" stroke="black" points="1582.3,-326.18 1592.86,-325.4 1584.12,-319.42 1582.3,-326.18"/>
<text text-anchor="middle" x="1475.62" y="-316.95" font-family="Times,serif" font-size="14.00">precise_multicore_undervolt</text>
</g>
<!-- SingleCoreTuning -->
<g id="node11" class="node">
<title>SingleCoreTuning</title>
<path fill="white" stroke="black" d="M1699.75,-195.25C1699.75,-195.25 1608.75,-195.25 1608.75,-195.25 1602.75,-195.25 1596.75,-189.25 1596.75,-183.25 1596.75,-183.25 1596.75,-171.25 1596.75,-171.25 1596.75,-165.25 1602.75,-159.25 1608.75,-159.25 1608.75,-159.25 1699.75,-159.25 1699.75,-159.25 1705.75,-159.25 1711.75,-165.25 1711.75,-171.25 1711.75,-171.25 1711.75,-183.25 1711.75,-183.25 1711.75,-189.25 1705.75,-195.25 1699.75,-195.25"/>
<text text-anchor="start" x="1604.75" y="-171.07" font-family="Times,serif" font-size="14.00">SingleCoreTuning</text>
</g>
<!-- OCTypeDecision&#45;&gt;SingleCoreTuning -->
<g id="edge10" class="edge">
<title>OCTypeDecision&#45;&gt;SingleCoreTuning</title>
<path fill="none" stroke="black" d="M1379.2,-270.76C1436.66,-251.15 1527.39,-220.19 1588.56,-199.32"/>
<polygon fill="black" stroke="black" points="1589.47,-202.71 1597.81,-196.17 1587.21,-196.08 1589.47,-202.71"/>
<text text-anchor="middle" x="1475.62" y="-263.13" font-family="Times,serif" font-size="14.00">single_core_tuning</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge11" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1616.37,-536.53C1556.69,-564.39 1434.55,-614.25 1325,-614.25 252,-614.25 252,-614.25 252,-614.25 169.87,-614.25 145.06,-578.42 99.25,-510.25 48.41,-434.59 41.3,-322.33 41.01,-269.61"/>
<polygon fill="black" stroke="black" points="44.51,-269.94 41.04,-259.93 37.51,-269.92 44.51,-269.94"/>
<text text-anchor="middle" x="814" y="-615.2" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;POST -->
<g id="edge12" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1573.32,-518.25C1506.85,-518.25 1409.77,-518.25 1325,-518.25 947.62,-518.25 947.62,-518.25 947.62,-518.25 808.9,-518.25 434.1,-587.99 323.5,-504.25 261.72,-457.48 253.2,-356.98 253.03,-306.89"/>
<polygon fill="black" stroke="black" points="256.53,-307.13 253.12,-297.1 249.53,-307.07 256.53,-307.13"/>
<text text-anchor="middle" x="948.62" y="-520.76" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge13" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1643.61,-362.68C1628.48,-389.56 1596.44,-438.87 1554,-462.25 1540.34,-469.78 1013.25,-536.55 997.75,-538.25 859.21,-553.47 824.62,-564.25 685.25,-564.25 252,-564.25 252,-564.25 252,-564.25 112.29,-564.25 60.65,-349.73 46.26,-269.8"/>
<polygon fill="black" stroke="black" points="49.74,-269.35 44.59,-260.09 42.84,-270.54 49.74,-269.35"/>
<text text-anchor="middle" x="814" y="-564.33" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;POST -->
<g id="edge14" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1571.64,-344.25C1505.22,-344.25 1409.06,-344.25 1325,-344.25 567.38,-344.25 567.38,-344.25 567.38,-344.25 465.67,-344.25 349.41,-310.08 291.26,-290.55"/>
<polygon fill="black" stroke="black" points="292.45,-287.26 281.85,-287.34 290.19,-293.88 292.45,-287.26"/>
<text text-anchor="middle" x="948.62" y="-345.2" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- SingleCoreTuning&#45;&gt;PoweredOff -->
<g id="edge25" class="edge">
<title>SingleCoreTuning&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1631.85,-158.86C1581.79,-117.8 1451.67,-22.25 1325,-22.25 252,-22.25 252,-22.25 252,-22.25 171.34,-22.25 152.68,-59.82 99.25,-120.25 75.65,-146.94 59.57,-185.01 50.52,-211.07"/>
<polygon fill="black" stroke="black" points="47.27,-209.75 47.44,-220.34 53.91,-211.95 47.27,-209.75"/>
<text text-anchor="middle" x="814" y="-23.2" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- SingleCoreTuning&#45;&gt;POST -->
<g id="edge26" class="edge">
<title>SingleCoreTuning&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1596.32,-177.25C1530.86,-177.25 1420.17,-177.25 1325,-177.25 813,-177.25 813,-177.25 813,-177.25 613.71,-177.25 380.62,-239.6 291.36,-265.83"/>
<polygon fill="black" stroke="black" points="290.5,-262.44 281.91,-268.64 292.5,-269.15 290.5,-262.44"/>
<text text-anchor="middle" x="948.62" y="-178.2" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- BootLoop&#45;&gt;PoweredOff -->
<g id="edge21" class="edge">
<title>BootLoop&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M532.49,-161.55C485.01,-163.65 397.49,-168.66 323.5,-179.25 222.7,-193.68 198.57,-203.78 99.25,-226.25 97.1,-226.74 94.91,-227.24 92.7,-227.75"/>
<polygon fill="black" stroke="black" points="91.98,-224.32 83.05,-230.02 93.59,-231.14 91.98,-224.32"/>
<text text-anchor="middle" x="253" y="-202.61" font-family="Times,serif" font-size="14.00">trigger_cmos_reset</text>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -8,21 +8,31 @@ resolution = "1920x1080"
fps = "60.000" fps = "60.000"
[client] [client]
hostname = "10.20.30.48" hostname = "10.20.30.90"
hwinfo_port = "60000" # Unless you've changed it! hwinfo_port = "60000" # Unless you've changed it!
# MAKE SURE YOU USE SINGLE QUOTES, THIS HAS TO BE A LITERAL
ryzen_smu_cli_path = 'C:\Users\rawhide\Downloads\win-x64\ryzen-smu-cli.exe'
ycruncher_path = 'C:\Users\rawhide\Downloads\y-cruncher v0.8.6.9545b\y-cruncher v0.8.6.9545\y-cruncher.exe'
bios_map_path = 'bios-maps/asus/x870-gaming-plus-wifi.gv'
[client.overclocking.common] # Just some ideas of how the settings may work for your system [client.overclocking.common] # Just some ideas of how the settings may work for your system
# "ACPI SRAT L3 Cache As NUMA Domain" = "Enabled" "ACPI SRAT L3 Cache As NUMA Domain" = "Enabled"
# "Spread Spectrum" = "Disabled" "PBO Limits" = "Motherboard"
# "PBO Limits" = "Motherboard" "Precision Boost Overdrive Scalar" = "10X"
# "Precision Boost Overdrive Scalar" = "10X" "Max CPU Boost Clock Override(+)" = "200"
# "Max CPU Boost Clock Override(+)" = "200" "Integrated Graphics" = "Disabled"
# "Auto Driver Installer" = "Disabled" "Voltage training" = "Enabled"
# "dGPU Only Mode" = "Enabled" "CPU Load-line Calibration" = "Level 8"
"CPU Current Capability" = "140%"
"Fixed CPU VRM Switching Frequency(KHz)" = "700"
"CPU Power Phase Control" = "Extreme"
"VDDSOC Current Capability" = "140%"
"Fixed VDDSOC Switching Frequency(KHz)" = "700"
"VDDSOC Power Phase Control" = "Extreme"
[client.overclocking.cpu] [client.overclocking.cpu]
[client.overclocking.memory] [client.overclocking.memory]
# "DRAM Profile Setting" = "XMP1-6000" # "DRAM Profile Setting" = "XMP1-6000"
# "DRAM Performance Mode" = "Aggressive" # "DRAM Performance Mode" = "Aggressive"
# "SOC/Uncore OC Voltage (VDD_SOC)" = "1.1" "VDDSOC Voltage Override" = "1.2"

View File

@ -1,3 +1,4 @@
from ipkvm import routes from ipkvm import routes, states
from ipkvm.states import events
__all__ = ["routes"] __all__ = ["routes", "states", "events"]

View File

@ -0,0 +1,6 @@
from . import states
model = states.Overclocking()
machine = states.MyMachine(model, states=states.State, initial=model.state)
machine.get_graph().draw('my_state_diagram.svg', prog='dot')

View File

@ -1,23 +1,29 @@
from ipkvm.app import ui from ipkvm.app import ui
from . import model
from ipkvm.util.mkb import esp32_serial
from ipkvm.util.mkb.mkb import GPIO
import time
@ui.on("power_on") @ui.on("power_on")
def handle_poweron(): def handle_poweron():
states.model.power_on() model.power_on()
@ui.on("soft_power_off") @ui.on("soft_power_off")
def handle_soft_poweroff(): def handle_soft_poweroff():
states.model.soft_shutdown() model.soft_shutdown()
@ui.on("hard_power_off") @ui.on("hard_power_off")
def handle_hard_poweroff(): def handle_hard_poweroff():
states.model.hard_shutdown() model.hard_shutdown()
@ui.on("reboot_into_bios") @ui.on("reboot_into_bios")
def handle_reboot_bios(): def handle_reboot_bios():
states.model.reboot_into_bios() model.reboot_into_bios()
@ui.on("clear_cmos") @ui.on("clear_cmos")
def handle_clear_cmos(): def handle_clear_cmos():
print("clear cmos and restart")
msg = { msg = {
"cmos": GPIO.HIGH.value "cmos": GPIO.HIGH.value
} }
@ -28,11 +34,14 @@ def handle_clear_cmos():
} }
esp32_serial.mkb_queue.put(msg) esp32_serial.mkb_queue.put(msg)
time.sleep(1) time.sleep(5)
power_switch(0.2) msg = {
spam_delete_until_bios() "pwr": GPIO.HIGH.value
}
@ui.on("test_route") esp32_serial.mkb_queue.put(msg)
def handle_test_route(): time.sleep(0.2)
graphs.test_route() msg = {
"pwr": GPIO.LOW.value
}
esp32_serial.mkb_queue.put(msg)

View File

@ -2,10 +2,13 @@ from enum import Enum
import time import time
from transitions.experimental.utils import with_model_definitions, add_transitions, transition from transitions.experimental.utils import with_model_definitions, add_transitions, transition
from transitions.extensions import GraphMachine from transitions.extensions import GraphMachine
from ipkvm.util import esp32_serial from ipkvm.util.mkb import esp32_serial
from ipkvm.util.mkb import GPIO, HIDKeyCode from ipkvm.util.mkb.mkb import GPIO
from ipkvm.util.mkb.scancodes import HIDKeyCode
from ipkvm.app import logging, ui from ipkvm.app import logging, ui
logging.basicConfig(level=logging.INFO)
class State(Enum): class State(Enum):
PoweredOff = "powered off" PoweredOff = "powered off"
EnterBIOS = "enter bios" EnterBIOS = "enter bios"
@ -22,15 +25,24 @@ class State(Enum):
class Overclocking: class Overclocking:
state: State = State.IdleWaitingForInput # wait for power status ig
time.sleep(0.5)
if esp32_serial.usb_status:
state: State = State.IdleWaitingForInput
else:
state: State = State.PoweredOff
_enter_bios_flag = False
_running_automatic = False
_current_BIOS_location = "EZ Mode"
# TRANSITION DEFINITIONS # TRANSITION DEFINITIONS
@add_transitions(transition([State.PoweredOff, State.IdleWaitingForInput], State.POST, after="_power_on", @add_transitions(transition(State.PoweredOff, State.POST, unless="client_powered"))
unless="client_powered"))
def power_on(self): ... def power_on(self): ...
@add_transitions(transition(State.POST, State.WaitingForOS)) @add_transitions(transition(State.POST, State.WaitingForOS))
def enter_os(self): ... def wait_os(self): ...
@add_transitions(transition(State.WaitingForOS, State.WaitingForHWInfo)) @add_transitions(transition(State.WaitingForOS, State.WaitingForHWInfo))
def os_booted(self): ... def os_booted(self): ...
@ -38,7 +50,7 @@ class Overclocking:
@add_transitions(transition(State.WaitingForHWInfo, State.OCTypeDecision)) @add_transitions(transition(State.WaitingForHWInfo, State.OCTypeDecision))
def hwinfo_available(self): ... def hwinfo_available(self): ...
@add_transitions(transition(State.POST, State.EnterBIOS, after="_enter_bios")) @add_transitions(transition(State.POST, State.EnterBIOS))
def enter_bios(self): ... def enter_bios(self): ...
@add_transitions(transition(State.EnterBIOS, State.BIOSSetup)) @add_transitions(transition(State.EnterBIOS, State.BIOSSetup))
@ -60,14 +72,13 @@ class Overclocking:
State.PreciseMulticoreUndervolt, State.SingleCoreTuning], State.POST)) State.PreciseMulticoreUndervolt, State.SingleCoreTuning], State.POST))
def reboot(self): ... def reboot(self): ...
@add_transitions(transition([State.BIOSSetup, State.IdleWaitingForInput, State.BootLoop, State.POST, @add_transitions(transition([State.BIOSSetup, State.IdleWaitingForInput, State.POST, State.WaitingForOS,
State.WaitingForOS, State.RoughMulticoreUndervolt, State.RoughMulticoreUndervolt, State.PreciseMulticoreUndervolt,
State.PreciseMulticoreUndervolt, State.SingleCoreTuning], State.SingleCoreTuning], State.PoweredOff, after="_hard_shutdown"))
State.PoweredOff, after="_hard_shutdown", conditions="client_powered"))
def hard_shutdown(self): ... def hard_shutdown(self): ...
@add_transitions(transition(State.IdleWaitingForInput, State.PoweredOff, @add_transitions(transition(State.IdleWaitingForInput, State.PoweredOff,
after="_soft_shutdown", conditions="client_powered")) after="_soft_shutdown"))
def soft_shutdown(self): ... def soft_shutdown(self): ...
@add_transitions(transition(State.OCTypeDecision, State.RoughMulticoreUndervolt)) @add_transitions(transition(State.OCTypeDecision, State.RoughMulticoreUndervolt))
@ -79,11 +90,91 @@ class Overclocking:
@add_transitions(transition(State.OCTypeDecision, State.SingleCoreTuning)) @add_transitions(transition(State.OCTypeDecision, State.SingleCoreTuning))
def single_core_tuning(self): ... def single_core_tuning(self): ...
@add_transitions(transition([State.POST, State.EnterBIOS], State.IdleWaitingForInput))
def go_idle(self): ...
# PROPERTIES GO HERE # PROPERTIES GO HERE
@property @property
def client_powered(self): def client_powered(self):
return esp32_serial.power_status return esp32_serial.usb_status
@property
def current_BIOS_location(self):
return self._current_BIOS_location
@current_BIOS_location.setter
def current_BIOS_location(self, value: str):
if type(value) == str:
self._current_BIOS_location = value
else:
raise ValueError("Attempted to set the current BIOS location to a non-string value!")
# STATE ENTRY FUNCTIONS
def on_enter_POST(self):
post_timer = time.time()
# If five minutes passes with no USB availability, something has gone terribly wrong...
while time.time() - post_timer <= 300 and not esp32_serial.usb_status:
pass
if not esp32_serial.usb_status:
self.unsuccessful_post()
else:
if self._enter_bios_flag:
self.enter_bios()
elif self._running_automatic:
self.wait_os()
else:
self.go_idle()
def on_enter_EnterBIOS(self):
# # Wait until the POST has progressed far enough for USB devices to be loaded and options to be imminent
# esp32_serial.notify_code = "45"
# esp32_serial.active_notification_request.set()
# esp32_serial.post_code_notify.wait()
# esp32_serial.post_code_notify.clear()
#
# # Spam delete until the BIOS is loaded
# esp32_serial.notify_code = "Ab"
# esp32_serial.active_notification_request.set()
# while not esp32_serial.post_code_notify.is_set():
spam_timer = time.time()
# Crushed by my lack of consistent access to BIOS post codes, we simply take our time...
while time.time() - spam_timer <= 10:
msg = {
"key_down": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
msg = {
"key_up": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
# esp32_serial.post_code_notify.clear()
# Wait a few seconds for the BIOS to become responsive
time.sleep(5)
self._enter_bios_flag = False
if self._running_automatic:
self.start_bios_setup()
else:
self.go_idle()
# STATE EXIT FUNCTIONS
def on_exit_PoweredOff(self):
self._power_switch(0.2)
# UTILITY FUNCTIONS GO HERE # UTILITY FUNCTIONS GO HERE
def _power_switch(self, delay: float): def _power_switch(self, delay: float):
@ -98,68 +189,30 @@ class Overclocking:
esp32_serial.mkb_queue.put(msg) esp32_serial.mkb_queue.put(msg)
# FUNCTIONS TRIGGERED BY STATE CHANGES # FUNCTIONS TRIGGERED BY STATE CHANGES
def _power_on(self):
self._power_switch(0.2)
# Unknown code definition, but this is the first consistent one indicating POST has started.
while esp32_serial.last_post_code != "FC":
pass
def _hard_shutdown(self): def _hard_shutdown(self):
self._power_switch(5) self._power_switch(5)
while self.client_powered:
pass
def _soft_shutdown(self): def _soft_shutdown(self):
self._power_switch(0.2) self._power_switch(0.2)
while self.client_powered: while esp32_serial.usb_status:
pass pass
def _enter_bios(self): # Wait a few seconds to REALLY be sure we're powered off...
# Wait until the POST has progressed far enough for USB devices to be loaded and options to be imminent time.sleep(10)
esp32_serial.notify_code = "45"
esp32_serial.active_notification_request.set()
esp32_serial.post_code_notify.wait()
esp32_serial.post_code_notify.clear()
# Spam delete until the BIOS is loaded
esp32_serial.notify_code = "Ab"
esp32_serial.active_notification_request.set()
while not esp32_serial.post_code_notify.is_set():
msg = {
"key_down": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
msg = {
"key_up": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
esp32_serial.post_code_notify.clear()
# Wait a few seconds for the BIOS to become responsive
time.sleep(5)
# OTHER FUNCTIONS GO HERE # OTHER FUNCTIONS GO HERE
def reboot_into_bios(self): def reboot_into_bios(self):
if self.client_powered: if esp32_serial.usb_status:
if self.state is State.IdleWaitingForInput: if self.state is State.IdleWaitingForInput:
self.soft_shutdown() self.soft_shutdown()
else: else:
self.hard_shutdown() self.hard_shutdown()
self._enter_bios_flag = True
self.power_on() self.power_on()
self.enter_bios()
@with_model_definitions @with_model_definitions
class MyMachine(GraphMachine): class MyMachine(GraphMachine):
pass pass
model = Overclocking()
machine = MyMachine(model, states=State, initial=model.state)
machine.get_graph().draw('my_state_diagram.svg', prog='dot')

View File

@ -14,7 +14,10 @@ function mkbhandler_load()
function keydown_handler(event) function keydown_handler(event)
{ {
socket.emit('key_down', event.code); if (event.code != "MetaLeft" && event.code != "MetaRight")
{
socket.emit('key_down', event.code);
}
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }

View File

@ -1,8 +1,9 @@
let code_mirror; let code_mirror;
let code_div;
function codemirror_load() function codemirror_load()
{ {
const code_div = document.getElementById('codemirror'); code_div = document.getElementById('codemirror');
code_mirror = CodeMirror(code_div, { code_mirror = CodeMirror(code_div, {
lineNumbers: true lineNumbers: true
@ -11,6 +12,19 @@ function codemirror_load()
socket.emit("get_current_profile", (data) => { socket.emit("get_current_profile", (data) => {
code_mirror.setValue(data) code_mirror.setValue(data)
}); });
code_div.addEventListener("mouseleave", disable_input);
code_div.addEventListener("mouseenter", enable_input);
}
function disable_input()
{
code_mirror.setOption("readOnly", "nocursor");
}
function enable_input()
{
code_mirror.setOption("readOnly", false);
} }
window.addEventListener("load", codemirror_load); window.addEventListener("load", codemirror_load);

View File

@ -12,9 +12,9 @@ function create_table(data) {
container.innerText = "" container.innerText = ""
Object.keys(data).forEach((key, index) => { Object.keys(data).forEach((key, index) => {
row_headers.push(key) col_headers.push(key)
Object.keys(data[key]).forEach((value, subIndex) => { Object.keys(data[key]).forEach((value, subIndex) => {
col_headers.push(value) row_headers.push(value)
}); });
}); });
@ -34,7 +34,7 @@ function update_core_info_table(data) {
hot.batch(() => { hot.batch(() => {
Object.keys(data).forEach((key, index) => { Object.keys(data).forEach((key, index) => {
Object.keys(data[key]).forEach((value, subIndex) => { Object.keys(data[key]).forEach((value, subIndex) => {
hot.setDataAtCell(index, subIndex, data[key][value]) hot.setDataAtCell(subIndex, index, data[key][value])
}); });
}); });
}); });

View File

@ -2,9 +2,9 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/vendor/socketio/socket.io.min.js') }}"></script> <script src="{{ url_for('static', filename='js/vendor/socketio/socket.io.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/SegmentDisplay/segment-display.js') }}"></script> <!-- <script src="{{ url_for('static', filename='js/vendor/SegmentDisplay/segment-display.js') }}"></script> -->
<script src="{{ url_for('static', filename='js/mkb_handler.js') }}"></script> <script src="{{ url_for('static', filename='js/mkb_handler.js') }}"></script>
<script src="{{ url_for('static', filename='js/seven_segment.js') }}"></script> <!-- <script src="{{ url_for('static', filename='js/seven_segment.js') }}"></script> -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/codemirror.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/codemirror.css') }}">
<script src="{{ url_for('static', filename='js/vendor/codemirror/codemirror.js') }}"></script> <script src="{{ url_for('static', filename='js/vendor/codemirror/codemirror.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/codemirror/toml/toml.js') }}"></script> <script src="{{ url_for('static', filename='js/vendor/codemirror/toml/toml.js') }}"></script>
@ -46,7 +46,7 @@
<div class="cm-editor"> <div class="cm-editor">
<div id="codemirror" class="cm-scroller"></div> <div id="codemirror" class="cm-scroller"></div>
</div> </div>
<div id="stats-table" class="ht-theme-main">Waiting for data...</div>
</div> </div>
<div class="right-third"> <div class="right-third">
<div class="row-flex-container"> <div class="row-flex-container">
@ -56,12 +56,13 @@
<button type="button" onclick="socket.emit(`reboot`);">Reboot</button> <button type="button" onclick="socket.emit(`reboot`);">Reboot</button>
<button type="button" onclick="socket.emit(`reboot_into_bios`);">Reboot into BIOS</button> <button type="button" onclick="socket.emit(`reboot_into_bios`);">Reboot into BIOS</button>
<button type="button" onclick="socket.emit(`clear_cmos`);">Clear CMOS</button> <button type="button" onclick="socket.emit(`clear_cmos`);">Clear CMOS</button>
<button type="button" onclick="socket.emit(`test_route`);">Test Route</button> <button type="button" onclick="socket.emit(`apply_current_bios_settings`);">Apply Current BIOS Settings</button>
</div> </div>
<div id="streamview" class="stream-container"> <div id="streamview" class="stream-container">
<img src="/video_feed" class="stream-view" /> <img src="/video_feed" class="stream-view" />
</div> </div>
<div class="row-flex-container right-third"> <div id="stats-table" class="ht-theme-main">Waiting for data...</div>
<!-- <div class="row-flex-container right-third">
<div id="post-log-container" class="post-log-container"></div> <div id="post-log-container" class="post-log-container"></div>
<div id="displayView" class="topic segment-container"> <div id="displayView" class="topic segment-container">
<div style="padding:20px"> <div style="padding:20px">
@ -71,7 +72,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->
</div> </div>
</div> </div>
</body> </body>

View File

@ -1,3 +1,5 @@
from . import hwinfo from . import hwinfo
from .mkb import events from .mkb import events
from .profiles import events from .profiles import events
__all__ = ["hwinfo", "events"]

View File

@ -1,70 +0,0 @@
import networkx as nx
from networkx import Graph
from typing import Any
from ipkvm.util import esp32_serial
from ipkvm.util.mkb import ASCII2JS
import time
# Type checker lunacy!
type MultiDiGraph = Graph[Any]
key_delay = 0.1
def traverse_path(graph: MultiDiGraph, node_a: str, node_b: str):
path = nx.shortest_path(graph, node_a, node_b)
path_edges = list(zip(path[:-1], path[1:]))
edge_path= [(u, v, graph[u][v]) for u, v in path_edges]
for step in edge_path:
if "initial_keypath" in step[2][0] and step[2][0]["visited"] == "false":
keys = step[2][0]["initial_keypath"].split(',')
# Type checker is simply wrong! This is the correct usage!
graph.edges[step[0], step[1], 0]["visited"] = "true" # type: ignore
else:
keys = step[2][0]["keypath"].split(',')
for key in keys:
time.sleep(key_delay)
esp32_serial.ez_press_key(key)
def apply_setting(graph: MultiDiGraph, setting_node: str, new_value: str):
if graph.nodes[setting_node]["option_type"] == "list":
possible_values = graph.nodes[setting_node]["options"].split(',')
key = graph.nodes[setting_node]["traversal_key"]
time.sleep(key_delay)
esp32_serial.ez_press_key("Enter")
for value in possible_values:
time.sleep(key_delay)
if value == new_value:
esp32_serial.ez_press_key("Enter")
break
else:
esp32_serial.ez_press_key(key)
elif graph.nodes[setting_node]["option_type"] == "field":
for key in new_value:
time.sleep(key_delay)
esp32_serial.ez_press_key(ASCII2JS[key])
time.sleep(key_delay)
esp32_serial.ez_press_key("Enter")
print(f"Changed {setting_node} from {graph.nodes[setting_node]["value"]} to {new_value}!")
graph.nodes[setting_node]["value"] = new_value
def test_route(settings: dict[Any, Any]):
graph: MultiDiGraph = nx.nx_agraph.read_dot("bios-maps/asrock/b650e-riptide-wifi.gv")
current_node = "Main"
for category in settings:
for setting_node in settings[category]:
if graph.nodes[setting_node]["value"] != settings[category][setting_node]:
traverse_path(graph, current_node, setting_node)
current_node = setting_node
apply_setting(graph, setting_node, settings[category][setting_node])

View File

@ -51,7 +51,7 @@ class HWInfoMonitor(threading.Thread):
temp_list.append(round(reading["value"], 2)) temp_list.append(round(reading["value"], 2))
elif match.group("core_vid"): elif match.group("core_vid"):
vid_list.append(reading["value"]) vid_list.append(round(reading["value"], 3))
elif match.group("core_mhz"): elif match.group("core_mhz"):
mhz_list.append(round(reading["value"], 2)) mhz_list.append(round(reading["value"], 2))
@ -70,7 +70,8 @@ class HWInfoMonitor(threading.Thread):
ui.emit("update_core_info_table", core_dataframe.to_dict("index")) ui.emit("update_core_info_table", core_dataframe.to_dict("index"))
except Exception as e: except Exception as e:
print(e) #print(e)
pass
def is_hwinfo_alive(self): def is_hwinfo_alive(self):
request = requests.get(self.request_url, timeout=1) request = requests.get(self.request_url, timeout=1)

View File

@ -1,15 +1,17 @@
from enum import IntEnum from enum import IntEnum
from os import name, listdir from os import name, listdir
import serial import serial
from ipkvm.app import logger, ui from ipkvm.app import logger
from ipkvm.util.profiles import profile_manager from ipkvm.util.profiles import profile_manager
import threading import threading
from queue import Queue from queue import Queue
import json import json
import networkx as nx
import time import time
from collections.abc import Mapping from collections.abc import Mapping
from .post_codes import POSTTextDef, POSTHex7Segment # from .post_codes import POSTTextDef, POSTHex7Segment
from .scancodes import HIDKeyCode from .scancodes import ASCII2JS, HIDKeyCode
from ipkvm.util.types import MultiDiGraph, OverclockingDict
class GPIO(IntEnum): class GPIO(IntEnum):
LOW = 0 LOW = 0
@ -18,13 +20,17 @@ class GPIO(IntEnum):
class Esp32Serial(threading.Thread): class Esp32Serial(threading.Thread):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.post_code_queue: Queue[str] = Queue() # self.post_code_queue: Queue[str] = Queue()
self.mkb_queue: Queue[Mapping[str, int | str | Mapping[str, int]]] = Queue() self.mkb_queue: Queue[Mapping[str, int | str | Mapping[str, int]]] = Queue()
self._power_status = False # self._power_status = False
self._last_post_code = "00" self._usb_status = False
self.notify_code: str self._last_usb_status = False
self.active_notification_request = threading.Event() # self._last_post_code = "00"
self.post_code_notify = threading.Event() # self.notify_code: str
# self.active_notification_request = threading.Event()
# self.post_code_notify = threading.Event()
self._key_delay = 0.2
self.start() self.start()
@ -48,19 +54,29 @@ class Esp32Serial(threading.Thread):
try: try:
line = json.loads(ser.readline().decode().strip()) line = json.loads(ser.readline().decode().strip())
if "pwr" in line: # self._power_status = line["pwr"]
self._power_status = line["pwr"] self._usb_status = line["usb"]
elif "post_code" in line: if self._usb_status != self._last_usb_status:
self._last_post_code = POSTHex7Segment[line["post_code"]] if self._usb_status:
logger.info("Client machine cleared POST.")
else:
logger.info("Client machine powered off.")
ui.emit("update_seven_segment", POSTHex7Segment[line["post_code"]]) self._last_usb_status = self._usb_status
ui.emit("update_post_log", f"{POSTTextDef[line["post_code"]]}: {POSTHex7Segment[line["post_code"]]}")
if self.active_notification_request.is_set(): # elif "post_code" in line:
if self._last_post_code == self.notify_code: # self._last_post_code = POSTHex7Segment[line["post_code"]]
self.post_code_notify.set() #
self.active_notification_request.clear() # ui.emit("update_seven_segment", POSTHex7Segment[line["post_code"]])
# ui.emit("update_post_log", f"{POSTTextDef[line["post_code"]]}: {POSTHex7Segment[line["post_code"]]}")
#
# if self.active_notification_request.is_set():
# if self._last_post_code == self.notify_code:
# self.post_code_notify.set()
# self.active_notification_request.clear()
#
# print(f"{POSTTextDef[line["post_code"]]}: {POSTHex7Segment[line["post_code"]]}")
except json.JSONDecodeError: except json.JSONDecodeError:
continue continue
@ -77,7 +93,7 @@ class Esp32Serial(threading.Thread):
bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE) bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE)
else: else:
raise RuntimeError("Your OS is unsupported!") raise RuntimeError("Your OS is unsupported at this time!")
def ez_press_key(self, key: str): def ez_press_key(self, key: str):
msg = msg = { msg = msg = {
@ -100,11 +116,72 @@ class Esp32Serial(threading.Thread):
serial_devices = [] serial_devices = []
return serial_devices return serial_devices
def _traverse_path(self, graph: MultiDiGraph, node_a: str, node_b: str):
path = nx.shortest_path(graph, node_a, node_b)
path_edges = list(zip(path[:-1], path[1:]))
edge_path= [(u, v, graph[u][v]) for u, v in path_edges]
@property for step in edge_path:
def power_status(self): if "initial_keypath" in step[2][0] and step[2][0]["visited"] == "false":
return self._power_status keys = step[2][0]["initial_keypath"].split(',')
# Type checker is simply wrong! This is the correct usage!
graph.edges[step[0], step[1], 0]["visited"] = "true" # type: ignore
else:
keys = step[2][0]["keypath"].split(',')
for key in keys:
time.sleep(self._key_delay)
self.ez_press_key(key)
def _apply_setting(self, graph: MultiDiGraph, setting_node: str, new_value: str):
if graph.nodes[setting_node]["option_type"] == "list":
possible_values = graph.nodes[setting_node]["options"].split(',')
key = graph.nodes[setting_node]["traversal_key"]
time.sleep(self._key_delay)
self.ez_press_key("Enter")
for value in possible_values:
time.sleep(self._key_delay)
if value == new_value:
self.ez_press_key("Enter")
break
else:
self.ez_press_key(key)
elif graph.nodes[setting_node]["option_type"] == "field":
for key in new_value:
time.sleep(self._key_delay)
self.ez_press_key(ASCII2JS[key])
time.sleep(self._key_delay)
self.ez_press_key("Enter")
logger.info(f"Changed {setting_node} from {graph.nodes[setting_node]["value"]} to {new_value}!")
graph.nodes[setting_node]["value"] = new_value
def apply_all_settings(self, settings: OverclockingDict, graph: MultiDiGraph, current_node: str):
for category in settings:
for setting_node in settings[category]:
if graph.nodes[setting_node]["value"] != settings[category][setting_node]:
self._traverse_path(graph, current_node, setting_node)
current_node = setting_node
self._apply_setting(graph, setting_node, settings[category][setting_node])
return current_node
# @property
# def power_status(self):
# return self._power_status
@property @property
def last_post_code(self): def usb_status(self):
return self._last_post_code return self._usb_status
# @property
# def last_post_code(self):
# return self._last_post_code

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
import tomlkit import tomlkit
from ipkvm.app import ui from ipkvm.app import ui
from . import profile_manager from . import profile_manager
from ipkvm.util.mkb import esp32_serial
from ipkvm.states import model
@ui.on("get_current_profile") @ui.on("get_current_profile")
def handle_current_profile(): def handle_current_profile():
@ -12,4 +14,9 @@ def handle_save_profile(data: str):
@ui.on("save_profile_as") @ui.on("save_profile_as")
def handle_save_profile_as(data: str, name: str): def handle_save_profile_as(data: str, name: str):
profile_manager.save_profile(tomlkit.parse(data), name) # type: ignore profile_manager.save_profile(tomlkit.parse(data), name) # type: ignore
@ui.on("apply_current_bios_settings")
def handle_bios_settings():
model.current_BIOS_location = esp32_serial.apply_all_settings(profile_manager.profile["client"]["overclocking"],
profile_manager.bios_map, model.current_BIOS_location)

View File

@ -1,26 +1,10 @@
from networkx import nx_agraph
from os import listdir from os import listdir
from os.path import exists
import threading import threading
import tomlkit import tomlkit
from ipkvm.app import logger, ui from ipkvm.app import logger
from typing import TypedDict from ipkvm.util.types import MultiDiGraph, ProfileDict
class VideoDict(TypedDict):
friendly_name: str
resolution: str
fps: str
class ServerDict(TypedDict):
esp32_serial: str
video_device: VideoDict
class ClientDict(TypedDict):
hostname: str
hwinfo_port: str
overclocking: dict[str, dict[str, str]]
class ProfileDict(TypedDict):
server: ServerDict
client: ClientDict
class ProfileManager(): class ProfileManager():
def __init__(self): def __init__(self):
@ -29,6 +13,7 @@ class ProfileManager():
self.restart_hwinfo = threading.Event() self.restart_hwinfo = threading.Event()
self._cur_profile_name: str = "" self._cur_profile_name: str = ""
self._profiles = listdir("profiles") self._profiles = listdir("profiles")
self._bios_map: MultiDiGraph
if len(self._profiles) == 0: if len(self._profiles) == 0:
logger.info("No profiles found, loading default profile.") logger.info("No profiles found, loading default profile.")
@ -50,6 +35,9 @@ class ProfileManager():
with open(f"profiles/{name}", 'r') as file: with open(f"profiles/{name}", 'r') as file:
self._cur_profile_name = name self._cur_profile_name = name
self._profile = tomlkit.parse(file.read()) # type: ignore self._profile = tomlkit.parse(file.read()) # type: ignore
if exists(self._profile["client"]["bios_map_path"]):
self._bios_map = nx_agraph.read_dot(self._profile["client"]["bios_map_path"])
self.notify_all() self.notify_all()
def save_profile(self, new_profile: ProfileDict, name: str = ""): def save_profile(self, new_profile: ProfileDict, name: str = ""):
@ -94,3 +82,7 @@ class ProfileManager():
@property @property
def profile(self): def profile(self):
return self._profile return self._profile
@property
def bios_map(self):
return self._bios_map

View File

@ -0,0 +1,31 @@
from networkx import Graph
from typing import Any, TypedDict
# Type checker lunacy!
type MultiDiGraph = Graph[Any]
class VideoDict(TypedDict):
friendly_name: str
resolution: str
fps: str
class ServerDict(TypedDict):
esp32_serial: str
video_device: VideoDict
class OverclockingDict(TypedDict):
common: dict[str, str]
cpu: dict[str, str]
memory: dict[str, str]
class ClientDict(TypedDict):
hostname: str
hwinfo_port: str
ryzen_smu_cli_path: str
ycruncher_path: str
bios_map_path: str
overclocking: OverclockingDict
class ProfileDict(TypedDict):
server: ServerDict
client: ClientDict