diff --git a/Makefile b/Makefile index c1993bb9..4ab95c62 100755 --- a/Makefile +++ b/Makefile @@ -37,8 +37,8 @@ include $(DEVKITPRO)/libnx/switch_rules # of a homebrew executable (.nro). This is intended to be used for sysmodules. # NACP building is skipped as well. #--------------------------------------------------------------------------------- -APP_TITLE := Ultra Monitor -APP_VERSION := 1.0.1 +APP_TITLE := Status Monitor +APP_VERSION := 1.0.3 TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source diff --git a/config/status-monitor/config.ini.template b/config/status-monitor/config.ini.template index f5220354..c143e078 100644 --- a/config/status-monitor/config.ini.template +++ b/config/status-monitor/config.ini.template @@ -1,5 +1,7 @@ [status-monitor] key_combo=L+R+DUP +battery_avg_iir_filter=false +battery_time_left_refreshrate=60 [full] refresh_rate=1 @@ -51,5 +53,5 @@ fps_counter_color=#4444 border_color=#F77F dashed_line_color=#8888 main_line_color=#FFFF -rounded_line_color=#0C0F -perfect_line_color=#F0FF \ No newline at end of file +rounded_line_color=#F0FF +perfect_line_color=#0C0F diff --git a/docs/config.md b/docs/config.md index 13c04f97..31aaa557 100644 --- a/docs/config.md +++ b/docs/config.md @@ -12,6 +12,9 @@ Colors are provided in RGBA4444 format, which means that each character represen | Key | Explanation | Possible values | Default Value | |-----|-------------|-----------------|---------------| | `key_combo` | Buttons combination that allows exiting Full, Mini and Micro modes; max 4 buttons, otherwise next buttons will be ignored. Combine different buttons with `+` | `A`, `B`, `X`, `Y`, `L`, `R`, `ZL`, `ZR`, `PLUS`, `MINUS`, `DUP`, `DDOWN`, `DLEFT`, `DRIGHT`, `SL`, `SR`, `LSTICK`, `RSTICK`, `UP`, `DOWN`, `LEFT`, `RIGHT` | `L+DDOWN+RSTICK` | +| `battery_avg_iir_filter` | Read voltage + current averages directly from fuel gauge, that uses infinite impulse response filter | `true`, `false` | `false` | +| `battery_time_left_refreshrate` | How many seconds must pass to refresh Battery Remaining Time | from `1` to `60` | `60` | + > [full] diff --git a/docs/modes.md b/docs/modes.md index df446801..aed63caf 100755 --- a/docs/modes.md +++ b/docs/modes.md @@ -9,15 +9,27 @@ For additional functions you need to install: This mode you can know from older releases of Status Monitor. It contains all informations properly described and supported with high precision. -| Category | Format | Explanation | -|-----------|-------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| CPU Usage | Frequency: %.1f (Δ%+.1f)
Core #0: %.2f
Core #1: %.2f
Core #2: %.2f
Core #3: %.2f | Targete clockrate of all CPU cores in MHz (^1)
Load of CPU Core #0 calculated from IdleTickCount to percent value
Load of CPU Core #1 calculated from IdleTickCount to percent value
Load of CPU Core #2 calculated from IdleTickCount to percent value
Load of CPU Core #3 calculated from IdleTickCount to percent value | -| GPU Usage | Frequency: %.1f (Δ%+.1f)
Load: %.1f | Target clockrate of GPU in MHz (^1)
GPU Load provided by PMU in percent | -| RAM Usage | - Real Frequency: %.1f (Δ%+.1f)
- Target Frequency: %.1f
- Load: %.1f (CPU %.1f \| GPU %.1f)`^1`
- %s: %.2f/%.2f | - Real clockrate of EMC in MHz `(^1)`
- Target clockrate of EMC in MHz
- RAM Load in % (Which part of that are CPU and GPU (with other hardware, but their impact on GPU readings is negligible) `(^1)`
- %s memory used/%s memory available in MB (not working with FW <5.0.0) | -| Board | Battery Power Flow: %+.2f[h:mm]
Temperatures:
- SoC: %.1f
- PCB: %.1f
- Skin: %.1f
Fan Rotation Level: %.1f | How much power in watts is discharged from or charged to the battery [time left before shutdown]
SoC temperature in Celsius degrees
PCB temperature in Celsius degrees
Skin temperature in Celsius degrees (^2)
Fan rotation level in percent | - -- ^1 - This shows only when sys-clk 2.0.0_rc4+ is installed. -- ^2 - Explanation provided at the end of file +- CPU Usage + - Real Frequency: `%.1f` = Real clockrate of all CPU cores in MHz (This shows only when sys-clk 2.0.0_4c+ is installed) + - Target Frequency: `%.1f` = Target clockrate of all CPU cores in MHz + - Core #0-#3: `%.2f` = Load of CPU Cores calculated from IdleTickCount to percent value + +- GPU Usage + - Real Frequency: `%.1f` = Real clockrate of GPU in MHz (This shows only when sys-clk 2.0.0_rc4+ is installed) + - Target Frequency: `%.1f` = Target clockrate of GPU in MHz + - Load: `%.1f` = GPU Load provided by PMU in percent + +- RAM Usage + - Real Frequency: `%.1f` = Real clockrate of EMC in MHz (This shows only when sys-clk 2.0.0_rc4+ is installed) + - Target Frequency: `%.1f` = Target clockrate of EMC in MHz + - Load: `%.1f` (CPU `%.1f` | GPU `%.1f`) = RAM Load in % (Which part of that are CPU and GPU (with other hardware, but their impact on GPU readings is negligible)) + - `%s`: `%.2f`/`%.2f` = %s memory used/%s memory available in MB (not working with FW <5.0.0) + +- Board + - Battery Power Flow: `%+.2f`[h:mm] = How much power in watts is discharged from or charged to the battery [time left before shutdown] + - Temperatures: SoC: `%.1f` / PCB: `%.1f` / Skin: `%.1f` = SoC / PCB / Skin temperature in Celsius degrees (Explanation provided at the end of file) + - Fan Rotation Level: `%.1f` = Fan rotation level in percent + ```Optional (shows only when SaltyNX is installed and game is running)``` @@ -102,14 +114,15 @@ Mode available only with SaltyNX installed. > Battery -| Category | Format | Explanation | -|---------------------------------|-----------|-----------------------------------------------------------------------------------------------| -| Battery Temperature | %.2f | Battery temperature in Celsius | -| Battery Raw Charge | %.2f | Raw battery charged capacity in percent | -| Battery Voltage (AVG of 5) | %.2f | Battery average voltage in mV taken from 5 readings in period of 5 seconds | -| Battery Current Flow (AVG of 5) | %+.2f | Battery average current flow in mA taken from 5 readings in period of 5 seconds | -| Battery Power Flow (AVG of 5) | %+.3f | Battery average power flow in W calciulated from Battery Voltage and Battery Current Flow | -| Battery Remaining Time | h:mm | How much time is left before shutdown | +- Battery Actual Capacity: `%d` = Battery Designed Capacity multiplied by Battery Age in mAh +- Battery Designed Capacity: `%d` = Battery capacity targeted by manufacturer in mAh +- Battery Temperature: `%.1f` = Battery temperature in Celsius +- Battery Raw Charge: `%.1f` = Raw battery charged capacity in percent +- Battery Age: `%.1f` = How much of designed capacity was charged last time battery was charged completely in percent +- Battery Voltage: `%.0f` = Battery average voltage in mV (time period: 5s, or with `battery_avg_iir_filter` enabled: 45s) +- Battery Current Flow: `%+.0f` = Battery average current flow in mA (time period: 5s, or with `battery_avg_iir_filter` enabled: 11.25s) +- Battery Power Flow: `%+.3f` = Battery average power flow in W calculated from Battery Voltage and Battery Current Flow +- Battery Remaining Time: h:mm - How much time is left before shutdown Shows only if charger is connected: | Category | Format | Explanation | diff --git a/include/i2c.h b/include/i2c.h index 762d841b..32a21e43 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -10,9 +10,13 @@ constexpr float max17050CGain = 1.99993; Result I2cReadRegHandler(u8 reg, I2cDevice dev, u16 *out) { - // I2C Bus Communication Reference: https://www.ti.com/lit/an/slva704/slva704.pdf - struct { u8 reg; } __attribute__((packed)) cmd; - struct { u16 val; } __attribute__((packed)) rec; + struct readReg { + u8 send; + u8 sendLength; + u8 sendData; + u8 receive; + u8 receiveLength; + }; I2cSession _session; @@ -20,37 +24,38 @@ Result I2cReadRegHandler(u8 reg, I2cDevice dev, u16 *out) if (res) return res; - cmd.reg = reg; - res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All); - if (res) - { - i2csessionClose(&_session); - return res; - } + u16 val; - res = i2csessionReceiveAuto(&_session, &rec, sizeof(rec), I2cTransactionOption_All); + struct readReg readRegister = { + .send = 0 | (I2cTransactionOption_Start << 6), + .sendLength = sizeof(reg), + .sendData = reg, + .receive = 1 | (I2cTransactionOption_All << 6), + .receiveLength = sizeof(val), + }; + + res = i2csessionExecuteCommandList(&_session, &val, sizeof(val), &readRegister, sizeof(readRegister)); if (res) { i2csessionClose(&_session); return res; } - *out = rec.val; + *out = val; i2csessionClose(&_session); return 0; } -bool Max17050ReadReg(u8 reg, u16 *out) +Result Max17050ReadReg(u8 reg, u16 *out) { u16 data = 0; Result res = I2cReadRegHandler(reg, I2cDevice_Max17050, &data); - if (res) + if (R_FAILED(res)) { - *out = res; - return false; + return res; } *out = data; - return true; -} \ No newline at end of file + return res; +} diff --git a/include/max17050.h b/include/max17050.h index 07e42136..c56ab9ba 100644 --- a/include/max17050.h +++ b/include/max17050.h @@ -42,6 +42,8 @@ #define MAXIM17050_I2C_ADDR 0x36 */ +#define MAX17050_WAIT_NS 1175800000 + enum MAX17050_reg { MAX17050_STATUS = 0x00, diff --git a/source/Utils.hpp b/source/Utils.hpp index c9446904..8ec4d3b4 100644 --- a/source/Utils.hpp +++ b/source/Utils.hpp @@ -33,7 +33,7 @@ Thread t3; Thread t4; Thread t6; Thread t7; -uint64_t systemtickfrequency = 19200000; +const uint64_t systemtickfrequency = 19200000; bool threadexit = false; bool threadexit2 = false; FanController g_ICon; @@ -89,6 +89,8 @@ float PowerConsumption = 0; int16_t batTimeEstimate = -1; float actualFullBatCapacity = 0; float designedFullBatCapacity = 0; +bool batteryFiltered = false; +uint8_t batteryTimeLeftRefreshRate = 60; //Temperatures float SOC_temperatureF = 0; @@ -239,133 +241,124 @@ void CheckIfGameRunning(void*) { } } +Mutex mutex_BatteryChecker = {0}; void BatteryChecker(void*) { - if (R_SUCCEEDED(psmCheck)){ - uint16_t data = 0; - float tempV = 0; - float tempA = 0; - size_t ArraySize = 10; - size_t CommonPowerAvgHistorySize = 3; // last 3 min history - size_t TmpPowerHistoryArraySize = 120; // last 60 sec history - float readingsAmp[ArraySize] = {0}; - float readingsVolt[ArraySize] = {0}; - std::vector commonAvgPowerHistory; // common avg history - float tmpPowerHistory[TmpPowerHistoryArraySize] = {0}; - - if (Max17050ReadReg(MAX17050_Current, &data)) { - tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - for (size_t i = 0; i < ArraySize; i++) { - readingsAmp[i] = tempA; - } - } - svcSleepThread(1000000); - if (Max17050ReadReg(MAX17050_VCELL, &data)) { - tempV = 0.625 * (data >> 3); - for (size_t i = 0; i < ArraySize; i++) { - readingsVolt[i] = tempV; - } - } - svcSleepThread(1000000); - if (!actualFullBatCapacity && Max17050ReadReg(MAX17050_FullCAP, &data)) { - actualFullBatCapacity = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; - } - svcSleepThread(1000000); - if (!designedFullBatCapacity && Max17050ReadReg(MAX17050_DesignCap, &data)) { - designedFullBatCapacity = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; - } - svcSleepThread(1000000); - size_t i = 0; - size_t powerHistoryIteration = 0; - int tempChargerType = 0; - if (!Max17050ReadReg(MAX17050_AvgCurrent, &data) && (s16)data > 0) { - float tmpCurrentAvg = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - while (powerHistoryIteration < 20) - tmpPowerHistory[powerHistoryIteration++] = tmpCurrentAvg; + if (R_FAILED(psmCheck)){ + return; + } + uint16_t data = 0; + float tempV = 0.0; + float tempA = 0.0; + size_t ArraySize = 10; + if (batteryFiltered) { + ArraySize = 1; + } + float* readingsAmp = new float[ArraySize]; + float* readingsVolt = new float[ArraySize]; + + Max17050ReadReg(MAX17050_AvgCurrent, &data); + tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; + for (size_t i = 0; i < ArraySize; i++) { + readingsAmp[i] = tempA; + } + Max17050ReadReg(MAX17050_AvgVCELL, &data); + tempV = 0.625 * (data >> 3); + for (size_t i = 0; i < ArraySize; i++) { + readingsVolt[i] = tempV; + } + if (!actualFullBatCapacity) { + Max17050ReadReg(MAX17050_FullCAP, &data); + actualFullBatCapacity = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; + } + if (!designedFullBatCapacity) { + Max17050ReadReg(MAX17050_DesignCap, &data); + designedFullBatCapacity = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; + } + if (readingsAmp[0] >= 0) { + batTimeEstimate = -1; + } + else { + Max17050ReadReg(MAX17050_TTE, &data); + float batteryTimeEstimateInMinutes = (5.625 * data) / 60; + if (batteryTimeEstimateInMinutes > (99.0*60.0)+59.0) { + batTimeEstimate = (99*60)+59; } + else batTimeEstimate = (int16_t)batteryTimeEstimateInMinutes; + } + + size_t counter = 0; + uint64_t tick_TTE = svcGetSystemTick(); + while (!threadexit) { + mutexLock(&mutex_BatteryChecker); + uint64_t startTick = svcGetSystemTick(); - while (!threadexit) { - svcSleepThread(1000000); - psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields); - // Calculation is based on Hekate's max17050.c - // Source: https://github.com/CTCaer/hekate/blob/master/bdk/power/max17050.c - if (!Max17050ReadReg(MAX17050_Current, &data)) - continue; - svcSleepThread(1000000); + psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields); + + // Calculation is based on Hekate's max17050.c + // Source: https://github.com/CTCaer/hekate/blob/master/bdk/power/max17050.c + + if (!batteryFiltered) { + Max17050ReadReg(MAX17050_Current, &data); + tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; + Max17050ReadReg(MAX17050_VCELL, &data); + tempV = 0.625 * (data >> 3); + } else { + Max17050ReadReg(MAX17050_AvgCurrent, &data); tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - if (!Max17050ReadReg(MAX17050_VCELL, &data)) - continue; - svcSleepThread(1000000); + Max17050ReadReg(MAX17050_AvgVCELL, &data); tempV = 0.625 * (data >> 3); + } - readingsAmp[i] = tempA; - readingsVolt[i] = tempV; - if (i+1 < ArraySize) { - i++; - } - else i = 0; - - float batCurrent = readingsAmp[0]; - float batVoltage = readingsVolt[0]; - float batPowerAvg = (readingsAmp[0] * readingsVolt[0]) / 1'000; - for (size_t x = 1; x < ArraySize; x++) { - batCurrent += readingsAmp[x]; - batVoltage += readingsVolt[x]; - batPowerAvg += (readingsAmp[x] * readingsVolt[x]) / 1'000; - } - float actualCapacity = actualFullBatCapacity / 100 * (float)_batteryChargeInfoFields.RawBatteryCharge / 1000; - batCurrent /= ArraySize; - batVoltage /= ArraySize; - batCurrentAvg = batCurrent; - batVoltageAvg = batVoltage; - batPowerAvg /= ArraySize * 1000; - PowerConsumption = batPowerAvg; - bool chargerTypeDifferent = (tempChargerType != _batteryChargeInfoFields.ChargerType); - if (hosversionAtLeast(17,0,0)) { - chargerTypeDifferent = (tempChargerType != ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields) -> ChargerType); - } - if (chargerTypeDifferent) { - powerHistoryIteration = 0; - batTimeEstimate = -1; - tempChargerType = _batteryChargeInfoFields.ChargerType; - if (hosversionAtLeast(17,0,0)) { - tempChargerType = ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields) -> ChargerType; - } - commonAvgPowerHistory.clear(); - commonAvgPowerHistory.shrink_to_fit(); - } - else if (batCurrentAvg < 0) { - tmpPowerHistory[powerHistoryIteration++] = batCurrentAvg; // add currentAvg to tmp array - if (powerHistoryIteration == TmpPowerHistoryArraySize) { - if (commonAvgPowerHistory.size() == CommonPowerAvgHistorySize) { - commonAvgPowerHistory.erase(commonAvgPowerHistory.begin()); - } - float tmpPowerSum = std::accumulate(tmpPowerHistory, tmpPowerHistory+TmpPowerHistoryArraySize, 0); - commonAvgPowerHistory.push_back(tmpPowerSum / TmpPowerHistoryArraySize); - float commonPowerSum = std::accumulate(commonAvgPowerHistory.begin(), commonAvgPowerHistory.end(), 0); - float commonAvg = -commonPowerSum / commonAvgPowerHistory.size(); - batTimeEstimate = (int)(actualCapacity / (commonAvg / 60)); - if (batTimeEstimate > (99*60)+59) - batTimeEstimate = (99*60)+59; - powerHistoryIteration = 0; - } - else if (commonAvgPowerHistory.size() == 0 && powerHistoryIteration < TmpPowerHistoryArraySize) { - float PowerSum = std::accumulate(tmpPowerHistory, tmpPowerHistory+powerHistoryIteration, 0); - float commonAvg = -PowerSum / powerHistoryIteration; - batTimeEstimate = (int)(actualCapacity / (commonAvg / 60)); - if (batTimeEstimate > (99*60)+59) - batTimeEstimate = (99*60)+59; - } + if (tempA && tempV) { + readingsAmp[counter % ArraySize] = tempA; + readingsVolt[counter % ArraySize] = tempV; + counter++; + } + + float batCurrent = 0.0; + float batVoltage = 0.0; + float batPowerAvg = 0.0; + for (size_t x = 0; x < ArraySize; x++) { + batCurrent += readingsAmp[x]; + batVoltage += readingsVolt[x]; + batPowerAvg += (readingsAmp[x] * readingsVolt[x]) / 1'000; + } + batCurrent /= ArraySize; + batVoltage /= ArraySize; + batCurrentAvg = batCurrent; + batVoltageAvg = batVoltage; + batPowerAvg /= ArraySize * 1000; + PowerConsumption = batPowerAvg; + + if (batCurrentAvg >= 0) { + batTimeEstimate = -1; + } + else { + static float batteryTimeEstimateInMinutes = 0; + Max17050ReadReg(MAX17050_TTE, &data); + batteryTimeEstimateInMinutes = (5.625 * data) / 60; + if (batteryTimeEstimateInMinutes > (99.0*60.0)+59.0) { + batteryTimeEstimateInMinutes = (99.0*60.0)+59.0; } - else { - powerHistoryIteration = 0; - batTimeEstimate = -1; + uint64_t new_tick_TTE = svcGetSystemTick(); + if (armTicksToNs(new_tick_TTE - tick_TTE) / 1'000'000'000 >= batteryTimeLeftRefreshRate) { + batTimeEstimate = (int16_t)batteryTimeEstimateInMinutes; + tick_TTE = new_tick_TTE; } - svcSleepThread(499'000'000); } - _batteryChargeInfoFields = {0}; - commonAvgPowerHistory.clear(); - commonAvgPowerHistory.shrink_to_fit(); + + mutexUnlock(&mutex_BatteryChecker); + uint64_t nanosecondsPassed = armTicksToNs(svcGetSystemTick() - startTick); + if (nanosecondsPassed < 1'000'000'000 / 2) { + svcSleepThread((1'000'000'000 / 2) - nanosecondsPassed); + } else { + svcSleepThread(1'000); + } } + batTimeEstimate = -1; + _batteryChargeInfoFields = {0}; + delete[] readingsAmp; + delete[] readingsVolt; } void StartBatteryThread() { @@ -373,10 +366,11 @@ void StartBatteryThread() { threadStart(&t7); } +Mutex mutex_Misc = {0}; //Stuff that doesn't need multithreading void Misc(void*) { while (!threadexit) { - + mutexLock(&mutex_Misc); // CPU, GPU and RAM Frequency if (R_SUCCEEDED(clkrstCheck)) { ClkrstSession clkSession; @@ -468,6 +462,7 @@ void Misc(void*) { FPSmax = 0; } // Interval + mutexUnlock(&mutex_Misc); svcSleepThread(100'000'000); } } @@ -494,10 +489,12 @@ void Misc2(void*) { } //Check each core for idled ticks in intervals, they cannot read info about other core than they are assigned +//In case of getting more than systemtickfrequency in idle, make it equal to systemtickfrequency to get 0% as output and nothing less +//This is because making each loop also takes time, which is not considered because this will take also additional time void CheckCore0(void*) { while (!threadexit) { - static uint64_t idletick_a0 = 0; - static uint64_t idletick_b0 = 0; + uint64_t idletick_a0 = 0; + uint64_t idletick_b0 = 0; svcGetInfo(&idletick_b0, InfoType_IdleTickCount, INVALID_HANDLE, 0); svcSleepThread(1'000'000'000 / TeslaFPS); svcGetInfo(&idletick_a0, InfoType_IdleTickCount, INVALID_HANDLE, 0); @@ -507,8 +504,8 @@ void CheckCore0(void*) { void CheckCore1(void*) { while (!threadexit) { - static uint64_t idletick_a1 = 0; - static uint64_t idletick_b1 = 0; + uint64_t idletick_a1 = 0; + uint64_t idletick_b1 = 0; svcGetInfo(&idletick_b1, InfoType_IdleTickCount, INVALID_HANDLE, 1); svcSleepThread(1'000'000'000 / TeslaFPS); svcGetInfo(&idletick_a1, InfoType_IdleTickCount, INVALID_HANDLE, 1); @@ -518,8 +515,8 @@ void CheckCore1(void*) { void CheckCore2(void*) { while (!threadexit) { - static uint64_t idletick_a2 = 0; - static uint64_t idletick_b2 = 0; + uint64_t idletick_a2 = 0; + uint64_t idletick_b2 = 0; svcGetInfo(&idletick_b2, InfoType_IdleTickCount, INVALID_HANDLE, 2); svcSleepThread(1'000'000'000 / TeslaFPS); svcGetInfo(&idletick_a2, InfoType_IdleTickCount, INVALID_HANDLE, 2); @@ -529,13 +526,12 @@ void CheckCore2(void*) { void CheckCore3(void*) { while (!threadexit) { - static uint64_t idletick_a3 = 0; - static uint64_t idletick_b3 = 0; + uint64_t idletick_a3 = 0; + uint64_t idletick_b3 = 0; svcGetInfo(&idletick_b3, InfoType_IdleTickCount, INVALID_HANDLE, 3); svcSleepThread(1'000'000'000 / TeslaFPS); svcGetInfo(&idletick_a3, InfoType_IdleTickCount, INVALID_HANDLE, 3); idletick3 = idletick_a3 - idletick_b3; - } } @@ -692,65 +688,58 @@ void formatButtonCombination(std::string& line) { } } +uint64_t MapButtons(const std::string& buttonCombo) { + std::map buttonMap = { + {"A", HidNpadButton_A}, + {"B", HidNpadButton_B}, + {"X", HidNpadButton_X}, + {"Y", HidNpadButton_Y}, + {"L", HidNpadButton_L}, + {"R", HidNpadButton_R}, + {"ZL", HidNpadButton_ZL}, + {"ZR", HidNpadButton_ZR}, + {"PLUS", HidNpadButton_Plus}, + {"MINUS", HidNpadButton_Minus}, + {"DUP", HidNpadButton_Up}, + {"DDOWN", HidNpadButton_Down}, + {"DLEFT", HidNpadButton_Left}, + {"DRIGHT", HidNpadButton_Right}, + {"SL", HidNpadButton_AnySL}, + {"SR", HidNpadButton_AnySR}, + {"LSTICK", HidNpadButton_StickL}, + {"RSTICK", HidNpadButton_StickR}, + {"UP", HidNpadButton_Up}, + {"DOWN", HidNpadButton_Down}, + {"LEFT", HidNpadButton_Left}, + {"RIGHT", HidNpadButton_Right} + }; -// Base class with virtual function -class ButtonMapper { -public: - virtual std::list MapButtons(const std::string& buttonCombo) = 0; -}; + uint64_t comboBitmask = 0; + std::string comboCopy = buttonCombo; // Make a copy of buttonCombo -// Derived class implementing the virtual function -class ButtonMapperImpl : public ButtonMapper { -public: - std::list MapButtons(const std::string& buttonCombo) override { - std::map buttonMap = { - {"A", static_cast(HidNpadButton_A)}, - {"B", static_cast(HidNpadButton_B)}, - {"X", static_cast(HidNpadButton_X)}, - {"Y", static_cast(HidNpadButton_Y)}, - {"L", static_cast(HidNpadButton_L)}, - {"R", static_cast(HidNpadButton_R)}, - {"ZL", static_cast(HidNpadButton_ZL)}, - {"ZR", static_cast(HidNpadButton_ZR)}, - {"PLUS", static_cast(HidNpadButton_Plus)}, - {"MINUS", static_cast(HidNpadButton_Minus)}, - {"DUP", static_cast(HidNpadButton_Up)}, - {"DDOWN", static_cast(HidNpadButton_Down)}, - {"DLEFT", static_cast(HidNpadButton_Left)}, - {"DRIGHT", static_cast(HidNpadButton_Right)}, - {"SL", static_cast(HidNpadButton_AnySL)}, - {"SR", static_cast(HidNpadButton_AnySR)}, - {"LSTICK", static_cast(HidNpadButton_StickL)}, - {"RSTICK", static_cast(HidNpadButton_StickR)}, - {"UP", static_cast(HidNpadButton_Up | HidNpadButton_StickLUp | HidNpadButton_StickRUp)}, - {"DOWN", static_cast(HidNpadButton_Down | HidNpadButton_StickLDown | HidNpadButton_StickRDown)}, - {"LEFT", static_cast(HidNpadButton_Left | HidNpadButton_StickLLeft | HidNpadButton_StickRLeft)}, - {"RIGHT", static_cast(HidNpadButton_Right | HidNpadButton_StickLRight | HidNpadButton_StickRRight)} - }; - - std::list mappedButtons; - std::string comboCopy = buttonCombo; // Make a copy of buttonCombo - - std::string delimiter = "+"; - size_t pos = 0; - std::string button; - size_t max_delimiters = 4; - while ((pos = comboCopy.find(delimiter)) != std::string::npos) { - button = comboCopy.substr(0, pos); - if (buttonMap.find(button) != buttonMap.end()) { - mappedButtons.push_back(buttonMap[button]); - } - comboCopy.erase(0, pos + delimiter.length()); - if(!--max_delimiters) { - return mappedButtons; - } + std::string delimiter = "+"; + size_t pos = 0; + std::string button; + size_t max_delimiters = 4; + while ((pos = comboCopy.find(delimiter)) != std::string::npos) { + button = comboCopy.substr(0, pos); + if (buttonMap.find(button) != buttonMap.end()) { + comboBitmask |= buttonMap[button]; } - if (buttonMap.find(comboCopy) != buttonMap.end()) { - mappedButtons.push_back(buttonMap[comboCopy]); + comboCopy.erase(0, pos + delimiter.length()); + if (!--max_delimiters) { + return comboBitmask; } - return mappedButtons; } -}; + if (buttonMap.find(comboCopy) != buttonMap.end()) { + comboBitmask |= buttonMap[comboCopy]; + } + return comboBitmask; +} + +static inline bool isKeyComboPressed(uint64_t keysHeld, uint64_t keysDown, uint64_t comboBitmask) { + return (keysDown == comboBitmask) || (keysHeld == comboBitmask); +} // Custom utility function for parsing an ini file void ParseIniFile() { @@ -778,26 +767,44 @@ void ParseIniFile() { long fileSize = ftell(configFileIn); rewind(configFileIn); - // Read the contents of the INI file - char* fileData = new char[fileSize + 1]; - fread(fileData, sizeof(char), fileSize, configFileIn); - fileData[fileSize] = '\0'; // Add null-terminator to create a C-string - fclose(configFileIn); - // Parse the INI data - std::string fileDataString(fileData, fileSize); + std::string fileDataString(fileSize, '\0'); + fread(&fileDataString[0], sizeof(char), fileSize, configFileIn); + fclose(configFileIn); + parsedData = tsl::hlp::ini::parseIni(fileDataString); - delete[] fileData; // Access and use the parsed data as needed // For example, print the value of a specific section and key - if (parsedData.find("status-monitor") != parsedData.end() && - parsedData["status-monitor"].find("key_combo") != parsedData["status-monitor"].end()) { - keyCombo = parsedData["status-monitor"]["key_combo"]; // load keyCombo variable - removeSpaces(keyCombo); // format combo - convertToUpper(keyCombo); - } else { - readExternalCombo = true; + if (parsedData.find("status-monitor") != parsedData.end()) { + if (parsedData["status-monitor"].find("key_combo") != parsedData["status-monitor"].end()) { + keyCombo = parsedData["status-monitor"]["key_combo"]; // load keyCombo variable + removeSpaces(keyCombo); // format combo + convertToUpper(keyCombo); + } + else { + readExternalCombo = true; + } + if (parsedData["status-monitor"].find("battery_avg_iir_filter") != parsedData["status-monitor"].end()) { + auto key = parsedData["status-monitor"]["battery_avg_iir_filter"]; + convertToUpper(key); + batteryFiltered = !key.compare("TRUE"); + } + if (parsedData["status-monitor"].find("battery_time_left_refreshrate") != parsedData["status-monitor"].end()) { + auto key = parsedData["status-monitor"]["battery_time_left_refreshrate"]; + long maxSeconds = 60; + long minSeconds = 1; + + long rate = atol(key.c_str()); + + if (rate > maxSeconds) { + rate = maxSeconds; + } + else if (rate < minSeconds) { + rate = minSeconds; + } + batteryTimeLeftRefreshRate = rate; + } } } else { @@ -978,10 +985,10 @@ void GetConfigSettings(MiniSettings* settings) { convertToUpper(key); settings -> realFrequencies = !(key.compare("TRUE")); } - if (parsedData["mini"].find("real_volts") != parsedData["mini"].end()) { - key = parsedData["mini"]["real_volts"]; - convertToUpper(key); - settings -> realVolts = !(key.compare("TRUE")); + if (parsedData["mini"].find("real_volts") != parsedData["mini"].end()) { + key = parsedData["mini"]["real_volts"]; + convertToUpper(key); + settings -> realVolts = !(key.compare("TRUE")); } long maxFontSize = 32; @@ -1056,7 +1063,7 @@ void GetConfigSettings(MiniSettings* settings) { void GetConfigSettings(MicroSettings* settings) { settings -> realFrequencies = false; - settings -> realVolts = false; + settings -> realVolts = false; settings -> handheldFontSize = 18; settings -> dockedFontSize = 18; settings -> alignTo = 1; @@ -1102,11 +1109,11 @@ void GetConfigSettings(MicroSettings* settings) { convertToUpper(key); settings -> realFrequencies = !(key.compare("TRUE")); } - if (parsedData["micro"].find("real_volts") != parsedData["micro"].end()) { - key = parsedData["micro"]["real_volts"]; - convertToUpper(key); - settings -> realVolts = !(key.compare("TRUE")); - } + if (parsedData["micro"].find("real_volts") != parsedData["micro"].end()) { + key = parsedData["micro"]["real_volts"]; + convertToUpper(key); + settings -> realVolts = !(key.compare("TRUE")); + } if (parsedData["micro"].find("text_align") != parsedData["micro"].end()) { key = parsedData["micro"]["text_align"]; convertToUpper(key); @@ -1262,8 +1269,8 @@ void GetConfigSettings(FpsGraphSettings* settings) { convertStrToRGBA4444("#FFFF", &(settings -> maxFPSTextColor)); convertStrToRGBA4444("#FFFF", &(settings -> minFPSTextColor)); convertStrToRGBA4444("#FFFF", &(settings -> mainLineColor)); - convertStrToRGBA4444("#0C0F", &(settings -> roundedLineColor)); - convertStrToRGBA4444("#F0FF", &(settings -> perfectLineColor)); + convertStrToRGBA4444("#F0FF", &(settings -> roundedLineColor)); + convertStrToRGBA4444("#0C0F", &(settings -> perfectLineColor)); settings -> refreshRate = 31; FILE* configFileIn = fopen("sdmc:/config/status-monitor/config.ini", "r"); @@ -1414,4 +1421,4 @@ void GetConfigSettings(FullSettings* settings) { convertToUpper(key); settings -> showTargetFreqs = key.compare("FALSE"); } -} \ No newline at end of file +} diff --git a/source/audsnoop.c b/source/audsnoop.c index 18308773..bb69fcd0 100644 --- a/source/audsnoop.c +++ b/source/audsnoop.c @@ -27,7 +27,7 @@ Result audsnoopDisableDspUsageMeasurement(void) { } Result audsnoopGetDspUsage(u32 *usage) { - u32 tmp; + u32 tmp = 0; Result rc = serviceDispatchOut(&g_audsnoopSrv, 6, tmp); if (R_SUCCEEDED(rc) && usage) *usage = tmp; diff --git a/source/main.cpp b/source/main.cpp index 116d20a7..b17fcaff 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,13 +2,16 @@ #include #include "Utils.hpp" -#include "FullOverlay.hpp" -#include "MiniOverlay.hpp" -#include "MicroOverlay.hpp" -#include "FPSCounterOverlay.hpp" -#include "FPSGraphOverlay.hpp" -#include "BatteryOverlay.hpp" -#include "MiscOverlay.hpp" +static tsl::elm::OverlayFrame* rootFrame = nullptr; +static bool skipMain = false; + +#include "modes/FPS_Counter.hpp" +#include "modes/FPS_Graph.hpp" +#include "modes/Full.hpp" +#include "modes/Mini.hpp" +#include "modes/Micro.hpp" +#include "modes/Battery.hpp" +#include "modes/Misc.hpp" //Graphs class GraphsMenu : public tsl::Gui { @@ -16,7 +19,7 @@ class GraphsMenu : public tsl::Gui { GraphsMenu() {} virtual tsl::elm::Element* createUI() override { - rootFrame = new tsl::elm::OverlayFrame("Ultra Monitor", "FPS"); + rootFrame = new tsl::elm::OverlayFrame("Status Monitor", "FPS"); auto list = new tsl::elm::List(); auto comFPSGraph = new tsl::elm::ListItem("Graph"); @@ -47,8 +50,7 @@ class GraphsMenu : public tsl::Gui { virtual void update() override {} virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - if (keysHeld & KEY_B) { - returningFromSelection = true; + if (keysDown & KEY_B) { tsl::goBack(); return true; } @@ -93,17 +95,10 @@ class OtherMenu : public tsl::Gui { virtual void update() override {} virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - if (!returningFromSelection && (keysHeld & KEY_B)) { - returningFromSelection = true; + if (keysDown & KEY_B) { tsl::goBack(); return true; } - if (returningFromSelection && !(keysHeld & KEY_B)) { - returningFromSelection = false; - } - if (keysHeld & KEY_B) { - return false; - } return false; } }; @@ -196,16 +191,10 @@ class MainMenu : public tsl::Gui { } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - if (!returningFromSelection && (keysHeld & KEY_B)) { + if (keysDown & KEY_B) { tsl::goBack(); return true; } - if (returningFromSelection && !(keysHeld & KEY_B)) { - returningFromSelection = false; - } - if (keysHeld & KEY_B) { - return false; - } return false; } }; @@ -216,11 +205,11 @@ class MonitorOverlay : public tsl::Overlay { virtual void initServices() override { //Initialize services tsl::hlp::doWithSmSession([this]{ - + apmInitialize(); if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize(); else pcvCheck = pcvInitialize(); - + tsCheck = tsInitialize(); if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); @@ -234,18 +223,18 @@ class MonitorOverlay : public tsl::Overlay { psmCheck = psmInitialize(); if (R_SUCCEEDED(psmCheck)) { psmService = psmGetServiceSession(); - i2cInitialize(); } - + i2cInitialize(); + SaltySD = CheckPort(); - + if (SaltySD) { LoadSharedMemory(); } if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) { uint32_t sysClkApiVer = 0; sysclkIpcGetAPIVersion(&sysClkApiVer); - if (sysClkApiVer != 4) { + if (sysClkApiVer < 4) { sysclkIpcExit(); } else sysclkCheck = 0; @@ -267,11 +256,10 @@ class MonitorOverlay : public tsl::Overlay { tcExit(); fanControllerClose(&g_ICon); fanExit(); - nvMapExit(); nvClose(fd); nvExit(); - i2cExit(); psmExit(); + i2cExit(); apmExit(); } @@ -289,11 +277,10 @@ class MicroMode : public tsl::Overlay { virtual void initServices() override { //Initialize services tsl::hlp::doWithSmSession([this]{ - apmInitialize(); if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize(); else pcvCheck = pcvInitialize(); - + if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); tsCheck = tsInitialize(); @@ -304,21 +291,22 @@ class MicroMode : public tsl::Overlay { else fanCheck = fanOpenController(&g_ICon, 1); } + i2cInitialize(); + psmCheck = psmInitialize(); if (R_SUCCEEDED(psmCheck)) { psmService = psmGetServiceSession(); - i2cInitialize(); } - + SaltySD = CheckPort(); - + if (SaltySD) { LoadSharedMemory(); } if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) { uint32_t sysClkApiVer = 0; sysclkIpcGetAPIVersion(&sysClkApiVer); - if (sysClkApiVer != 4) { + if (sysClkApiVer < 4) { sysclkIpcExit(); } else sysclkCheck = 0; @@ -330,6 +318,9 @@ class MicroMode : public tsl::Overlay { virtual void exitServices() override { CloseThreads(); shmemClose(&_sharedmemory); + if (R_SUCCEEDED(sysclkCheck)) { + sysclkIpcExit(); + } //Exit services clkrstExit(); pcvExit(); diff --git a/source/modes/Battery.hpp b/source/modes/Battery.hpp index e2f835aa..a766f4a9 100644 --- a/source/modes/Battery.hpp +++ b/source/modes/Battery.hpp @@ -1,13 +1,9 @@ -#pragma once -#include -#include "common.hpp" - -//Battery class BatteryOverlay : public tsl::Gui { private: char Battery_c[512]; public: BatteryOverlay() { + mutexInit(&mutex_BatteryChecker); StartBatteryThread(); } ~BatteryOverlay() { @@ -15,16 +11,11 @@ class BatteryOverlay : public tsl::Gui { } virtual tsl::elm::Element* createUI() override { - rootFrame = new tsl::elm::OverlayFrame("Ultra Monitor", APP_VERSION); + rootFrame = new tsl::elm::OverlayFrame("Status Monitor", APP_VERSION); auto Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - - if (R_SUCCEEDED(psmCheck)) { - - renderer->drawString("Battery/Charger Stats:", false, 20, 120, 20, renderer->a(0xFFFF)); - renderer->drawString(Battery_c, false, 20, 155, 18, renderer->a(0xFFFF)); - } - + renderer->drawString("Battery/Charger Stats:", false, 20, 120, 20, renderer->a(0xFFFF)); + renderer->drawString(Battery_c, false, 20, 155, 18, renderer->a(0xFFFF)); }); rootFrame->setContent(Status); @@ -36,6 +27,7 @@ class BatteryOverlay : public tsl::Gui { ///Battery + mutexLock(&mutex_BatteryChecker); char tempBatTimeEstimate[8] = "-:--"; if (batTimeEstimate >= 0) { snprintf(&tempBatTimeEstimate[0], sizeof(tempBatTimeEstimate), "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); @@ -44,11 +36,13 @@ class BatteryOverlay : public tsl::Gui { BatteryChargeInfoFieldsChargerType ChargerConnected = _batteryChargeInfoFields.ChargerType; int32_t ChargerVoltageLimit = _batteryChargeInfoFields.ChargerVoltageLimit; int32_t ChargerCurrentLimit = _batteryChargeInfoFields.ChargerCurrentLimit; + if (hosversionAtLeast(17,0,0)) { ChargerConnected = ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields) -> ChargerType; ChargerVoltageLimit = ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields) -> ChargerVoltageLimit; ChargerCurrentLimit = ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields) -> ChargerCurrentLimit; } + if (ChargerConnected) snprintf(Battery_c, sizeof Battery_c, "Battery Actual Capacity: %.0f mAh\n" @@ -56,9 +50,9 @@ class BatteryOverlay : public tsl::Gui { "Battery Temperature: %.1f\u00B0C\n" "Battery Raw Charge: %.1f%%\n" "Battery Age: %.1f%%\n" - "Battery Voltage (5s AVG): %.0f mV\n" - "Battery Current Flow (5s AVG): %+.0f mA\n" - "Battery Power Flow (5s AVG): %+.3f W\n" + "Battery Voltage (%ds AVG): %.0f mV\n" + "Battery Current Flow (%ss AVG): %+.0f mA\n" + "Battery Power Flow%s: %+.3f W\n" "Battery Remaining Time: %s\n" "Charger Type: %u\n" "Charger Max Voltage: %u mV\n" @@ -68,9 +62,9 @@ class BatteryOverlay : public tsl::Gui { (float)_batteryChargeInfoFields.BatteryTemperature / 1000, (float)_batteryChargeInfoFields.RawBatteryCharge / 1000, (float)_batteryChargeInfoFields.BatteryAge / 1000, - batVoltageAvg, - batCurrentAvg, - PowerConsumption, + batteryFiltered ? 45 : 5, batVoltageAvg, + batteryFiltered ? "11.25" : "5", batCurrentAvg, + batteryFiltered ? "" : " (5s AVG)", PowerConsumption, tempBatTimeEstimate, ChargerConnected, ChargerVoltageLimit, @@ -83,28 +77,28 @@ class BatteryOverlay : public tsl::Gui { "Battery Temperature: %.1f\u00B0C\n" "Battery Raw Charge: %.1f%%\n" "Battery Age: %.1f%%\n" - "Battery Voltage (5s AVG): %.0f mV\n" - "Battery Current Flow (5s AVG): %.0f mA\n" - "Battery Power Flow (5s AVG): %+.3f W\n" + "Battery Voltage (%ds AVG): %.0f mV\n" + "Battery Current Flow (%ss AVG): %+.0f mA\n" + "Battery Power Flow%s: %+.3f W\n" "Battery Remaining Time: %s", actualFullBatCapacity, designedFullBatCapacity, (float)_batteryChargeInfoFields.BatteryTemperature / 1000, (float)_batteryChargeInfoFields.RawBatteryCharge / 1000, (float)_batteryChargeInfoFields.BatteryAge / 1000, - batVoltageAvg, - batCurrentAvg, - PowerConsumption, + batteryFiltered ? 45 : 5, batVoltageAvg, + batteryFiltered ? "11.25" : "5", batCurrentAvg, + batteryFiltered ? "" : " (5s AVG)", PowerConsumption, tempBatTimeEstimate ); + mutexUnlock(&mutex_BatteryChecker); } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - if (keysHeld & KEY_B) { - returningFromSelection = true; + if (keysDown & KEY_B) { tsl::goBack(); return true; } return false; } -}; \ No newline at end of file +}; diff --git a/source/modes/FPS_Counter.hpp b/source/modes/FPS_Counter.hpp index 2e3222b9..70889db6 100644 --- a/source/modes/FPS_Counter.hpp +++ b/source/modes/FPS_Counter.hpp @@ -1,11 +1,6 @@ -#pragma once -#include -#include "common.hpp" - -//FPS Counter mode class com_FPS : public tsl::Gui { private: - std::list mappedButtons = buttonMapper.MapButtons(keyCombo); // map buttons + uint64_t mappedButtons = MapButtons(keyCombo); // map buttons char FPSavg_c[8]; FpsCounterSettings settings; size_t fontsize = 0; @@ -104,17 +99,7 @@ class com_FPS : public tsl::Gui { } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - - bool allButtonsHeld = true; - for (const HidNpadButton& button : mappedButtons) { - if (!(keysHeld & static_cast(button))) { - allButtonsHeld = false; - break; - } - } - - if (allButtonsHeld) { - returningFromSelection = true; + if (isKeyComboPressed(keysHeld, keysDown, mappedButtons)) { tsl::goBack(); return true; } diff --git a/source/modes/FPS_Graph.hpp b/source/modes/FPS_Graph.hpp index 8b9a07e9..1470d9ad 100644 --- a/source/modes/FPS_Graph.hpp +++ b/source/modes/FPS_Graph.hpp @@ -1,11 +1,6 @@ -#pragma once -#include -#include "common.hpp" - -//FPS Graph mode class com_FPSGraph : public tsl::Gui { private: - std::list mappedButtons = buttonMapper.MapButtons(keyCombo); // map buttons + uint64_t mappedButtons = MapButtons(keyCombo); // map buttons char FPSavg_c[8]; FpsGraphSettings settings; public: @@ -184,17 +179,7 @@ class com_FPSGraph : public tsl::Gui { } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - - bool allButtonsHeld = true; - for (const HidNpadButton& button : mappedButtons) { - if (!(keysHeld & static_cast(button))) { - allButtonsHeld = false; - break; - } - } - - if (allButtonsHeld) { - returningFromSelection = true; + if (isKeyComboPressed(keysHeld, keysDown, mappedButtons)) { TeslaFPS = 60; tsl::goBack(); return true; diff --git a/source/modes/Full.hpp b/source/modes/Full.hpp index 86a4ecb8..1c947236 100644 --- a/source/modes/Full.hpp +++ b/source/modes/Full.hpp @@ -1,55 +1,52 @@ -#pragma once -#include -#include "common.hpp" - -//Full mode class FullOverlay : public tsl::Gui { private: - std::list mappedButtons = buttonMapper.MapButtons(keyCombo); // map buttons - char RealCPU_Hz_c[32]; - char DeltaCPU_c[12]; - char DeltaGPU_c[12]; - char DeltaRAM_c[12]; - char RealGPU_Hz_c[32]; - char RealRAM_Hz_c[32]; - char GPU_Load_c[32]; - char Rotation_SpeedLevel_c[64]; - char RAM_compressed_c[64]; - char RAM_var_compressed_c[128]; - char CPU_Hz_c[64]; - char GPU_Hz_c[64]; - char RAM_Hz_c[64]; - char CPU_compressed_c[160]; - char CPU_Usage0[32]; - char CPU_Usage1[32]; - char CPU_Usage2[32]; - char CPU_Usage3[32]; - char SoCPCB_temperature_c[64]; - char skin_temperature_c[32]; - char BatteryDraw_c[64]; - char FPS_var_compressed_c[64]; - char RAM_load_c[64]; + uint64_t mappedButtons = MapButtons(keyCombo); // map buttons + char RealCPU_Hz_c[32] = ""; + char DeltaCPU_c[12] = ""; + char DeltaGPU_c[12] = ""; + char DeltaRAM_c[12] = ""; + char RealGPU_Hz_c[32] = ""; + char RealRAM_Hz_c[32] = ""; + char GPU_Load_c[32] = ""; + char Rotation_SpeedLevel_c[64] = ""; + char RAM_compressed_c[64] = ""; + char RAM_var_compressed_c[128] = ""; + char CPU_Hz_c[64] = ""; + char GPU_Hz_c[64] = ""; + char RAM_Hz_c[64] = ""; + char CPU_compressed_c[160] = ""; + char CPU_Usage0[32] = ""; + char CPU_Usage1[32] = ""; + char CPU_Usage2[32] = ""; + char CPU_Usage3[32] = ""; + char SoCPCB_temperature_c[64] = ""; + char skin_temperature_c[32] = ""; + char BatteryDraw_c[64] = ""; + char FPS_var_compressed_c[64] = ""; + char RAM_load_c[64] = ""; uint8_t COMMON_MARGIN = 20; FullSettings settings; + uint64_t systemtickfrequency_impl = systemtickfrequency; public: FullOverlay() { GetConfigSettings(&settings); - StartThreads(); + mutexInit(&mutex_BatteryChecker); + mutexInit(&mutex_Misc); tsl::hlp::requestForeground(false); TeslaFPS = settings.refreshRate; - systemtickfrequency /= settings.refreshRate; + systemtickfrequency_impl /= settings.refreshRate; if (settings.setPosRight) { tsl::gfx::Renderer::getRenderer().setLayerPos(1248, 0); } deactivateOriginalFooter = true; + StartThreads(); } ~FullOverlay() { CloseThreads(); FullMode = true; tsl::hlp::requestForeground(true); alphabackground = 0xD; - systemtickfrequency = 19200000; if (settings.setPosRight) { tsl::gfx::Renderer::getRenderer().setLayerPos(0, 0); } @@ -57,7 +54,7 @@ class FullOverlay : public tsl::Gui { } virtual tsl::elm::Element* createUI() override { - rootFrame = new tsl::elm::OverlayFrame("Ultra Monitor", APP_VERSION); + rootFrame = new tsl::elm::OverlayFrame("Status Monitor", APP_VERSION); auto Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { @@ -206,26 +203,30 @@ class FullOverlay : public tsl::Gui { } virtual void update() override { - //In case of getting more than systemtickfrequency in idle, make it equal to systemtickfrequency to get 0% as output and nothing less - //This is because making each loop also takes time, which is not considered because this will take also additional time - if (idletick0 > systemtickfrequency) idletick0 = systemtickfrequency; - if (idletick1 > systemtickfrequency) idletick1 = systemtickfrequency; - if (idletick2 > systemtickfrequency) idletick2 = systemtickfrequency; - if (idletick3 > systemtickfrequency) idletick3 = systemtickfrequency; - //Make stuff ready to print ///CPU + if (idletick0 > systemtickfrequency_impl) + strcpy(CPU_Usage0, "Core #0: 0.00%"); + else snprintf(CPU_Usage0, sizeof CPU_Usage0, "Core #0: %.2f%%", (1.d - ((double)idletick0 / systemtickfrequency_impl)) * 100); + if (idletick1 > systemtickfrequency_impl) + strcpy(CPU_Usage1, "Core #1: 0.00%"); + else snprintf(CPU_Usage1, sizeof CPU_Usage1, "Core #1: %.2f%%", (1.d - ((double)idletick1 / systemtickfrequency_impl)) * 100); + if (idletick2 > systemtickfrequency_impl) + strcpy(CPU_Usage2, "Core #2: 0.00%"); + else snprintf(CPU_Usage2, sizeof CPU_Usage2, "Core #2: %.2f%%", (1.d - ((double)idletick2 / systemtickfrequency_impl)) * 100); + if (idletick3 > systemtickfrequency_impl) + strcpy(CPU_Usage3, "Core #3: 0.00%"); + else snprintf(CPU_Usage3, sizeof CPU_Usage3, "Core #3: %.2f%%", (1.d - ((double)idletick3 / systemtickfrequency_impl)) * 100); + + snprintf(CPU_compressed_c, sizeof CPU_compressed_c, "%s\n%s\n%s\n%s", CPU_Usage0, CPU_Usage1, CPU_Usage2, CPU_Usage3); + + mutexLock(&mutex_Misc); snprintf(CPU_Hz_c, sizeof(CPU_Hz_c), "%u.%u MHz", CPU_Hz / 1000000, (CPU_Hz / 100000) % 10); if (realCPU_Hz) { snprintf(RealCPU_Hz_c, sizeof(RealCPU_Hz_c), "%u.%u MHz", realCPU_Hz / 1000000, (realCPU_Hz / 100000) % 10); int32_t deltaCPU = (int32_t)(realCPU_Hz / 1000) - (CPU_Hz / 1000); snprintf(DeltaCPU_c, sizeof(DeltaCPU_c), "Δ %d.%u", deltaCPU / 1000, abs(deltaCPU / 100) % 10); } - snprintf(CPU_Usage0, sizeof CPU_Usage0, "Core #0: %.2f%%", (1.d - ((double)idletick0 / systemtickfrequency)) * 100); - snprintf(CPU_Usage1, sizeof CPU_Usage1, "Core #1: %.2f%%", (1.d - ((double)idletick1 / systemtickfrequency)) * 100); - snprintf(CPU_Usage2, sizeof CPU_Usage2, "Core #2: %.2f%%", (1.d - ((double)idletick2 / systemtickfrequency)) * 100); - snprintf(CPU_Usage3, sizeof CPU_Usage3, "Core #3: %.2f%%", (1.d - ((double)idletick3 / systemtickfrequency)) * 100); - snprintf(CPU_compressed_c, sizeof CPU_compressed_c, "%s\n%s\n%s\n%s", CPU_Usage0, CPU_Usage1, CPU_Usage2, CPU_Usage3); ///GPU snprintf(GPU_Hz_c, sizeof GPU_Hz_c, "%u.%u MHz", GPU_Hz / 1000000, (GPU_Hz / 100000) % 10); @@ -274,12 +275,6 @@ class FullOverlay : public tsl::Gui { RAM_GPU_Load / 10, RAM_GPU_Load % 10); } ///Thermal - char remainingBatteryLife[8]; - if (batTimeEstimate >= 0) { - snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } - else snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "-:--"); - snprintf(BatteryDraw_c, sizeof BatteryDraw_c, "Battery Power Flow: %+.2fW[%s]", PowerConsumption, remainingBatteryLife); if (hosversionAtLeast(10,0,0)) { snprintf(SoCPCB_temperature_c, sizeof SoCPCB_temperature_c, "%2.1f\u00B0C\n%2.1f\u00B0C\n%2d.%d\u00B0C", @@ -296,27 +291,26 @@ class FullOverlay : public tsl::Gui { ///FPS snprintf(FPS_var_compressed_c, sizeof FPS_var_compressed_c, "%u\n%2.1f", FPS, FPSavg); + + mutexUnlock(&mutex_Misc); + + //Battery Power Flow + char remainingBatteryLife[8]; + mutexLock(&mutex_BatteryChecker); + if (batTimeEstimate >= 0) { + snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); + } + else snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "-:--"); + snprintf(BatteryDraw_c, sizeof BatteryDraw_c, "Battery Power Flow: %+.2fW[%s]", PowerConsumption, remainingBatteryLife); + mutexUnlock(&mutex_BatteryChecker); } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - - bool allButtonsHeld = true; - for (const HidNpadButton& button : mappedButtons) { - if (!(keysHeld & static_cast(button))) { - allButtonsHeld = false; - break; - } - } - - if (allButtonsHeld) { - returningFromSelection = true; + if (isKeyComboPressed(keysHeld, keysDown, mappedButtons)) { TeslaFPS = 60; tsl::goBack(); return true; } - if (keysHeld & KEY_B) { - return false; - } return false; } }; \ No newline at end of file diff --git a/source/modes/Micro.hpp b/source/modes/Micro.hpp index 17fdefb9..b21aaeba 100644 --- a/source/modes/Micro.hpp +++ b/source/modes/Micro.hpp @@ -1,27 +1,22 @@ -#pragma once -#include -#include "common.hpp" - -//Micro mode class MicroOverlay : public tsl::Gui { private: - std::list mappedButtons = buttonMapper.MapButtons(keyCombo); // map buttons - char GPU_Load_c[32]; - char Rotation_SpeedLevel_c[64]; - char Power_c[64]; - char RAM_var_compressed_c[128]; - char CPU_compressed_c[160]; - char CPUS_compressed_c[160]; - char CPU_Usage[32]; - char CPU_Usage0[32]; - char CPU_Usage1[32]; - char CPU_Usage2[32]; - char CPU_Usage3[32]; - char skin_temperature_c[48]; - char skin_temperatureB_c[48]; - char skin_temperatureS_c[48]; - char batteryCharge[10]; // Declare the batteryCharge variable - char FPS_var_compressed_c[64]; + uint64_t mappedButtons = MapButtons(keyCombo); // map buttons + char GPU_Load_c[32] = ""; + char Rotation_SpeedLevel_c[64] = ""; + char RAM_var_compressed_c[128] = ""; + char Power_c[64] = ""; + char CPU_compressed_c[160] = ""; + char CPUS_compressed_c[160] = ""; + char CPU_Usage[32] = ""; + char CPU_Usage0[32] = ""; + char CPU_Usage1[32] = ""; + char CPU_Usage2[32] = ""; + char CPU_Usage3[32] = ""; + char skin_temperature_c[48] = ""; + char skin_temperatureB_c[48] = ""; + char skin_temperatureS_c[48] = ""; + char batteryCharge[10] = ""; // Declare the batteryCharge variable + char FPS_var_compressed_c[64] = ""; char Battery_c[32]; char BatteryS_c[32]; char CPU_volt_c[10]; @@ -51,6 +46,7 @@ class MicroOverlay : public tsl::Gui { ApmPerformanceMode performanceMode = ApmPerformanceMode_Invalid; size_t fontsize = 0; bool showFPS = false; + uint64_t systemtickfrequency_impl = systemtickfrequency; public: MicroOverlay() { GetConfigSettings(&settings); @@ -64,11 +60,13 @@ class MicroOverlay : public tsl::Gui { if (settings.setPosBottom) { tsl::gfx::Renderer::getRenderer().setLayerPos(0, 1038); } - StartThreads(); + mutexInit(&mutex_BatteryChecker); + mutexInit(&mutex_Misc); TeslaFPS = settings.refreshRate; - systemtickfrequency /= settings.refreshRate; + systemtickfrequency_impl /= settings.refreshRate; alphabackground = 0x0; deactivateOriginalFooter = true; + StartThreads(); } ~MicroOverlay() { CloseThreads(); @@ -343,16 +341,30 @@ class MicroOverlay : public tsl::Gui { fontsize = settings.dockedFontSize; } } - //In case of getting more than systemtickfrequency in idle, make it equal to systemtickfrequency to get 0% as output and nothing less - //This is because making each loop also takes time, which is not considered because this will take also additional time - if (idletick0 > systemtickfrequency) idletick0 = systemtickfrequency; - if (idletick1 > systemtickfrequency) idletick1 = systemtickfrequency; - if (idletick2 > systemtickfrequency) idletick2 = systemtickfrequency; - if (idletick3 > systemtickfrequency) idletick3 = systemtickfrequency; - double cpu_usage0 = (1.d - ((double)idletick0 / systemtickfrequency)) * 100; - double cpu_usage1 = (1.d - ((double)idletick1 / systemtickfrequency)) * 100; - double cpu_usage2 = (1.d - ((double)idletick2 / systemtickfrequency)) * 100; - double cpu_usage3 = (1.d - ((double)idletick3 / systemtickfrequency)) * 100; + + //Make stuff ready to print + ///CPU + /* if (idletick0 > systemtickfrequency_impl) + strcpy(CPU_Usage0, "0%"); + else snprintf(CPU_Usage0, sizeof CPU_Usage0, "%.0f%%", (1.d - ((double)idletick0 / systemtickfrequency_impl)) * 100); + if (idletick1 > systemtickfrequency_impl) + strcpy(CPU_Usage1, "0%"); + else snprintf(CPU_Usage1, sizeof CPU_Usage1, "%.0f%%", (1.d - ((double)idletick1 / systemtickfrequency_impl)) * 100); + if (idletick2 > systemtickfrequency_impl) + strcpy(CPU_Usage2, "0%"); + else snprintf(CPU_Usage2, sizeof CPU_Usage2, "%.0f%%", (1.d - ((double)idletick2 / systemtickfrequency_impl)) * 100); + if (idletick3 > systemtickfrequency_impl) + strcpy(CPU_Usage3, "0%"); + else snprintf(CPU_Usage3, sizeof CPU_Usage3, "%.0f%%", (1.d - ((double)idletick3 / systemtickfrequency_impl)) * 100); */ + + if (idletick0 > systemtickfrequency_impl) idletick0 = systemtickfrequency_impl; + if (idletick1 > systemtickfrequency_impl) idletick1 = systemtickfrequency_impl; + if (idletick2 > systemtickfrequency_impl) idletick2 = systemtickfrequency_impl; + if (idletick3 > systemtickfrequency_impl) idletick3 = systemtickfrequency_impl; + double cpu_usage0 = (1.d - ((double)idletick0 / systemtickfrequency_impl)) * 100; + double cpu_usage1 = (1.d - ((double)idletick1 / systemtickfrequency_impl)) * 100; + double cpu_usage2 = (1.d - ((double)idletick2 / systemtickfrequency_impl)) * 100; + double cpu_usage3 = (1.d - ((double)idletick3 / systemtickfrequency_impl)) * 100; double cpu_usageM = 0; if (cpu_usage0 > cpu_usageM) cpu_usageM = cpu_usage0; if (cpu_usage1 > cpu_usageM) cpu_usageM = cpu_usage1; @@ -367,6 +379,7 @@ class MicroOverlay : public tsl::Gui { snprintf(CPU_Usage2, sizeof CPU_Usage2, "%.0f%%", (1.d - ((double)idletick2 / systemtickfrequency)) * 100); snprintf(CPU_Usage3, sizeof CPU_Usage3, "%.0f%%", (1.d - ((double)idletick3 / systemtickfrequency)) * 100); + mutexLock(&mutex_Misc); char difference[5] = "@"; if (realCPU_Hz) { int32_t deltaCPU = (int32_t)(realCPU_Hz / 1000) - (CPU_Hz / 1000); @@ -380,7 +393,6 @@ class MicroOverlay : public tsl::Gui { strcpy(difference, "▽"); } } - if (settings.realVolts) { if (settings.realFrequencies && realCPU_Hz) { snprintf(CPU_compressed_c, sizeof CPU_compressed_c, @@ -542,6 +554,7 @@ class MicroOverlay : public tsl::Gui { ///Battery char remainingBatteryLife[8]; + mutexLock(&mutex_BatteryChecker); if (batTimeEstimate >= 0) { snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); } @@ -639,31 +652,21 @@ class MicroOverlay : public tsl::Gui { Rotation_SpeedLevel_f * 100); } } + mutexUnlock(&mutex_BatteryChecker); snprintf(Rotation_SpeedLevel_c, sizeof Rotation_SpeedLevel_c, "%2.1f%%", Rotation_SpeedLevel_f * 100); ///FPS snprintf(FPS_var_compressed_c, sizeof FPS_var_compressed_c, "%2.1f", FPSavg); + + mutexUnlock(&mutex_Misc); } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - //std::list mappedButtons; - //ButtonMapperImpl buttonMapper; // Create an instance of the ButtonMapperImpl class - //mappedButtons = buttonMapper.MapButtons(keyCombo); // map buttons - - bool allButtonsHeld = true; - for (const HidNpadButton& button : mappedButtons) { - if (!(keysHeld & static_cast(button))) { - allButtonsHeld = false; - break; - } - } - - if (allButtonsHeld) { - returningFromSelection = true; + if (isKeyComboPressed(keysHeld, keysDown, mappedButtons)) { TeslaFPS = 60; if (skipMain) tsl::goBack(); @@ -673,9 +676,6 @@ class MicroOverlay : public tsl::Gui { } return true; } - if (keysHeld & KEY_B) { - return false; - } return false; } }; \ No newline at end of file diff --git a/source/modes/Mini.hpp b/source/modes/Mini.hpp index 400d70e4..33ea0cc8 100644 --- a/source/modes/Mini.hpp +++ b/source/modes/Mini.hpp @@ -1,23 +1,19 @@ -#pragma once -#include -#include "common.hpp" - -//Mini mode class MiniOverlay : public tsl::Gui { private: - std::list mappedButtons = buttonMapper.MapButtons(keyCombo); // map buttons - char GPU_Load_c[32]; - char Rotation_SpeedLevel_c[64]; - char RAM_var_compressed_c[128]; - char SoCPCB_temperature_c[64]; - char skin_temperature_c[32]; + uint64_t mappedButtons = MapButtons(keyCombo); // map buttons + char GPU_Load_c[32] = ""; + char Rotation_SpeedLevel_c[64] = ""; + char RAM_var_compressed_c[128] = ""; + char SoCPCB_temperature_c[64] = ""; + char skin_temperature_c[32] = ""; uint32_t rectangleWidth = 0; - char Variables[512]; + char Variables[512] = ""; size_t fontsize = 0; MiniSettings settings; bool Initialized = false; ApmPerformanceMode performanceMode = ApmPerformanceMode_Invalid; + uint64_t systemtickfrequency_impl = systemtickfrequency; public: MiniOverlay() { GetConfigSettings(&settings); @@ -25,9 +21,7 @@ class MiniOverlay : public tsl::Gui { if (performanceMode == ApmPerformanceMode_Normal) { fontsize = settings.handheldFontSize; } - else if (performanceMode == ApmPerformanceMode_Boost) { - fontsize = settings.dockedFontSize; - } + else fontsize = settings.dockedFontSize; switch(settings.setPos) { case 1: case 4: @@ -40,20 +34,21 @@ class MiniOverlay : public tsl::Gui { tsl::gfx::Renderer::getRenderer().setLayerPos(1248, 0); break; } - StartThreads(); + mutexInit(&mutex_BatteryChecker); + mutexInit(&mutex_Misc); alphabackground = 0x0; tsl::hlp::requestForeground(false); FullMode = false; TeslaFPS = settings.refreshRate; - systemtickfrequency /= settings.refreshRate; + systemtickfrequency_impl /= settings.refreshRate; deactivateOriginalFooter = true; + StartThreads(); } ~MiniOverlay() { CloseThreads(); FullMode = true; tsl::hlp::requestForeground(true); alphabackground = 0xD; - systemtickfrequency = 19200000; deactivateOriginalFooter = false; } @@ -114,50 +109,50 @@ class MiniOverlay : public tsl::Gui { if (print_text[0]) strcat(print_text, "\n"); strcat(print_text, "CPU"); - if (settings.realVolts) - strcat(print_text, "\n"); entry_count++; - if (settings.realVolts) + if (settings.realVolts) { + strcat(print_text, "\n"); entry_count++; + } flags |= (1 << 0); } else if (!key.compare("GPU") && !(flags & 1 << 1)) { if (print_text[0]) strcat(print_text, "\n"); strcat(print_text, "GPU"); - if (settings.realVolts) - strcat(print_text, "\n"); entry_count++; - if (settings.realVolts) + if (settings.realVolts) { + strcat(print_text, "\n"); entry_count++; + } flags |= (1 << 1); } else if (!key.compare("RAM") && !(flags & 1 << 2)) { if (print_text[0]) strcat(print_text, "\n"); strcat(print_text, "RAM"); - if (settings.realVolts) - strcat(print_text, "\n"); entry_count++; - if (settings.realVolts) + if (settings.realVolts) { + strcat(print_text, "\n"); entry_count++; + } flags |= (1 << 2); } - else if (!key.compare("DRAW") && !(flags & 1 << 3)) { + else if (!key.compare("TEMP") && !(flags & 1 << 3)) { if (print_text[0]) strcat(print_text, "\n"); - strcat(print_text, "DRAW"); - if (settings.realVolts) - strcat(print_text, "\n"); + strcat(print_text, "TEMP"); entry_count++; - if (settings.realVolts) + if (settings.realVolts) { + strcat(print_text, "\n"); entry_count++; + } flags |= (1 << 3); } - else if (!key.compare("TEMP") && !(flags & 1 << 4)) { + else if (!key.compare("DRAW") && !(flags & 1 << 4)) { if (print_text[0]) strcat(print_text, "\n"); - strcat(print_text, "TEMP"); + strcat(print_text, "DRAW"); entry_count++; flags |= (1 << 4); } @@ -209,8 +204,9 @@ class MiniOverlay : public tsl::Gui { } renderer->drawRect(base_x, base_y, margin + rectangleWidth + (fontsize / 3), height, a(settings.backgroundColor)); - renderer->drawString(print_text, false, base_x, base_y + fontsize, fontsize, renderer->a(settings.catColor)); + + ///GPU renderer->drawString(Variables, false, base_x + margin, base_y + fontsize, fontsize, renderer->a(settings.textColor)); }); @@ -233,13 +229,7 @@ class MiniOverlay : public tsl::Gui { fontsize = settings.dockedFontSize; } } - //In case of getting more than systemtickfrequency in idle, make it equal to systemtickfrequency to get 0% as output and nothing less - //This is because making each loop also takes time, which is not considered because this will take also additional time - if (idletick0 > systemtickfrequency) idletick0 = systemtickfrequency; - if (idletick1 > systemtickfrequency) idletick1 = systemtickfrequency; - if (idletick2 > systemtickfrequency) idletick2 = systemtickfrequency; - if (idletick3 > systemtickfrequency) idletick3 = systemtickfrequency; - + //Make stuff ready to print ///CPU char MINI_CPU_Usage0[7] = ""; @@ -247,13 +237,23 @@ class MiniOverlay : public tsl::Gui { char MINI_CPU_Usage2[7] = ""; char MINI_CPU_Usage3[7] = ""; - snprintf(MINI_CPU_Usage0, sizeof(MINI_CPU_Usage0), "%.0f%%", (1.d - ((double)idletick0 / systemtickfrequency)) * 100); - snprintf(MINI_CPU_Usage1, sizeof(MINI_CPU_Usage1), "%.0f%%", (1.d - ((double)idletick1 / systemtickfrequency)) * 100); - snprintf(MINI_CPU_Usage2, sizeof(MINI_CPU_Usage2), "%.0f%%", (1.d - ((double)idletick2 / systemtickfrequency)) * 100); - snprintf(MINI_CPU_Usage3, sizeof(MINI_CPU_Usage3), "%.0f%%", (1.d - ((double)idletick3 / systemtickfrequency)) * 100); + if (idletick0 > systemtickfrequency_impl) + strcpy(MINI_CPU_Usage0, "0%"); + else snprintf(MINI_CPU_Usage0, sizeof(MINI_CPU_Usage0), "%.0f%%", (1.d - ((double)idletick0 / systemtickfrequency_impl)) * 100); + if (idletick1 > systemtickfrequency_impl) + strcpy(MINI_CPU_Usage1, "0%"); + else snprintf(MINI_CPU_Usage1, sizeof(MINI_CPU_Usage1), "%.0f%%", (1.d - ((double)idletick1 / systemtickfrequency_impl)) * 100); + if (idletick2 > systemtickfrequency_impl) + strcpy(MINI_CPU_Usage2, "0%"); + else snprintf(MINI_CPU_Usage2, sizeof(MINI_CPU_Usage2), "%.0f%%", (1.d - ((double)idletick2 / systemtickfrequency_impl)) * 100); + if (idletick3 > systemtickfrequency_impl) + strcpy(MINI_CPU_Usage3, "0%"); + else snprintf(MINI_CPU_Usage3, sizeof(MINI_CPU_Usage3), "%.0f%%", (1.d - ((double)idletick3 / systemtickfrequency_impl)) * 100); + + mutexLock(&mutex_Misc); char MINI_CPU_compressed_c[42] = ""; - char MINI_CPU_volt_c[7] = ""; + char MINI_CPU_volt_c[7] = ""; if (settings.realFrequencies && realCPU_Hz) { snprintf(MINI_CPU_compressed_c, sizeof(MINI_CPU_compressed_c), "[%s,%s,%s,%s]@%hu.%hhu", @@ -270,7 +270,6 @@ class MiniOverlay : public tsl::Gui { snprintf(MINI_CPU_volt_c, sizeof(MINI_CPU_volt_c), "%umV", realCPU_mV); } - ///GPU char MINI_GPU_Load_c[14]; char MINI_GPU_volt_c[7] = ""; if (settings.realFrequencies && realGPU_Hz) { @@ -335,14 +334,6 @@ class MiniOverlay : public tsl::Gui { } ///Thermal - char MINI_SOC_volt_c[7] = ""; - char remainingBatteryLife[8]; - if (batTimeEstimate >= 0) { - snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } - else snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "--:--"); - - snprintf(SoCPCB_temperature_c, sizeof SoCPCB_temperature_c, "%0.2fW[%s]", PowerConsumption, remainingBatteryLife); if (hosversionAtLeast(10,0,0)) { snprintf(skin_temperature_c, sizeof skin_temperature_c, "%2.1f\u00B0C/%2.1f\u00B0C/%hu.%hhu\u00B0C", @@ -356,6 +347,7 @@ class MiniOverlay : public tsl::Gui { PCB_temperatureC / 1000, (PCB_temperatureC / 100) % 10, skin_temperaturemiliC / 1000, (skin_temperaturemiliC / 100) % 10); } + char MINI_SOC_volt_c[7] = ""; snprintf(Rotation_SpeedLevel_c, sizeof Rotation_SpeedLevel_c, "%2.1f%%", Rotation_SpeedLevel_f * 100); if (settings.realVolts) { snprintf(MINI_SOC_volt_c, sizeof(MINI_SOC_volt_c), "%umV", realSOC_mV); @@ -398,29 +390,29 @@ class MiniOverlay : public tsl::Gui { } flags |= 1 << 2; } - else if (!key.compare("DRAW") && !(flags & 1 << 3)) { + else if (!key.compare("TEMP") && !(flags & 1 << 3)) { if (Temp[0]) { strcat(Temp, "\n"); } - strcat(Temp, SoCPCB_temperature_c); + strcat(Temp, skin_temperature_c); if (settings.realVolts) { strcat(Temp, "\n"); strcat(Temp, MINI_SOC_volt_c); } flags |= 1 << 3; } - else if (!key.compare("TEMP") && !(flags & 1 << 4)) { + else if (!key.compare("FAN") && !(flags & 1 << 4)) { if (Temp[0]) { strcat(Temp, "\n"); } - strcat(Temp, skin_temperature_c); + strcat(Temp, Rotation_SpeedLevel_c); flags |= 1 << 4; } - else if (!key.compare("FAN") && !(flags & 1 << 5)) { + else if (!key.compare("DRAW") && !(flags & 1 << 5)) { if (Temp[0]) { strcat(Temp, "\n"); } - strcat(Temp, Rotation_SpeedLevel_c); + strcat(Temp, SoCPCB_temperature_c); flags |= 1 << 5; } else if (!key.compare("FPS") && !(flags & 1 << 6) && GameRunning) { @@ -436,21 +428,22 @@ class MiniOverlay : public tsl::Gui { flags |= 1 << 6; } } + mutexUnlock(&mutex_Misc); strcpy(Variables, Temp); - } - virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - - bool allButtonsHeld = true; - for (const HidNpadButton& button : mappedButtons) { - if (!(keysHeld & static_cast(button))) { - allButtonsHeld = false; - break; - } + char remainingBatteryLife[8]; + mutexLock(&mutex_BatteryChecker); + if (batTimeEstimate >= 0) { + snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); } + else snprintf(remainingBatteryLife, sizeof remainingBatteryLife, "--:--"); + + snprintf(SoCPCB_temperature_c, sizeof SoCPCB_temperature_c, "%0.2fW[%s]", PowerConsumption, remainingBatteryLife); + mutexUnlock(&mutex_BatteryChecker); - if (allButtonsHeld) { - returningFromSelection = true; + } + virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + if (isKeyComboPressed(keysHeld, keysDown, mappedButtons)) { TeslaFPS = 60; tsl::goBack(); return true; @@ -459,9 +452,6 @@ class MiniOverlay : public tsl::Gui { FPSmin = 254; FPSmax = 0; } - if (keysHeld & KEY_B) { - return false; - } return false; } }; \ No newline at end of file diff --git a/source/modes/Misc.hpp b/source/modes/Misc.hpp index 9652ceb2..814fd373 100644 --- a/source/modes/Misc.hpp +++ b/source/modes/Misc.hpp @@ -1,7 +1,3 @@ -#pragma once -#include -#include "common.hpp" - void StartMiscThread() { threadCreate(&t0, Misc2, NULL, NULL, 0x1000, 0x3F, 3); threadStart(&t0); @@ -23,7 +19,7 @@ class MiscOverlay : public tsl::Gui { char Nifm_pass[96]; char Nifm_ipaddr[16]; public: - MiscOverlay() { + MiscOverlay() { smInitialize(); nifmCheck = nifmInitialize(NifmServiceType_Admin); if (R_SUCCEEDED(mmuInitialize())) { @@ -52,8 +48,8 @@ class MiscOverlay : public tsl::Gui { audsnoopExit(); } - virtual tsl::elm::Element* createUI() override { - rootFrame = new tsl::elm::OverlayFrame("Ultra Monitor", APP_VERSION); + virtual tsl::elm::Element* createUI() override { + rootFrame = new tsl::elm::OverlayFrame("Status Monitor", APP_VERSION); auto Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { @@ -91,7 +87,6 @@ class MiscOverlay : public tsl::Gui { renderer->drawString("IP Address:", false, 20, 320, 15, renderer->a(0xFFFF)); renderer->drawString(Nifm_ipaddr, false, 104, 320, 15, renderer->a(0xFFFF)); } - else renderer->drawString("Type: Not connected", false, 20, 280, 18, renderer->a(0xFFFF)); } @@ -126,7 +121,7 @@ class MiscOverlay : public tsl::Gui { else { memcpy(&pass_temp1, &(Nifm_profile.wireless_setting_data.passphrase[0]), 24); } - snprintf(Nifm_pass, sizeof Nifm_pass, "%s\n%s\n%s", pass_temp1, pass_temp2, pass_temp3); + snprintf(Nifm_pass, sizeof Nifm_pass, "%s\n%s\n%s", pass_temp1, pass_temp2, pass_temp3); if (!ipaddr_value || ipaddr[0] == '\0') { nifmGetCurrentIpAddress(&ipaddr_value); ipaddr[0] = (ipaddr_value >> 24) & 0xFF; @@ -134,7 +129,7 @@ class MiscOverlay : public tsl::Gui { ipaddr[2] = (ipaddr_value >> 8) & 0xFF; ipaddr[3] = ipaddr_value & 0xFF; } - snprintf(Nifm_ipaddr, sizeof Nifm_ipaddr, "%u.%u.%u.%u", ipaddr[3], ipaddr[2], ipaddr[1], ipaddr[0]); + snprintf(Nifm_ipaddr, sizeof Nifm_ipaddr, "%u.%u.%u.%u", ipaddr[3], ipaddr[2], ipaddr[1], ipaddr[0]); } virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { @@ -143,14 +138,10 @@ class MiscOverlay : public tsl::Gui { } else Nifm_showpass = false; - if (keysHeld & KEY_B) { - returningFromSelection = true; + if (keysDown & KEY_B) { tsl::goBack(); return true; } - if (keysHeld & KEY_B) { - return false; - } return false; } }; \ No newline at end of file