Skip to content

Commit f6c2050

Browse files
committed
Complete MCU services implementation
1 parent 36fe1ad commit f6c2050

File tree

20 files changed

+3615
-86
lines changed

20 files changed

+3615
-86
lines changed

libctru/include/3ds.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,15 @@ extern "C" {
8181
#include <3ds/services/srvpm.h>
8282
#include <3ds/services/loader.h>
8383
#include <3ds/services/y2r.h>
84+
#include <3ds/services/mcucam.h>
85+
#include <3ds/services/mcugpu.h>
86+
#include <3ds/services/mcuhid.h>
87+
#include <3ds/services/mcurtc.h>
88+
#include <3ds/services/mcusnd.h>
89+
#include <3ds/services/mcunwm.h>
8490
#include <3ds/services/mcuhwc.h>
91+
#include <3ds/services/mcupls.h>
92+
#include <3ds/services/mcucdc.h>
8593
#include <3ds/services/cdcchk.h>
8694

8795
#include <3ds/gpu/gx.h>
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
/**
2+
* @file mcu_common.h
3+
* @brief Common MCU-related definitions.
4+
*/
5+
6+
#pragma once
7+
8+
#include <3ds/types.h>
9+
10+
/// SRV notifications published by the MCU system module.
11+
enum MCU_InterruptNotification
12+
{
13+
MCUNOTIF_SHELL_STATE_CHANGE = 0x200, ///< The shell state has changed.
14+
MCUNOTIF_POWER_BUTTON_PRESSED = 0x202, ///< The power button was pressed.
15+
MCUNOTIF_POWER_BUTTON_HELD = 0x203, ///< The power button was held.
16+
MCUNOTIF_HOME_BUTTON_PRESSED = 0x204, ///< The HOME button was pressed.
17+
MCUNOTIF_HOME_BUTTON_RELEASED = 0x205, ///< The HOME button was released.
18+
MCUNOTIF_WLAN_SWITCH_TRIGGERED = 0x206, ///< The WiFi switch was triggered.
19+
MCUNOTIF_FATAL_HW_ERROR = 0x20C, ///< MCU watchdog reset occurred.
20+
MCUNOTIF_AC_ADAPTER_REMOVED = 0x20D, ///< The AC adapter was disconnected.
21+
MCUNOTIF_AC_ADAPTER_CONNECTED = 0x20E, ///< The AC adapter was connected.
22+
MCUNOTIF_STARTED_CHARGING = 0x20F, ///< The battery started charging.
23+
MCUNOTIF_STOPPED_CHARGING = 0x210, ///< The battery stopped charging.
24+
};
25+
26+
/// MCU interrupts.
27+
enum MCU_Interrupt
28+
{
29+
MCUINT_POWER_BUTTON_PRESS = BIT(0), ///< The power button was pressed.
30+
MCUINT_POWER_BUTTON_HELD = BIT(1), ///< The power button was held.
31+
MCUINT_HOME_BUTTON_PRESS = BIT(2), ///< The HOME button was pressed.
32+
MCUINT_HOME_BUTTON_RELEASE = BIT(3), ///< The HOME button was released.
33+
MCUINT_WLAN_SWITCH_TRIGGER = BIT(4), ///< The WiFi switch was triggered.
34+
MCUINT_SHELL_CLOSE = BIT(5), ///< The shell was closed (or sleep switch turned off).
35+
MCUINT_SHELL_OPEN = BIT(6), ///< The shell was opened (or sleep switch turned on).
36+
MCUINT_FATAL_HW_ERROR = BIT(7), ///< MCU watchdog reset occurred.
37+
MCUINT_AC_ADAPTER_REMOVED = BIT(8), ///< The AC adapter was disconnected.
38+
MCUINT_AC_ADAPTER_PLUGGED_IN = BIT(9), ///< The AC adapter was connected.
39+
MCUINT_RTC_ALARM = BIT(10), ///< The RTC alarm time has been reached.
40+
MCUINT_ACCELEROMETER_I2C_MANUAL_IO = BIT(11), ///< The manual accelerometer I²C read/write operation has completed.
41+
MCUINT_ACCELEROMETER_NEW_SAMPLE = BIT(12), ///< A new accelerometer sample is available.
42+
MCUINT_CRITICAL_BATTERY = BIT(13), ///< The battery is critically low.
43+
MCUINT_CHARGING_STOP = BIT(14), ///< The battery stopped charging.
44+
MCUINT_CHARGING_START = BIT(15), ///< The battery started charging.
45+
46+
MCUINT_VOL_SLIDER = BIT(22), ///< The position of the volume slider changed.
47+
48+
MCUINT_LCD_OFF = BIT(24), ///< The LCDs turned off.
49+
MCUINT_LCD_ON = BIT(25), ///< The LCDs turned on.
50+
MCUINT_BOT_BACKLIGHT_OFF = BIT(26), ///< The bottom screen backlight turned off.
51+
MCUINT_BOT_BACKLIGHT_ON = BIT(27), ///< The bottom screen backlight turned on.
52+
MCUINT_TOP_BACKLIGHT_OFF = BIT(28), ///< The top screen backlight turned off.
53+
MCUINT_TOP_BACKLIGHT_ON = BIT(29), ///< The top screen backlight turned on.
54+
};
55+
56+
/// MCU register IDs.
57+
enum MCU_RegisterId
58+
{
59+
MCUREG_VERSION_HIGH = 0x0, ///< Major version of the MCU firmware.
60+
MCUREG_VERSION_LOW = 0x1, ///< Minor version of the MCU firmware.
61+
62+
MCUREG_RESET_EVENTS = 0x2, ///< @ref MCU_ResetEventFlags
63+
64+
MCUREG_VCOM_TOP = 0x3, ///< Flicker/VCOM value for the top screen.
65+
MCUREG_VCOM_BOTTOM = 0x4, ///< Flicker/VCOM value for the bottom screen.
66+
67+
MCUREG_FIRMWARE_UPLOAD_0 = 0x5, ///< Firmware upload register.
68+
MCUREG_FIRMWARE_UPLOAD_1 = 0x6, ///< Firmware upload register.
69+
MCUREG_FIRMWARE_UPLOAD_2 = 0x7, ///< Firmware upload register.
70+
71+
MCUREG_3D_SLIDER_POSITION = 0x8, ///< Position of the 3D slider.
72+
MCUREG_VOLUME_SLIDER_POSITION = 0x9, ///< Position of the volume slider.
73+
74+
MCUREG_BATTERY_PCB_TEMPERATURE = 0xA, ///< Temperature of the battery, measured on a sensor on the PCB.
75+
MCUREG_BATTERY_PERCENTAGE_INT = 0xB, ///< Integer part of the battery percentage.
76+
MCUREG_BATTERY_PERCENTAGE_FRAC = 0xC, ///< Fractional part of the battery percentage.
77+
MCUREG_BATTERY_VOLTAGE = 0xD, ///< Voltage of the battery, in units of 20 mV.
78+
79+
MCUREG_POWER_STATUS = 0xF, ///< @ref MCU_PowerStatusFlags
80+
81+
MCUREG_LEGACY_VERSION_HIGH = 0xF, ///< (Old MCU_FIRM only) Major firmware version.
82+
MCUREG_LEGACY_VERSION_LOW = 0x10, ///< (Old MCU_FIRM only) Minor firmware version.
83+
MCUREG_LEGACY_FIRM_UPLOAD = 0x3B, ///< (Old MCU_FIRM only) Firmware upload register.
84+
85+
MCUREG_RECEIVED_IRQS = 0x10, ///< Bitmask of received IRQs. @ref MCU_Interrupt
86+
MCUREG_IRQ_MASK = 0x18, ///< Bitmask of enabled IRQs. @ref MCU_Interrupt
87+
88+
MCUREG_PWR_CTL = 0x20, ///< @ref MCU_PowerTrigger
89+
MCUREG_LCD_PWR_CTL = 0x22, ///< @ref MCU_PowerStatusFlags
90+
MCUREG_MCU_RESET_CTL = 0x23, ///< Writing 'r' to this register resets the MCU. Stubbed on retail.
91+
MCUREG_FORCE_SHUTDOWN_DELAY = 0x24, ///< The amount of time, in units of 0.125s, for which the power button needs to be held to trigger a hard shutdown.
92+
93+
MCUREG_VOLUME_UNK_25 = 0x25, ///< Unknown register. Used in mcu::SND
94+
MCUREG_UNK_26 = 0x26, ///< Unknown register. Used in mcu::CDC
95+
96+
MCUREG_LED_BRIGHTNESS_STATE = 0x28, ///< Brightness of the status LEDs.
97+
MCUREG_POWER_LED_STATE = 0x29, ///< @ref MCU_PowerLedState
98+
MCUREG_WLAN_LED_STATE = 0x2A, ///< Controls the WiFi LED.
99+
MCUREG_CAMERA_LED_STATE = 0x2B, ///< Controls the camera LED (on models that have one).
100+
MCUREG_3D_LED_STATE = 0x2C, ///< Controls the 3D LED (on models that have one).
101+
MCUREG_NOTIFICATION_LED_STATE = 0x2D, ///< @ref MCU_InfoLedPattern
102+
MCUREG_NOTIFICATION_LED_CYCLE_STATE = 0x2E, ///< Bit 0 is set if the info (notification) LED has started a new cycle of its pattern.
103+
104+
MCUREG_RTC_TIME_SECOND = 0x30, ///< RTC second.
105+
MCUREG_RTC_TIME_MINUTE = 0x31, ///< RTC minute.
106+
MCUREG_RTC_TIME_HOUR = 0x32, ///< RTC hour.
107+
MCUREG_RTC_TIME_WEEKDAY = 0x33, ///< RTC day of the week.
108+
MCUREG_RTC_TIME_DAY = 0x34, ///< RTC day of the month.
109+
MCUREG_RTC_TIME_MONTH = 0x35, ///< RTC month.
110+
MCUREG_RTC_TIME_YEAR = 0x36, ///< RTC year.
111+
MCUREG_RTC_TIME_CORRECTION = 0x37, ///< RTC subsecond (RSUBC) correction value.
112+
113+
MCUREG_RTC_ALARM_MINUTE = 0x38, ///< RTC alarm minute.
114+
MCUREG_RTC_ALARM_HOUR = 0x39, ///< RTC alarm hour.
115+
MCUREG_RTC_ALARM_DAY = 0x3A, ///< RTC alarm day.
116+
MCUREG_RTC_ALARM_MONTH = 0x3B, ///< RTC alarm month.
117+
MCUREG_RTC_ALARM_YEAR = 0x3C, ///< RTC alarm year.
118+
119+
MCUREG_TICK_COUNTER_LSB = 0x3D, ///< MCU tick counter value (low byte).
120+
MCUREG_TICK_COUNTER_MSB = 0x3E, ///< MCU tick counter value (high byte).
121+
122+
MCUREG_SENSOR_CONFIG = 0x40, ///< @ref MCU_SensorConfig
123+
124+
MCUREG_ACCELEROMETER_MANUAL_REGID_R = 0x41, ///< Hardware register ID for use in manual accelerometer I²C reads.
125+
MCUREG_ACCELEROMETER_MANUAL_REGID_W = 0x43, ///< Hardware reigster ID for use in manual accelerometer I²C writes.
126+
MCUREG_ACCELEROMETER_MANUAL_IO = 0x44, ///< Data register for manual accelerometer reads/writes.
127+
MCUREG_ACCELEROMETER_OUTPUT_X_LSB = 0x45, ///< Accelerometer X coordinate (low byte).
128+
MCUREG_ACCELEROMETER_OUTPUT_X_MSB = 0x46, ///< Accelerometer X coordinate (high byte).
129+
MCUREG_ACCELEROMETER_OUTPUT_Y_LSB = 0x47, ///< Accelerometer Y coordinate (low byte).
130+
MCUREG_ACCELEROMETER_OUTPUT_Y_MSB = 0x48, ///< Accelerometer Y coordinate (high byte).
131+
MCUREG_ACCELEROMETER_OUTPUT_Z_LSB = 0x49, ///< Accelerometer Z coordinate (low byte).
132+
MCUREG_ACCELEROMETER_OUTPUT_Z_MSB = 0x4A, ///< Accelerometer Z coordinate (high byte).
133+
134+
MCUREG_PEDOMETER_STEPS_LOWBYTE = 0x4B, ///< Pedometer step count (low byte).
135+
MCUREG_PEDOMETER_STEPS_MIDDLEBYTE = 0x4C, ///< Pedometer step count (middle byte).
136+
MCUREG_PEDOMETER_STEPS_HIGHBYTE = 0x4D, ///< Pedometer step count (high byte).
137+
MCUREG_PEDOMETER_CNT = 0x4E, ///< @ref MCU_PedometerControl
138+
MCUREG_PEDOMETER_STEP_DATA = 0x4F, ///< @ref MCU_PedometerStepData
139+
MCUREG_PEDOMETER_WRAP_MINUTE = 0x50, ///< The minute within each RTC hour at which the step history should roll into the next hour.
140+
MCUREG_PEDOMETER_WRAP_SECOND = 0x51, ///< The second within each RTC hour at which the step history should roll into the next hour.
141+
142+
MCUREG_VOLUME_CALIBRATION_MIN = 0x58, ///< Lower bound of sound volume.
143+
MCUREG_VOLUME_CALIBRATION_MAX = 0x59, ///< Upper bound of sound volume.
144+
145+
MCUREG_STORAGE_AREA_OFFSET = 0x60, ///< Offset within the storage area to read/write to.
146+
MCUREG_STORAGE_AREA = 0x61, ///< Input/output byte for write/read operations in the storage area.
147+
148+
MCUREG_INFO = 0x7F, ///< System information register.
149+
};
150+
151+
enum MCU_ResetEventFlags
152+
{
153+
MCU_RESETFLG_RTC_TIME_LOST = BIT(0), ///< RTC time was lost (as is the case when the battery is removed).
154+
MCU_RESETFLG_WATCHDOG_RESET = BIT(1), ///< MCU Watchdog reset occurred.
155+
};
156+
157+
enum MCU_PowerStatusFlags
158+
{
159+
MCU_PWRSTAT_SHELL_OPEN = BIT(1), ///< Set if the shell is open.
160+
MCU_PWRSTAT_ADAPTER_CONNECTED = BIT(3), ///< Set if the AC adapter is connected.
161+
MCU_PWRSTAT_CHARGING = BIT(4), ///< Set if the battery is charging.
162+
MCU_PWRSTAT_BOTTOM_BL_ON = BIT(5), ///< Set if the bottom backlight is on.
163+
MCU_PWRSTAT_TOP_BL_ON = BIT(6), ///< Set if the top backlight is on.
164+
MCU_PWRSTAT_LCD_ON = BIT(7) ///< Set if the LCDs are on.
165+
};
166+
167+
enum MCU_PedometerControl
168+
{
169+
MCU_PEDOMETER_CLEAR = BIT(0), ///< Clear the step history.
170+
MCU_PEDOMETER_STEPS_FULL = BIT(4) ///< Set when the step history is full.
171+
};
172+
173+
enum MCU_PowerTrigger
174+
{
175+
MCU_PWR_SHUTDOWN = BIT(0), ///< Turn off the system.
176+
MCU_PWR_RESET = BIT(1), ///< Reset the MCU.
177+
MCU_PWR_REBOOT = BIT(2), ///< Reboot the system.
178+
MCU_PWR_LGY_SHUTDOWN = BIT(3), ///< Turn off the system. (Used by LgyBg)
179+
MCU_PWR_SLEEP = BIT(4), ///< Signal to enter sleep mode.
180+
OLDMCU_BL_OFF = BIT(4), ///< (Old MCU_FIRM only) turn the backlights off.
181+
OLDMCU_BL_ON = BIT(5), ///< (Old MCU_FIRM only) turn the backlights on.
182+
OLDMCU_LCD_OFF = BIT(6), ///< (Old MCU_FIRM only) turn the LCDs off.
183+
OLDMCU_LCD_ON = BIT(7), ///< (Old MCU_FIRM only) turn the LCDs on.
184+
};
185+
186+
typedef enum MCU_PowerLedState
187+
{
188+
LED_NORMAL = 0, ///< Fade power LED to blue, while checking for battery percentage.
189+
LED_FADE_BLUE = 1, ///< Fade power LED to blue.
190+
LED_SLEEP_MODE = 2, ///< The power LED pulses blue slowly, as it does in sleep mode.
191+
LED_OFF = 3, ///< Power LED fades off.
192+
LED_RED = 4, ///< Power LED instantaneously turns red.
193+
LED_BLUE = 5, ///< Power LED instantaneously turns blue.
194+
LED_BLINK_RED = 6, ///< Power LED and info (notification) LED blink red, as they do when the battery is critically low.
195+
} MCU_PowerLedState;
196+
197+
typedef struct MCU_InfoLedAnimation
198+
{
199+
u8 ticksPerFrame; ///< The amount of time (in ticks), for which a given frame is active. Must be nonzero. (See @ref mcuTicksFromMs)
200+
u8 frameTransitionDelay; ///< Amount of time (in ticks) between pattern frames. (See @ref mcuTicksFromMs) Set to 0 to disable interpolation, or equal to ticksPerFrame for linear interpolation.
201+
u8 numLastFrameRepeats; ///< The amount of times for which the last frame should be repeated. Treated as if the pattern contains numLastFrameRepeats more of the last frame than it actually does. Set to 0xFF to repeat forever.
202+
u8 _pad;
203+
} MCU_InfoLedAnimation;
204+
205+
typedef struct MCU_InfoLedPattern
206+
{
207+
MCU_InfoLedAnimation animation; ///< Animation.
208+
u8 redPattern[32]; ///< Pattern for red component.
209+
u8 greenPattern[32]; ///< Pattern for green component.
210+
u8 bluePattern[32]; ///< Pattern for blue component.
211+
} MCU_InfoLedPattern;
212+
213+
typedef enum MCU_WifiMode
214+
{
215+
WIFI_MODE_CTR = 0, ///< 3DS WiFi mode.
216+
WIFI_MODE_MP = 1, ///< DS[i] WiFi mode ("MP").
217+
} MCU_WifiMode;
218+
219+
typedef struct MCU_RtcTime
220+
{
221+
u8 second; ///< RTC second.
222+
u8 minute; ///< RTC minute.
223+
u8 hour; ///< RTC hour.
224+
u8 weekday; ///< RTC day of the week.
225+
u8 monthday; ///< RTC day of the month.
226+
u8 month; ///< RTC month.
227+
u8 year; ///< RTC year (since 2000).
228+
} MCU_RtcTime;
229+
230+
typedef struct MCU_RtcAlarmTime
231+
{
232+
u8 minute; ///< RTC alarm minute.
233+
u8 hour; ///< RTC alarm hour.
234+
u8 day; ///< RTC alarm day.
235+
u8 month; ///< RTC alarm day of the month.
236+
u8 year; ///< RTC alarm year (since 2000).
237+
} CTR_PACKED MCU_RtcAlarmTime;
238+
239+
typedef enum MCU_SensorConfig
240+
{
241+
MCU_SENSOR_ACCELEROMETER_ENABLE = BIT(0), ///< If set, the accelerometer is enabled.
242+
MCU_SENSOR_PEDOMETER_ENABLE = BIT(1), ///< If set, the pedometer is enabled.
243+
} MCU_SensorConfig;
244+
245+
typedef struct MCU_AccelerometerData
246+
{
247+
s16 x; ///< X coordinate of the current accelerometer sample.
248+
s16 y; ///< Y coordinate of the current accelerometer sample.
249+
s16 z; ///< Z coordinate of the current accelerometer sample.
250+
} MCU_AccelerometerData;
251+
252+
typedef struct MCU_PedometerStepData
253+
{
254+
struct MCU_PedometerTime
255+
{
256+
u8 hour; ///< RTC hour at the time of the update.
257+
u8 monthday; ///< RTC day of the month at the time of the update.
258+
u8 month; ///< RTC month at the time of the update.
259+
u8 year; ///< RTC year (since 2000) at the time of the update.
260+
u8 minute; ///< RTC minute at the time of the update.
261+
u8 second; ///< RTC second at the time of the update.
262+
} pedometerTime; ///< RTC timestamp for the time this data was last updated.
263+
u16 stepCounts[7 * 24]; ///< Step counts for every hour in the week, with the last element referring to the current hour.
264+
} CTR_PACKED MCU_PedometerStepData;
265+
266+
typedef enum MCU_AccelerometerScale
267+
{
268+
ACC_SCALE_2G = 0x0, ///< -2G to 2G
269+
ACC_SCALE_4G = 0x1, ///< -4G to 4G
270+
ACC_SCALE_8G = 0x3, ///< -8G to 8G
271+
} MCU_AccelerometerScale;
272+
273+
typedef struct MCU_LgyLcdSettings
274+
{
275+
u8 enableAblPowersave : 1; ///< Whether or not ABL (adaptive backlight) power save is enabled.
276+
u8 luminanceLevel : 3; ///< The brightness level (1-5).
277+
u8 _unused : 4;
278+
} MCU_LgyLcdSettings;
279+
280+
static inline u8 mcuTicksFromMs(u32 ms)
281+
{
282+
// 512Hz
283+
u32 res = 512u * ms / 1000u;
284+
res = res < 2 ? 1 : res - 1; // res not allowed to be zero
285+
res = res > 255 ? 255 : res; // res can't exceed 255
286+
return (u8)res;
287+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @file mcucam.h
3+
* @brief MCU Camera service.
4+
*/
5+
#pragma once
6+
7+
#include <3ds/types.h>
8+
#include <3ds/services/mcu_common.h>
9+
10+
/// Initializes mcuCam.
11+
Result mcuCamInit(void);
12+
13+
/// Exits mcuCam.
14+
void mcuCamExit(void);
15+
16+
/**
17+
* @brief Gets the current mcuCam session handle.
18+
* @return A pointer to the current mcuCam session handle.
19+
*/
20+
Handle *mcuCamGetSessionHandle(void);
21+
22+
/**
23+
* @brief Sets the camera LED state.
24+
* @param on Whether or not the camera LED should be turned on.
25+
*/
26+
Result MCUCAM_SetCameraLedState(bool on);
27+
28+
/**
29+
* @brief Returns whether or not the camera LED is on.
30+
* @param out_on Pointer to output whether or not the camera LED is on.
31+
*/
32+
Result MCUCAM_GetCameraLedState(bool *out_on);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @file mcucdc.h
3+
* @brief MCU CODEC service.
4+
*/
5+
#pragma once
6+
7+
#include <3ds/types.h>
8+
#include <3ds/services/mcu_common.h>
9+
10+
/// Initializes mcuCdc.
11+
Result mcuCdcInit(void);
12+
13+
/// Exits mcuCdc.
14+
void mcuCdcExit(void);
15+
16+
/**
17+
* @brief Gets the current mcuCdc session handle.
18+
* @return A pointer to the current mcuCdc session handle.
19+
*/
20+
Handle *mcuCdcGetSessionHandle(void);
21+
22+
/**
23+
* @brief Writes bit 4 to MCU register 26h.
24+
*/
25+
Result MCUCDC_SetReg26h();

0 commit comments

Comments
 (0)