diff --git a/.gitignore b/.gitignore index 7212d2758..8645c08d2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /build/artifacts/ build/device/**/*.pyc epsilon.elf +epsilon.map .vscode .DS_Store .gradle diff --git a/ion/src/simulator/3ds/driver/common.cpp b/ion/src/simulator/3ds/driver/common.cpp index 0eb6e2d23..b4bd829a1 100644 --- a/ion/src/simulator/3ds/driver/common.cpp +++ b/ion/src/simulator/3ds/driver/common.cpp @@ -1,4 +1,5 @@ #include <3ds.h> +#include #include "common.h" static bool plugged = false; @@ -6,6 +7,36 @@ static bool battery_charging = false; static Ion::Battery::Charge battery_level = Ion::Battery::Charge::FULL; static time_t last_pull = 0; +static Handle ptmsysmHandle = 0; + +static Result common_ptmsysmInit() { + return srvGetServiceHandle(&ptmsysmHandle, "ptm:sysm"); +} + +static Result common_ptmsysmExit() { + return svcCloseHandle(ptmsysmHandle); +} + +Result Ion::Simulator::CommonDriver::common_ptmsysmSetInfoLedPattern(RGBLedPattern pattern) { + if (ptmsysmHandle == 0) + return -1; + + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x8010640; + memcpy(&ipc[1], &pattern, 0x64); + Result ret = svcSendSyncRequest(ptmsysmHandle); + if(ret < 0) return ret; + return ipc[1]; +} + +void Ion::Simulator::CommonDriver::init() { + common_ptmsysmInit(); +} + +void Ion::Simulator::CommonDriver::deinit() { + common_ptmsysmExit(); +} + bool Ion::Simulator::CommonDriver::isPlugged() { pullData(); return plugged; diff --git a/ion/src/simulator/3ds/driver/common.h b/ion/src/simulator/3ds/driver/common.h index 4707bf3f4..3e7ea336b 100644 --- a/ion/src/simulator/3ds/driver/common.h +++ b/ion/src/simulator/3ds/driver/common.h @@ -3,17 +3,28 @@ #include #include +#include <3ds.h> #define PULL_DELAY 1.0f +typedef struct { + u32 ani; + u8 r[32]; + u8 g[32]; + u8 b[32]; +} RGBLedPattern; + namespace Ion { namespace Simulator { namespace CommonDriver { +void init(); +void deinit(); void pullData(); bool isPlugged(); bool isCharging(); Ion::Battery::Charge getLevel(); +Result common_ptmsysmSetInfoLedPattern(RGBLedPattern pattern); } } diff --git a/ion/src/simulator/3ds/driver/led.cpp b/ion/src/simulator/3ds/driver/led.cpp index 91e0cb0b4..819390f57 100644 --- a/ion/src/simulator/3ds/driver/led.cpp +++ b/ion/src/simulator/3ds/driver/led.cpp @@ -1,18 +1,79 @@ #include +#include +#include +#include + +#include +#include <3ds.h> +#include "common.h" + +static KDColor sLedColor = KDColorBlack; namespace Ion { namespace LED { KDColor getColor() { - return KDColorBlack; + return sLedColor; } -void setColor(KDColor c) {} +void setColor(KDColor c) { + sLedColor = c; + + /* + * According to https://www.3dbrew.org/wiki/MCURTC:SetInfoLEDPattern + * annimation pattern is as follow + * u8 ??? | u8 loop_delay | u8 smoothing | u8 delay + */ + RGBLedPattern pat; + memset(&pat, 0, sizeof(pat)); + + for(int i = 0; i < 32; i++) { + pat.r[i] = sLedColor.red(); + pat.g[i] = sLedColor.green(); + pat.b[i] = sLedColor.blue(); + } + + pat.ani = 0x20; + + Ion::Simulator::CommonDriver::common_ptmsysmSetInfoLedPattern(pat); +} -void setBlinking(uint16_t period, float dutyCycle) {} +void setBlinking(uint16_t period, float dutyCycle) { + uint8_t period_3ds = (uint8_t)((float)(period)*0.016f); + uint8_t duty_3ds = (uint8_t)(dutyCycle*32.0f); + + /* + * According to https://www.3dbrew.org/wiki/MCURTC:SetInfoLEDPattern + * annimation pattern is as follow + * u8 ??? | u8 loop_delay | u8 smoothing | u8 delay + * + * Se, we seet ??? to 0, loop_delay to 0 (to have it loop) + */ + RGBLedPattern pat; + memset(&pat, 0, sizeof(pat)); + + for(int i = 0; i < duty_3ds && i < 32; i++) { + pat.r[i] = (sLedColor.red() > 0) ? 255 : 0; + pat.g[i] = (sLedColor.green() > 0) ? 255 : 0; + pat.b[i] = (sLedColor.blue() > 0) ? 255 : 0; + } + + pat.ani = period_3ds; + + Ion::Simulator::CommonDriver::common_ptmsysmSetInfoLedPattern(pat); +} KDColor updateColorWithPlugAndCharge() { - return KDColorBlack; + KDColor ledColor = getColor(); + if (ExamMode::FetchExamMode() == 0) { // If exam mode is on, we do not update the LED with the plugged/charging state + if (USB::isPlugged()) { + ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen; + } else { + ledColor = KDColorBlack; + } + setColor(ledColor); + } + return ledColor; } } diff --git a/ion/src/simulator/3ds/main.cpp b/ion/src/simulator/3ds/main.cpp index 5b4d29ce1..c0b38e9c4 100644 --- a/ion/src/simulator/3ds/main.cpp +++ b/ion/src/simulator/3ds/main.cpp @@ -13,6 +13,8 @@ #include <3ds.h> +#include "driver/common.h" + void Ion::Timing::msleep(uint32_t ms) { svcSleepThread((s64) ms * 1000); } @@ -43,6 +45,7 @@ static bool sNeedsRefresh = false; void init() { gfxInitDefault(); cfguInit(); + Ion::Simulator::CommonDriver::init(); // mcuHwcInit(); ptmuInit(); relayout(); @@ -88,6 +91,7 @@ void quit() { // mcuHwcExit(); ptmuExit(); cfguExit(); + Ion::Simulator::CommonDriver::deinit(); gfxExit(); }