3DS reverse engineering

Discussion of development of software for any "obsolete" computer or video game system.
nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sat Sep 21, 2019 6:00 pm

Accelerometer
This is now more or less solved. The chip is said to be ST LIS331DLH, and software-wise, that seems to be correct. Ie. the register map looks as so:

Code: Select all

LIS331DLH Accelerometer Register address map
  Name                     Type Addr  Default Comment Hex Binary
  Reserved (do not modify)   -  00-0E -         Reserved
  WHO_AM_I                   r  0F    00110010  Dummy register
  Reserved (do not modify)   -  10-1F -         Reserved
  CTRL_REG1                  rw 20    00000111
  CTRL_REG2                  rw 21    00000000
  CTRL_REG3                  rw 22    00000000
  CTRL_REG4                  rw 23    00000000
  CTRL_REG5                  rw 24    00000000
  HP_FILTER_RESET            r  25    -         Dummy register
  REFERENCE                  rw 26    00000000
  STATUS_REG                 r  27    00000000
  OUT_X_L                    r  28    output
  OUT_X_H                    r  29    output
  OUT_Y_L                    r  2A    output
  OUT_Y_H                    r  2B    output
  OUT_Z_L                    r  2C    output
  OUT_Z_H                    r  2D    output
  Reserved (do not modify)   -  2E-2F -         Reserved
  INT1_CFG                   rw 30    00000000
  INT1_SOURCE                r  31    00000000
  INT1_THS                   rw 32    00000000
  INT1_DURATION              rw 33    00000000
  INT2_CFG                   rw 34    00000000
  INT2_SOURCE                r  35    00000000
  INT2_THS                   rw 36    00000000
  INT2_DURATION              rw 37    00000000
  Reserved (do not modify)   -  38-3F -         Reserved
  Undocumented (zero)        -  40-7F
  As above with auto-increment  80-FF
And Hardware-wise...
On Old3DS it is marked ""2048, 33DH, X1MAQ", which is said to be ST LIS331DLH.
On New3DSXL it is marked "KXTKK, 40860, .3413", which might be a Kionix chip, resembling KXTIK, but with LIS331DLH-style register map & device address.

The chip is wired to the MCU, so it's I2C registers can be accessed only indirectly, through the MCU. The related MCU registers on 3dbrew are mostly left undocumented, or even mistaken as gyroscope registers ; )
The actual functions for MCU register 40h..4Fh are:

Code: Select all

  40h          R/W  Accelerometer Mode (bit0,1) (enable/mode flags or so?)
  41h          R/W  Accelerometer I2C Index for manual read  (via MCU[44h])
  42h          R/W  Unused?
  43h          R/W  Accelerometer I2C Index for manual write (via MCU[44h])
  44h          R/W  Accelerometer I2C Dat from/to read/write (via MCU[41h/43h])
  45h,46h      R    Accelerometer Output X (lsb,msb)
  47h,48h      R    Accelerometer Output Y (lsb,msb)
  49h,4Ah      R    Accelerometer Output Z (lsb,msb)
  4Bh          R/W  Pedometer Step Count, bit0-7    ;\(for the current day)
  4Ch          R/W  Pedometer Step Count, bit8-15   ; (uh, how/which day?)
  4Dh          R/W  Pedometer Step Count, bit16-23  ;/
  4Eh          R/W  Pedometer Flags (Wr.bit0=ClearArray?, Rd.bit4=ArrayFull?)
  4Fh          R    Pedometer Array[6+N]   ;timestamp[6] and step.counts[2*A8h]
The Pedometer is some software feature in the MCU that converts the accelerometer data to step counters. Reading the Output X/Y/Z registers would be the normal way to get the accelerometer data (if enabled in the mode register). The manual read/write feature allows to view/modify I2C registers directly; for debugging/hacking purposes or so. The manual read/write seem to be done in a callback function (=not immediately after writing register 41h or 44h), and, before touching further accelerometer registers, one must wait until the callback has executed (which is indicated by MCU.interrupt.bit11).

Both Old3DS and New3DSXL have the chip on the mainboard, somewhere underneath of the bottom-screen. That (and the exact location) may be important when interpreting the accelerometer data (ie. the chip isn't parallel with the top-screen unless the case is fully unfolded).

With the pedometer feature... I guess that means that the accelerometer chip is always (or maybe optionally) battery-powered, even when the console is off?

Pokun
Posts: 1324
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 3DS reverse engineering

Post by Pokun » Sun Sep 22, 2019 3:13 am

Why does the accelerometer needs to be powered when power is off? The pedometer, for the purpose of Play Coins and the pre-installed statistic app "Omoide Kirokuchou", doesn't count steps when the 3DS is off. Only when it's on and in sleep mode by shutting the lid (or by using a small magnet around the A, B, X and Y buttons).

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Sep 22, 2019 8:29 am

I just guessed so, because the chip is wired to MCU, and the MCU is itself battery powered (at least for the RTC and RAM sections), and it could have made sense to support the step counter even when powered off.
But supporting it in sleep mode only makes sense, too. I have just checked: In "off" state both supply pins of the accelerometer (pin1+14) are 0V. So yes, it isn't always on. Good to know, thanks for that detail!

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Sep 22, 2019 9:36 am

Gyroscopes
This was a bit confusing because there are two different/incompatible gyroscope versions (with only one of them being known so far).

Old Gyroscope
The old gyroscope is described on ifixit/3dbrew. I2C Bus and Device number should be 2:D0h.
The part number is ITG-3270 (can be seen on the ifixit 3DS teardown photos; just clicking the photo links to a blurred image, but clicking on the magnification glass symbol links to hires; and there is also a text link next to the image, that does also link to hires, but in raw quality - without the colored rectangles).
For datasheets, the ITG-3200 datasheet is reportedly matching for the ITG-3270 chip. If that's true, then the register map would look as so:

Code: Select all

  Hex Register Name Res R/W
  00h WHO_AM_I      (-) R/W Device ID (aka Who Am I) (should be 58h or 69h or so)
  15h SMPLRT_DIV    00h R/W Sample Rate Divider
  16h DLPF_FS       00h R/W DLPF, Full Scale
  17h INT_CFG       00h R/W Interrupt Configuration
  1Ah INT_STATUS    00h R   Interrupt Status
  1Bh TEMP_OUT_H    -   R   TEMP_OUT_H
  1Ch TEMP_OUT_L    -   R   TEMP_OUT_L
  1Dh GYRO_XOUT_H   -   R   GYRO_XOUT_H
  1Eh GYRO_XOUT_L   -   R   GYRO_XOUT_L
  1Fh GYRO_YOUT_H   -   R   GYRO_YOUT_H
  20h GYRO_YOUT_L   -   R   GYRO_YOUT_L
  21h GYRO_ZOUT_H   -   R   GYRO_ZOUT_H
  22h GYRO_ZOUT_L   -   R   GYRO_ZOUT_L
  3Eh PWR_MGM       00h R/W Power Management
  xxh-FFh Undocumented (unknown)
New Gyroscope
What I have found in the New3DSXL is completely different: The bus/device is 2:D2h (not 2:D0h), and the part number is "IT3B,315BA1,LT425A", and the TEMP/GYRO_OUT registers are somewhere at index 40h and up, and the WHO_AM_I register is at index 75h.
Searching for datasheets with WHO_AM_I and value 75h (or 117 decimal), there are quite a bunch...

Code: Select all

     --> alike ICM-20608  ;16pin LGA 3xGyro+3xAccel
     --> alike ICM-20689  ;24pin QFN 3xGyro+3xAccel
     --> alike IAM-20680            ;3xGyro+3xAccel?
     --> alike ICM-20789            ;3xGyro+3xAccel?
     --> alike MPU-9250   ;24pin QFN 3xGyro+3xAccel+3xMagneto
     --> alike MPU-6000/6050    ;QFN 3xGyro+3xAccel+3xMagneto
     --> alike MPU-6555             ;3xGyro+3xAccel
     --> alike ICG-1020S  ;12pin LGA 2xGyro (only 2-axis)
     --> alike ITG-1010   ;16pin QFN 3xGyro <------ THIS looks alike New3DSXL
Most of that chips are also having a built-in accelerometer (which is a separate chip in 3DS's), so the ITG-1010 chip looks closest to the New3DSXL hardware. The register map for that chip would be:

Code: Select all

  Hex Dec Register Name I/F  Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
  04h 04  XG_OFFS_TC_H R/W - - - - - - XG_OFFS_TC_H [9] XG_OFFS_TC_H [8]
  05h 05  XG_OFFS_TC_L R/W XG_OFFS_TC_L [7:0]
  07h 07  YG_OFFS_TC_H R/W - - - - - - YG_OFFS_TC_H [9] YG_OFFS_TC_H [8]
  08h 08  YG_OFFS_TC_L R/W YG_OFFS_TC_L [7:0]
  0Ah 10  ZG_OFFS_TC_H R/W - - - - - - ZG_OFFS_TC_H [9] ZG_OFFS_TC_H [8]
  0Bh 11  ZG_OFFS_TC_L R/W ZG_OFFS_TC_L [7:0]
  13h 19  XG_OFFS_USRH R/W X_OFFS_USR[15:8]
  14h 20  XG_OFFS_USRL R/W X_OFFS_USR[7:0]
  15h 21  YG_OFFS_USRH R/W Y_OFFS_USR[15:8]
  16h 22  YG_OFFS_USRL R/W Y_OFFS_USR[7:0]
  17h 23  ZG_OFFS_USRH R/W Z_OFFS_USR[15:8]
  18h 24  G_OFFS_USRL  R/W Z_OFFS_USR[7:0]
  19h 25  SMPLRT_DIV   R/W SMPLRT_DIV[7:0]
  1Ah 26  CONFIG       R/W - FIFO_MODE EXT_SYNC_SET[2:0] DLPF_CFG[2:0]
  1Bh 27  GYRO_CONFIG  R/W XG_ST YG_ST ZG_ST FS_SEL [1:0] - FCHOICE_B[1:0]
  23h 35  FIFO_EN      R/W TEMP_FIFO_EN XG_FIFO_EN YG_FIFO_EN ZG_FIFO_EN - - - -
  37h 55  INT_PIN_CFG  R/W INT_LEVEL INT_OPEN LATCH_INT_EN INT_RD_CLEAR FSYNC_INT_LEVEL FSYNC_INT_MODE_EN - -
  38h 56  INT_ENABLE   R/W - - - FIFO_OFLOW_EN FSYNC_INT_EN - - DATA_RDY_EN
  3Ah 58  INT_STATUS   R   - - - FIFO_OFLOW_INT FSYNC_INT - - DATA_RDY_INT
  41h 65  TEMP_OUT_H   R   TEMP_OUT[15:8]
  42h 66  TEMP_OUT_L   R   TEMP_OUT[7:0]
  43h 67  GYRO_XOUT_H  R   GYRO_XOUT[15:8]
  44h 68  GYRO_XOUT_L  R   GYRO_XOUT[7:0]
  45h 69  GYRO_YOUT_H  R   GYRO_YOUT[15:8]
  46h 70  GYRO_YOUT_L  R   GYRO_YOUT[7:0]
  47h 71  GYRO_ZOUT_H  R   GYRO_ZOUT[15:8]
  48h 72  GYRO_ZOUT_L  R   GYRO_ZOUT[7:0]
  6Ah 106 USER_CTRL    R/W - FIFO_EN - I2C_IF_DIS - FIFO_RESET - SIG_COND_RESET
  6Bh 107 PWR_MGMT_1   R/W DEVICE_RESET SLEEP - - TEMP_DIS CLKSEL[2:0]
  6Ch 108 PWR_MGMT_2   R/W - - - - STBY_XG STBY_YG STBY_ZG
  72h 114 FIFO_COUNTH  R/W - - - - - - FIFO_COUNT[9:8]
  73h 115 FIFO_COUNTL  R/W FIFO_COUNT[7:0]
  74h 116 FIFO_R_W     R/W FIFO_DATA[7:0]
  75h 117 WHO_AM_I     R   - WHO_AM_I[6:1] - (reads as 68h)
  80h-FFh Undocumented (in New3DSXL these are same as 00h-7Fh)
That looks more or less right, the outputs at 41h..48h seem to be okay, and the WHO_AM_I at 75h is okay, and 3Ah has the RDY bit set. Most others are zero, except 6Bh has bit0 set, uhm, and 00h..0Fh have non-zero values:

Code: Select all

BD DB D1 29  9C 1D 20 67  F4 1A 8C 08  B1 71 00 00
That values are weird. The datasheet says that everything except WHO_AM_I is zero on reset - although, a few lines later, it is stating that the OFFS_TC values at 04h..0Bh are factory-programmed, so those can be non-zero, except that the High bytes at 04h,07h,0Ah should be only 2bit wide, that doesn't match up with what I am seeing.
For the first two bytes (BDh, DBh), I have found some old docs for clumsy RS232 gyroscopes that are stating "1 0xBD First header byte 2 0xDB Second header". Either that's just coincidence, or that two bytes are an undocumented relict from older gyro protocols.
Hmmm, and the part number, "IT3B,315BA1,LT425A" doesn't really sound like an abbreviation for ITG-1010, the IT3B might rather hint on something like the old ITG-3xxx part number. But those 4-letter chip codes are often meaningless, and, for now, ITG-1010 seems to be the best matching datasheet.
Last edited by nocash on Fri Oct 18, 2019 2:59 am, edited 2 times in total.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Sep 22, 2019 10:11 am

The GYRO X/Y/Z OUT values are signed offsets since last sample (or since last read). Ie. they are zero when the console isn't moving.
Or at least almost zero...

Even when firmly seated on a table, the LSBs are having some dirt, and only the MSBs are 00h.
That means the values are something like 00xxh+/-dirt (rather than 0000h+/-dirt, which would result in MSB=00h/FFh).

Are there calibration offsets in the 3DS filesystem files that could help to get rid of the 00xxh errors?
Otherwise software could try to auto-calibrate itself.
Or prompt users for manual calibration.
Or simply ignore values close to 0000h (but that might badly hurt resolution for slow movements).

lidnariq
Posts: 9034
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: 3DS reverse engineering

Post by lidnariq » Sun Sep 22, 2019 10:30 am

nocash wrote:The GYRO X/Y/Z OUT values are signed offsets since last sample (or since last read)
Digital gyroscopes give a direct measurement of the rotational velocity ω (often in radians/second, but I've seen others). If you have access to a physical phonograph turntable (or anything else with a predictable rotational velocity), you should be able to figure out the units you're getting.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Sep 22, 2019 7:23 pm

Ah, I was thinking that the values were similar as for mouse reads (where you get a "distance" since last read). And I would have thought that gyroscopes are also measuring offsets to initial direction, or offset to most recent direction?
But, well, if it is a "rotation speed" value, then one would need to compute the angle since last read based on the time since last read:

Code: Select all

  angle_offset = rotation_speed * time
On the other hand, if reading is done at a constant rate, then one could just declare it as:

Code: Select all

  angle_offset = rotation_speed
and eventually multiply it by a general-purpose constant that contains the fixed time value, and any adjustments for number of fractional bits, and whatever conversions between rotations/radians/degrees.

Yeah, a turn table with 33rpm might help. Or just displaying an arrow or compass needle on the screen, and then tweaking the software to keep it always pointing in one direction. I am wondering how long it could maintain that direction?
For example, if it were told to point "north", and gets turned a bunch of times back and forth, and if there are conversion errors, rounding errors, and calibration errors... I guess that it would quickly forget where "north" was exacly. Or are those digital gyros more reliable than I think?

If it does also forget what is "horizontal" and what is "vertical", that might be even more confusing. And possibly difficult to recalibrate that on the fly... it might work only by guessing if the user is currently holding the console in horizontal orientation.

Getting back to how a mouse input is working: I am just wondering if gyro input could benefit from things like double-speed-threshold.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Sep 22, 2019 8:03 pm

New3DS 16bit IO Expander (aka QTM)
I2C Bus/device 0:40h goes to a 16bit IO Expander (aka a 16bit gpio, aka TCA6416A chip). The I2C registers are:

Code: Select all

16bit IO Expander I2C Registers (I2C Bus/Device: 0:40h)
  00h Input Port 0                    (R) (reset: var, reads as 05h on New3DS)
  01h Input Port 1                    (R) (reset: var, reads as 00h on New3DS)
  02h Output Port 0                   (R/W) (reset: FFh)
  03h Output Port 1                   (R/W) (reset: FFh)
  04h Polarity Inversion 0            (R/W) (reset: 00h=normal)
  05h Polarity Inversion 1            (R/W) (reset: 00h=normal)
  06h Configuration (aka Direction) 0 (R/W) (reset: FFh=input)
  07h Configuration (aka Direction) 1 (R/W) (reset: FFh=input)
  08h..FFh Reserved                   (-)   (FFh)
As for what the registers are used for. I could only do some far fetched guesses...
3dbrew says that the device is for QTM (that, I couldn't guess what QTM stands for).
There are some hints on QTM being related to head-tracking (whatever that is, and whatever it is good for).
The 16bit gpio itself is unlikely to be capable of head-tracking.
And I haven't spotted any other head-tracking-dedicated hardware in the component list.

So the guesses are:
Head-tracking is done by interpreting the camera input on the ARM processors, perhaps assisted by the camera's IR LED.
Head-tracking result might be passed to the parallax barrier of the stereoscopic screen, perhaps using the IO Expander chip.
Could that be right, or is it all nonsense from scratch up?

If anybody (with working top-screen) wants to verify the parallax theory:
One could output red/blue pixels for left/right eye, and then try to change the light direction using the IO expander bits.
Maybe best done with a high backlight setting, so that the screen would act as a two-color torch.
One of the IO Expander bits might also affect the IR LED, though that might be only visible when having a suitable IR receiver.

Oh, and one extra oddity: The IO Expander is wired to the I2C bus for DSi devices, and the DSi did assign the same device number to some sort of unused/debug hardware.
If any DSi titles are actually accessing that device, then all kinds or weird effects might happen in software or on hardware : )

lidnariq
Posts: 9034
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: 3DS reverse engineering

Post by lidnariq » Sun Sep 22, 2019 10:49 pm

nocash wrote:just displaying an arrow or compass needle on the screen, and then tweaking the software to keep it always pointing in one direction. I am wondering how long it could maintain that direction?
For example, if it were told to point "north", and gets turned a bunch of times back and forth, and if there are conversion errors, rounding errors, and calibration errors... I guess that it would quickly forget where "north" was exactly.
The physics works out such that you can directly measure acceleration and rotation rate as an intrinsic property of a material. (Rotation rate can be measured by having two single-axis accelerometers at a fixed separation; the common mode tells you the bulk acceleration, the differential term along the axis of the separation tells you the centrifugal force and so tells you the rotational rate)
Or are those digital gyros more reliable than I think?
A single integration (i.e. the summation you're implying) is reasonably accurate, but yes it will still drift with time. In contrast, the double integration needed to calculate position from acceleration is almost unusable given real-world measurement error.
If it does also forget what is "horizontal" and what is "vertical", that might be even more confusing. And possibly difficult to recalibrate that on the fly... it might work only by guessing if the user is currently holding the console in horizontal orientation.
My understanding is that dead reckoning works reasonably well, but not by simply integrating the outputs but instead finding moments when the total acceleration is approximately equal to 9.8m/s² and hasn't changed significantly recently.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Mon Sep 23, 2019 8:46 am

lidnariq wrote:finding moments when the total acceleration is approximately equal to 9.8m/s² and hasn't changed significantly recently.
Oops, I was so focused on the gyroscope-direction that I forgot about the accelerometer, and that the accelerometer can measure gravity.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Thu Sep 26, 2019 7:14 pm

AIC chip (Touchscreen/Sound)
I am a bit stuck with the AIC chip. The overall chip is just a customized TSC2117 (similar to that used in DSi).
On 3DS, it does reportedly additionally include the Circle Pad analog inputs, is it already known how to read that inputs?
And how to activate the microphone input (probably simple, but I think it's still unknown how to do that, even on DSi)?

Touchscreen calibration on 3DS isn't clear to me.
For 3DS mode: Is there a calibration file?
For NDS/DSi mode: The calibration data for 256x192pix NDS screens is in Wifi-Flash, but how does that translate to the 320x240pix 3DS screens...?
Does the 3DS display NDS games in a small 256x192pix window? Or does it stretch them to 320x240pix size? Or does it allow either one optionally?

Some small findings...
The 3ds touchscreen registers seem to be compatible with DSi, although some registers seem to have different power-up values.
Registers TSC[3:2Ah..45h] should theoretically contain the current ADC values, but, on both DSi+3DS, they seem to be always-zero, so one could read the data only via the ringbuffer (unless there is some way to enable the always-zero registers?).
Register TSC[0:0Dh] seems to be completely unused in existing DSi code, however, it looks as if the undocumented TSC[0:0Eh] register is serving a similar function.
And I should really update gbatek with some flowcharts for touchscreen init & dsi-to-nds-mode-switch functions (and remove some very outdated stuff that was written before finding the TSC2117 datasheet).

PS. And of course everything about the Mini-DSP instruction set is unknown, I don't even know if the DSi/3DS hardware does really implement that feature; I don't think that any DSi software is using it.

Arisotura
Posts: 6
Joined: Sun May 19, 2019 7:01 am

Re: 3DS reverse engineering

Post by Arisotura » Mon Sep 30, 2019 1:57 am

nocash wrote:Does the 3DS display NDS games in a small 256x192pix window? Or does it stretch them to 320x240pix size? Or does it allow either one optionally?
it allows both display modes, iirc you can get the native-size mode by pressing SELECT while booting a DS game, otherwise the default mode is fullscreen.


also, speaking of the touchscreen controller thing

that thing is way interesting. I wonder if there's a way to extract the microcontroller firmware or whatever?

I wondered about the miniDSP thing, but turns out the instruction set isn't public, and all TI provides is some lego-brick type building software for building audio processing flows, and it's not even a free download so if you're gonna ask for it you better be a serious company with actual plans to get a serious product into production so they will consider your "US Government Export Request" seriously.

couldn't find a download on another site either, all I can find is some dumb 'informer.com' scam site invading the search results by pretending to have every related file, but they ask you for an email address, only to send you an email telling you that 'muh we dont have the file'.

so, beh.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Tue Oct 01, 2019 12:25 am

Arisotura wrote:it allows both display modes, iirc you can get the native-size mode by pressing SELECT while booting a DS game, otherwise the default mode is fullscreen.
Good to know, reminds me of this wiki sentence "Like DS gamecards, holding down start+select while starting the dsmode dlplay client will disable stretching the screens." Until now I couldn't make much sense of it, because, in my experience, DS-carts don't stretch themselves... but now, I guess DS-carts-in-3DS-consoles might do so.
8bit carts on GBA did also allow stretching, including toggling that feature on/off during gameplay, but that's probably impossible with DS titles on 3DS because it would also require to toggle the touchscreen calibration points during gameplay (or unless the AIC chip could automatically scale the ADC values).
Arisotura wrote:also, speaking of the touchscreen controller thing
that thing is way interesting. I wonder if there's a way to extract the microcontroller firmware or whatever?
Yes, seeing the touch/microphone hardware changing from "A/D converter" (DS) to "fully-fledged sound studio and built-in A/D converter" (DSi) was quite interesting, if not to say scary.
I don't know if there's a firmware in it, or if it's plain logic. The 4Mbit/s SPI write speed suggests that the data goes directly into hardware registers without software processing (or it's stored in a register array, and changes are later processed by software at slower speed). There are some "slow" events (like soft-reset completion for coefficient ram, and programmed-gain reached flags), maybe that parts are handled by software, or they might be done by dma-memfill and hardware counters.
Arisotura wrote:I wondered about the miniDSP thing, but turns out the instruction set isn't public...
Yeah, getting specs or just a sample binary seems to be difficult. And, it isn't yet confirmed if the DSi/3DS is even having any DSP instruction RAM at all. As far as I remember reading that memory just returns zeroes. Though it might be actually zeroflled upon reset... I don't remember if I have ever tried to write to that memory.

Microphone (tested on DSi) (but 3DS should be very similar)
Rev-engineering that kind of hardware isn't so attractive, the incoming data is just random noise/sound, making it impossible to test if the data is correct. The things that can be tested are timings for Status Flags, IRQs, and DMA, which isn't so much fun to do, either. But I think I've now tested and solved almost all relevant stuff... and then... I can finally remove the chapter about the DSi's Unknown ARM7 Registers in gbatek : )

First of, the flowchart for (un-)muting the microphone (assuming that the Launcher had already initialized other TSC registers for things like PLL timings):

Code: Select all

mic_enable:
 TSC[1:2Eh]=03h   ;MICBIAS=AVDD
 TSC[0:51h]=80h   ;ADC Digital Mic, on
 TSC[0:52h]=00h   ;ADC Digital Volume Control Fine Adjust, unmute
 TSC[1:2Fh]=37h   ;MIC PGA=27.5dB (eg. as used by SystemSettings/MicTest)

mic_disable:
 TSC[0:52h]=80h   ;ADC Digital Volume Control Fine Adjust, mute
 TSC[0:51h]=00h   ;ADC Digital Mic, off
 TSC[1:2Eh]=00h   ;MICBIAS=Off
And then, ARM registers are working as...

Code: Select all

4004600h - DSi7 - MIC_CNT - Microphone Control (can be 0000E10Fh)
  0-1   Data Format    (0=TwiceSame, 1=SimilarAsNormal, 2=Normal, 3=None) (R/W)
  2-3   Sampling Rate  (0..3=F/1, F/2, F/3, F/4)                          (R/W)
  4-7   Unused (0)                                                          (-)
  8     FIFO Empty     (0=No, 1=Empty)           ;0 words                   (R)
  9     FIFO Half-Full (0=No, 1=Half-Full)       ;8 or more words           (R)
  10    FIFO Full      (0=No, 1=Full)            ;16 words                  (R)
  11    FIFO Overrun   (0=No, 1=Overrun/Stopped) ;more than 16 words        (R)
  12    Clear FIFO     (0=No change, 1=Clear)    ;works only if bit15 was 0 (W)
  13-14 IRQ Enable     (0=Off, 1=Same as 3, 2=When Full, 3=When Half-Full)(R/W)
  15    Enable         (0=Disable, 1=Enable)                              (R/W)
The Sampling Rate depends on the I2S frequency in SNDEXCNT.Bit13,
  I2S=32.73kHz --> F/1=32.73kHz, F/2=16.36kHz, F/3=10.91kHz, F/4=8.18kHz
  I2S=47.61kHz --> F/1=47.61kHz, F/2=23.81kHz, F/3=15.87kHz, F/4=11.90kHz
The Sampling Rate becomes zero (no data arriving) when SNDEXCNT.Bit15=0, or
when MIC_CNT.bit0-1=3, or when MIC_CNT.bit15=0, or when Overrun has occurred.
The Sample Data tends to be 0000h or FFFFh if the microphone related
TSC-registers aren't unmuted.

4004604h - DSi7 - MIC_DATA - Microphone Data (R)
  0-15  Signed 16bit Data     ;\16 words FIFO, aka 32 halfwords
  16-31 Signed 16bit Data     ;/
MIC_DATA can be read by software, or via NDMA (with startup mode 0Ch and
Blocksize 8 words).
The "TwiceSame" data format converts the incoming mono data to stereo (ie. data bit0-15 and bit16-31 will contain the same value; and, accordingly, the 16-word fifo will get full twice as fast).
The two other data formats are storing separate mono samples in bit0-15 and bit16-31. I don't know yet if the lower/upper halfword contains the first or second sample though, or maybe either one is supported... it could be tested when recording a sine- or sawtooth-wave.
So far, the data seems to be always signed 16bit. But the launcher does also contain some code for handling unsigned data, maybe there is a TSC register that can switch to unsigned mode (and, hmm, TSC[0:1Bh] seems to support non-16bit data, however that would end up on ARM side).

Overrun Caution: If data isn't read fast enough then the Overrun flag will get set, and FIFO updates will be stopped. At that point one can still read the remaining 16 words from the FIFO, but no further words will be added to the FIFO, until clearing the FIFO and Overrun flag via MIC_CNT.bit12 (which requires bit15=0 before setting bit12).

For SNDEXCNT, one new detail is that the Mute flag (whatever that is) it doesn't affect microphone. And, the I2S frequency can be changed only if SNDEXCNT.bit15 is (or was?) 0. The exact two frequencies are supposedly 33.513982MHz divided by either 400h, or 2C0h.
That SNDEXCNT stuff might be different on 3DS... I don't know know if the 3DS has an equivalent to SNDEXCNT at all... maybe one of the "CODEC" registers?

Oh, and, if I remember correctly... I think the microphone could be also routed to the Teaklite processor. That's probably still totally unknown how it works... unless wwylele has already figured out that part?
Last edited by nocash on Sat Oct 12, 2019 2:12 am, edited 2 times in total.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Tue Oct 01, 2019 4:21 pm

And the last three peripherals - those are unfortunately not so easy to figure out, even when having official datasheets...

NFC - Near-Field Communication (New3DS)
Bus/device 1:EEh. The chip used here is apparently a Broadcom BCM20791, there is a datasheet for it, but it's covering only electrical stuff, not the I2C bus protocol. That protocol appears to be a standarized thing called "NFC Controller Interface (NCI)" from the "NFC Forum", which is one those non-profit organizations not shy of charging $600 for a copy of the protocol specifications.
Homebrew specs, or any leaked details form the official specs might help... or, otherwise... there are several open-source implementations for BCM20791, and for NCI in general. But it would require some rev-engineering work to find the relevant source files, and to extract the actual protocol from the source code.

C-Stick and ZL/ZR-buttons (New3DS)
This is probably Bus/device 2:54h. And probably wired to the huge 44pin chip on the button-board. Trying to write index + read data from that device does return mostly FFh bytes, with some random bytes here and there (regardless of the written index byte), perhaps a few more random bytes when pressing the ZL/ZR-buttons (but I am not really sure on that).
If the chip is really just there for the stick+buttons then the protocol is probably very simple, but one would need to look at the official firmware driver's code to figure out how it works.
3dbrew is associating device 2:54h with some kind of IR:rst service, but I guess that's just a backwards-compatibility thing (the Old3DS did have a similar add-on (called Circle Pad Pro) attached to the IR port).

Infra-Red IrDA/SIR
Bus/device 2:9Ah, does use a SC16IS750 chip, containing UART and IrDA/SIR hardware. The datasheet does almost exclusively describe the UART part, and barely mentions IR at all. I guess the IR mode does basically redirect the UART RX/TX signals to the IR receiver/transmitter, presumably with "pulsed" signals instead of constant HIGH or LOW levels. In so far it would be simple to use (except, maybe needing additional error handling, and possibly needing software handshakes if RTC/CTS are left unimplemented in IR mode).
The more complicated part is that the official IrDA implemention does supposedly consist of a more complex protocol (reportedly available for $100 upwards, but, as for NFC, one can probably find open source code for free). I don't know if Nintendo had bothered to use the official IrDA protocol though, also possible that they have just used a custom protocol for their add-ons.
The overall purpose on Old3DS is using the IrDA hardware to access the external NFC reader and Circle Pad Pro add-ons. The New3DS does have that add-ons built-in, so the IrDA chip is becoming rather useless on New3DS... unless it's still used for other things?
IrDA as such appears to be limited to short-range transfers of 20cm - 100cm range, and to some sort of binary data... so it's probably not suitable for implementing things like classic TV remote controls.
Last edited by nocash on Fri Oct 18, 2019 2:44 am, edited 3 times in total.

assemblyx69
Posts: 1
Joined: Wed Oct 02, 2019 12:50 am

Re: 3DS reverse engineering

Post by assemblyx69 » Wed Oct 02, 2019 5:08 am

NCI Technical Specification
Attachments
NFC Controller Interface (NCI) Technical Specification.pdf
(1.08 MiB) Downloaded 99 times

Post Reply