Skip to content

Commit 4a0011f

Browse files
committed
Complete MCU services implementation
1 parent 0076007 commit 4a0011f

20 files changed

Lines changed: 3606 additions & 86 deletions

File tree

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: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
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 delay; ///< Delay between pattern values, 1/16th of a second (1 second = 0x10)
200+
u8 smoothing; ///< Smoothing between pattern values (higher = smoother)
201+
u8 loopDelay; ///< Delay between pattern loops, 1/16th of a second (1 second = 0x10, 0xFF = pattern is played only once)
202+
u8 blinkSpeed; ///< Blink speed, when smoothing == 0x00
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;
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)