Didj Hacking

390MHz ARM9 with OpenGL Accelerator for less than 30€

Warning! This is a work in progress. You will likely destroy your Didj.  I'm not responsible for any damages, claims or injuries that may result from this write up and files. If you don't know what you are doing just leave the Didj as it is.

Update 12.02.2010 :

Some notes about the availability of the cartridges.

Update 24.05.2009 :

Finished my custom cartridge layout and successfully compiled a uClibc/GCC 4.1 compiler for  cross-compiling  linux apps for the Didj

Udpate 31.05.2009 :

Added preliminary x-modem upload support in lightning-boot. Stitch together a lightning-boot Winarm package for easy cross-compiling on windows machines

Udpate 2.06.2009 

Found the xmodem EOT bug. Identified more pins on the cartridge connector. Added u-boot download mode in lighning boot. Build u-boot for the Didj and build a Linux Kernel out of the Leapfrog tarball which surprisingly works :-)

Udpate 7.06.2009 

Build a DIDJ to xD Card Adapter. Linux reads the correct Flash ID from the xD Card.

Update 29.6.2009

Dumped the xD Card thing, got the SD-Card controller partially working in u-boot. Lightning-boot loads u-boot from the internal NAND Flash. 

Update 25.9.2009

Ordered 10 Didj cartridge PCBs. Set up a project on Berlios

Update 1.10.2009

New Cartridge Pinout.

Update 11.10.2009

The PCBs arrived yesterday. Prototype is working :-)

Update 26.12.2009

Finished the cartridges.

A couple of months ago I found this blog . Too sad the Didj isn't avaiable in Europe yet , but my mother was on holiday in the states. So she bought me two of these ( Thanks :-) )

I was impressed about the size of the Didj , really big for a children's toy. The screen is also big compared to other toys (OnStation,those 20€ Sega Handhelds,..).

Here a couple of pictures showing the front and back ... 

The Didj runs on 4 AA cells or with an external 9V DC adapter. It has a build in speaker and a headphone connector. On the top side there is a USB device connector and the cartridge slot. It has 32MB of DDR RAM and 256MB of NAND Flash. On the NAND there are 7 partitions (Lightning Boot,Atomic Bootflags,Kernel,Rootfs,RFS Kernel?,RFS Rootfs?,Brio and EXT)

So let's start ...

Thanks to elinux.org that the pins for the console are known. I soldered a 3.3V RS232 level shifter on these pins. Poking around in the filesystem I found some interesting test tools in the /usr/bin directory.

  •  lftest_lcd     -  puts some color patterns on the screen and shows a picture of a guy
  •  lftest_oss   -  plays a audio file ( some part of classic tune or whatever)
  •  lftest_rtc      - counts some seconds on the rtc device
  •  lftest_usb   - does some stuff with the USB device , didn't figured out yet what it does
Those tests are basically shell scripts which call user space applications. For example with "usbctl" , called by lftest_usb, you can  configure the USB device to export some of the Didj's NAND partitions as USB Mass Storage , so you can back up files from the Didj on your PC :-)

Time to do some serious hacking! 

Leapfrog published the source code of the linux kernel , uboot (which isn't used in the release version of the Didj) and a custom bootloader called "lightning-boot".

Theoretically it would be possible to build a own kernel from the published source code and use the usbctl application to transfer it to the Didj overwriting the original kernel in the NAND , but what if the build fails (what is likely !) and the Didj won't start anymore? No more usbctl to access the NAND ->  Brick

 I figured  two ways out to boot the Didj from external sources. 

The processor  (Magic Eyes Pollux , or some kind of custom derivate for Leapfrog called LF1000) has the ability to boot over the UART. An other nice feature is the possibility to swap the NAND chip select lines with those on the cartridge connector. 

This features are controlled by pull up / down resistors on the cartridge slot . For example if you want to use the UART boot feature you have to pull D5 and D6 down (I used some 470 Ohm resistors). The next time you power up the Didj it seems as it won't start , but the processor is full functional an waits for some input on the UART.

The pinout of the cartridge slot ( no guarantee !)

I hooked some resistor and a dip-switch on some pins to probe the different modes ...

Some pictures of the mainboard

Back to the UART boot feature, the UART boot statemachine runs on 19200 baud and awaits a file of 16kbyte (0x4000) size.  On the first try i used a dumped bootloader from the NAND. Trimmed it to 16kbyte (the dump contained only 8k of real data , the rest was 0xff) and transferred it to UART with 19200 baud. As soon the 16kbyte were transferred the Didj booted as normal :-)

The next step was to build an own bootloader. I used scratchbox as development environment , just setup a ARM GCC 4.1 compiler with uclibc and was ready to go. The supplied source code has a nice build script , I only had to set some CFLAGS , CC and environment variables to build the bootloader (README file inside the source directory)

The resulting binary was around 8kbyte large , I filled the file with 0xff's until it grow to 16kbyte and transferred it to the Didj.

Woot! My own build bootloader boots!!! 

But a minor bug is there , I had to hold the power button slider. It seems my bootloader doesn't initialize some GPIOs the right way.

If you want to try it by yourself  (please read the warnings on top of the page!) ,
here is my bootloader  lightning-boot-wo-nand-bootstrap.bin 

You have to install the pull down resistors mentioned above. Afterwards, if you remove these pull down resistors, the Didj starts normal from NAND.

In the next days I'm trying to build my own NAND cartridge , at the moment I'm waiting for my Digikey order containing some NANDs and a STM32. My plan is to use the STM32 as a USB to NAND interface , so I can easily put files on my custom cartridge.  

Update 24.5.09
I finished layout my custom cartridge . In case anybody dares to build his own , here are the (untested!) design files in Altium Designer 6 format : didjcart24.05.200918-46-56.zip

When assembled the cartridge should look like this :

On the cartridge there is the same type of NAND as soldered inside the DIDJ (MT29F2G08AADWP , 256MB). This NAND chip is connected on the DIDJs expansion connector and to a STM32 (STM32F103VET6 , 512K Flash) on the cartridge.  The purpose of the STM32 is to boot the DIDJ with my custom bootloader which the STM32 transfers to the DIDJ on powerup over the UART. The second purpose of the STM32 is a USB interface to the NAND chip  (raw , no fs!) on the cartridge. And at last the STM32 converts the DIDJs UART to a USB CDC class. 

Further I rebuild the cross-compiler. On the first try I build a OABI compiler but the DIDJs rootfs/kernel was build with EABI.
If anybody want's to build a toolchain suitable for the DIDJ , here are my crosstool-ng 1.2.5 and uClibc config files :

I did some experiments with the mplayer patch , supplied in the Leapfrog tarball, but didn't succeed. I got sound but the 
vo_brio and vo_brioyuv plugins won't work as expected.  After fixing some paths in the vo_brio source files I got some garbage on the LCD. 
Maybe Leapfrog changed the mlc driver in the release version ? So it's time to get my own kernel running on the DIDJ. 

Update 31.5.09
Add preliminary x-modem support in lightning-boot. At the moment it is possible to transfer a 320x240 24bit raw image to 
the Didj's bootloader. The image is displayed on the TFT. There is a bug in the x-modem code, EOT doesn't work.
In the next days I will add a x-modem kernel/u-boot load feature ( if I can fix the EOT bug...)
Here is the lightning-boot source (ready for cross-compiling with winarm) : lightning-boot_winarm.zip
Please don't blame me for my spaghetti code , the soldering iron is my weapon of choice :-)

Update 02.06.09
Pheeew !  10 hours Didj hacking marathon this day :-)  But it was worth the time :

* lightning-boot 1.0                           *
* Modified with xmodem download support        *
* 31.05.09 Claude Schwarz                      *
xmodem download mode
Switching to 115200 Baud
press any button to start download
Loaded : 0x00023600 bytes
Starting image at 0x01000000

U-Boot 1.1.6 (Jun  2 2009 - 09:33:04)

DRAM:   0 kB
Flash:  0 kB
NAND:  mfgid=2c devid=da
256 MiB
Using default environment

In:    serial
Out:   serial
Err:   serial
LF1000 #
LF1000 # setenv bootargs mem=18M init=/sbin/init console=ttyS0,115200 root=31:06
ro rootflags=noatime rootfstype=jffs2 ubi.mtd=Brio ubi.mtd=prg_Brio ubi.mtd=Cart
ridge ubi.mtd=EXT
LF1000 # setenv loadaddr 1800000
LF1000 # loadb
## Ready for binary (kermit) download to 0x01800000 at 115200 bps...
## Total Size      = 0x001250a0 = 1200288 Bytes
## Start Addr      = 0x01800000
LF1000 # go 1800000
## Starting application at 0x01800000 ...
Uncompressing Linux.............................................................
............... done, booting the kernel.
Linux version (debian@debian) (gcc version 4.1.2) #7 Tue Jun 2
 13:42:39 EDT 2009
CPU: ARM926EJ-S-LF1000 [41069265] revision 5 (ARMv5TEJ), cr=0005317f
Machine: ARM-LF1000
Warning: bad configuration page, trying to continue
Memory policy: ECC disabled, Data cache writeback
PLL0=393.218109 MHz   PLL1=147.000 MHz   CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists.  Total pages: 4572
Kernel command line: mem=18M init=/sbin/init console=ttyS0,115200 root=31:06 ro
rootflags=noatime rootfstype=jffs2 ubi.mtd=Brio ubi.mtd=prg_Brio ubi.mtd=Cartrid
ge ubi.mtd=EXT ubi.mtd=prg_EXT
PID hash table entries: 128 (order: 7, 512 bytes)
TIM0=  4.593 MHz   TIM1=  4.593 MHz   TIM2=  4.593 MHz   TIM3=  4.593 MHz   TIM4
=  4.593 MHz
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 18MB = 18MB total
Memory: 15796KB available (2128K code, 178K data, 96K init)
Calibrating delay loop (skipped)... 786.43 BogoMIPS preset
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 1024 bind 512)
TCP reno registered
JFFS2 version 2.2. (NAND) (SUMMARY)  (C) 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler deadline registered (default)
Software Watchdog Timer: 0.07 initialized. soft_noboot=0 soft_margin=60 sec (now
ayout= 0)
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
serial8250: ttyS0 at MMIO 0x0 (irq = 10) is a 8250
serial8250: ttyS1 at MMIO 0x0 (irq = 34) is a 8250
serial8250: ttyS2 at MMIO 0x0 (irq = 35) is a 8250
serial8250: ttyS3 at MMIO 0x0 (irq = 36) is a 8250
RAMDISK driver initialized: 1 RAM disks of 128K size 512 blocksize
input: LF1000 Keyboard as /class/input/input0
lf1000-rtc lf1000-rtc: rtc core: registered lf1000-rtc as rtc0
LF1000 Real Time Clock driver.
lf1000-sdio driver
audio: expected rate 32000Hz, actual: 32000Hz
lf1000-dpc driver
dpc: PWM clock rate is 9800000
input: LF1000 USB as /class/input/input1
NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c $Revision: 1.41 $
NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (ST Micro NAND 256MiB 3,3V 8-b
Scanning device for bad blocks
Bad eraseblock 1297 at 0x0a220000
lf1000-mtd: cartridge not inserted
Creating 9 MTD partitions on "lf1000-base":
0x00000000-0x00020000 : "LF1000_uniboot"
0x00020000-0x00100000 : "Atomic_Boot_Flags"
0x00100000-0x00200000 : "Manufacturing_Data"
0x00200000-0x00400000 : "Kernel0"
0x00400000-0x01200000 : "Linux_RFS0"
0x01200000-0x01400000 : "Kernel1"
0x01400000-0x02200000 : "Linux_RFS1"
0x02200000-0x10000000 : "Brio"
0x10000000-0x10000000 : "EXT"
mtd: partition "EXT" is out of reach -- disabled
UBI: attached mtd7 to ubi1
UBI: MTD device name:            "Brio"
UBI: MTD device size:            222 MiB
UBI: physical eraseblock size:   131072 bytes (128 KiB)
UBI: logical eraseblock size:    129024 bytes
UBI: number of good PEBs:        1775
UBI: number of bad PEBs:         1
UBI: smallest flash I/O unit:    2048
UBI: VID header offset:          512 (aligned 512)
UBI: data offset:                2048
UBI: max. allowed volumes:       128
UBI: wear-leveling threshold:    4096
UBI: number of internal volumes: 1
UBI: number of user volumes:     1
UBI: available PEBs:             0
UBI: total number of reserved PEBs: 1775
UBI: number of PEBs reserved for bad PEB handling: 17
UBI: max/mean erase counter: 7/3
UBI error: attach_mtd_dev: incorrect MTD device: "prg_Brio"
UBI error: ubi_init: Failed to find MTD device prg_Brio.  Skipping.
UBI error: attach_mtd_dev: incorrect MTD device: "Cartridge"
UBI error: ubi_init: Failed to find MTD device Cartridge.  Skipping.
UBI: empty MTD device detected
UBI: create volume table (copy #1)
UBI error: ubi_scan_get_free_peb: no eraseblocks found
UBI error: ubi_init: Failed to find MTD device EXT.  Skipping.
UBI error: attach_mtd_dev: incorrect MTD device: "prg_EXT"
UBI error: ubi_init: Failed to find MTD device prg_EXT.  Skipping.
input: Power Button as /class/input/input2
UBI: background thread "ubi_bgt0d" started, PID 18
TCP cubic registered
NET: Registered protocol family 1
lf1000-rtc lf1000-rtc: setting the system clock to 2026-11-23 21:31:54 (17954695
VFS: Mounted root (jffs2 filesystem) readonly.
Freeing init memory: 96K
init started: BusyBox v1.5.0 (2009-02-03 17:58:58 PST) multi-call binary
starting pid 22, tty '': '/etc/init.d/rcS'
Initializing System
Mounting Atomic Boot Flags partition
Mounting Manufacturing Data partition
Configuring Brio
Serial Number: 00000
modprobe: cannot parse modules.dep
Starting simple example script.
Starting Application and Power Monitor daemon.
starting pid 172, tty '': '/bin/sh'
# fw= bl= pkg=0
[0] CAppManager::CAppManager; LightningBase/Src/AppManager.cpp; 105; MemFree:
[0] Shutdown Timer set for 10000 [ms] timeout
[0] USB Device Watchdog set for 10 [sec] timeout
[0] DidjSerialNumber is : 00000
monitord: app set power timer to 10
[0] PushApp Start: BLT/BLT.so; LightningBase/Src/AppManager.cpp; 382; MemFree:
monitord: app set usb timer to 10
[0] CSequencer::init() Sequencer thread created
[0] PushApp Done: BLT/BLT.so; LightningBase/Src/AppManager.cpp; 384; MemFree:

!ASSERT: [5] DisplayModule::InitModule: /dev/ga3d driver failed

PowerDown/Assert exit!

Main App Result: 139
WARNING: *** abnormal AppManager exit 139 ***
starting pid 354, tty '': '/etc/init.d/shutdown'
Shutting down system
Stopping simple example script.
killall: AppManager: no process killed
stopped launch_main (pid 169)
Sample Rate: 32000
Changed rate to 32000

Channels: 2
Changed channels to 2

Bits per sample: 16
Changed format to AFMT_S16_LE

Ignoring unsupported chunk 0x6c706d73
Bytes of data: 342248
Stopping Application and Power Monitor daemon
monitord: exiting...
modprobe: cannot parse modules.dep
Unmounting /Didj
Unmounting Manufacturing Data partition
Unmounting Atomic Boot Flags partition
The system is going down NOW!
Sending SIGTERM to all processes
Sending SIPower down.
Reboot failed -- System halted

The hardest part was fixing u-boot to compile with any of my toolchains. At last I got it working with my crosstool-ng EABI toolchain (with a lot of hackery...). 

If you want to try it by yourself 
  • Lightning-boot with xmodem support : lightning-boot.bin
  • U-boot (build from the Leapfrog tarball) : u-boot.bin
  • Linux Kernel zImage (also build from the Leapfrog Tarball) : zImage2
Sourcecode will follow shortly !

Short howto :
Bring Didj in UART boot mode (mentioned above)
Transfer lightning-boot.bin to the DIDJ (19200 baud , as binary) while holding any of the buttons. As soon as lightning-boot starts release the button and switch the terminal program to 115200 baud. Start xmodem transfer of u-boot.bin in terminal program and press any button on the DIDJ to start.
U-boot should start now , set the environment variables (as in the bootlog above) and transmit the kernel zImage with kermit. Type in "go 1800000" and watch the Brio application crashing at the end of booting :-)

Now I'm confident in going further with the DIDJ. So confident that I'm willing to spend some money on PCBs for my custom NAND cartridge and some DDR chips :-) 

Ohhh and I think I have found some testpoints for the USB Host and TV-Out ,wich the LF1000/Pollux has build in.

Update 07.06.09
I have build a xD Adapter which plugs in the DIDJ Cartridge slot , i got the idea for this from DJWillis's Blog http://blogs.distant-earth.com/wp/?p=64 . Btw , Thanks for the Support !! :-) 

Linux recognizes my xD Card (Read the manufacture ID) but I can't get linux-mtd use it.

lf1000-nand: cartridge ECC mode: <6>software
NAND device: Manufacturer ID: 0x98, Chip ID: 0xd5
NAND device: Manufacturer ID: 0x98, Chip ID: 0xd5 (Toshiba NAND 4MiB 3,3V 8-bit)
Scanning device for bad blocks

 My xD card is a 2 GByte type which uses MLC NAND Flash and I can't get an datasheet for any type of MLC NAND -> so no Linux driver for it :-( .
So I ordered some 512MB xD Cards (or non "Type M" Cards) , they are based on SLC NAND  and should work like any other NAND Chip.
Here are some pictures of the Adapter :

and plugged in the DIDJ

Update 29.06.09

Long time no updates, but I wasn't lazy :-) I was busy getting the SD-Card controller working. At the first try I added SD-Card support in lightning-boot. But this was a mess an never worked really , since I have no real information how the SD controller works it was mostly guesswork. After some days I found a u-boot tarball for the GPH WIZ , the GPH WIZ uses the same CPU as the DIDJ and has SD-Card support in u-boot! I just picked the needed files out of the tarball and patched the leapfrog u-boot. After some attempts i got this in u-boot :

LF1000 # mmcinit

SD ver 2.0

SD found : Size = 3930624 KBytes

Yeah right , 4GB SDHC on the DIDJ :-) Plenty of space for homebrew

Since it is really difficult to get those non - "Type M" xD-Cards these days , I dumped the xD-Card cartridge idea and go for a simple SD-Card cartridge without any controller or other fancy stuff on it (  except for a FTDI USB/RS232 converter for console access) .

Further , as mentioned above, I did some stuff with lightning-boot. Lightning-boot now has LCD Text output and some simple drawing functions ( setpixel , clear screen). Lightning-boot loads u-boot from the internal NAND flash, I added u-boot to the kernel partition ( which has a obscure "filesystem" , called TFS but luckily in the leapfrog tarball there is a python script to generate a flashable TFS image).

On my to-do list are now this things :

  • Add SD-Card support to the Kernel
  • Clean up the Sources of lightning-boot and u-boot
  • Design and build a SD-Card cartridge
  • Put all together in a Buildroot or Openembedded package
  • Write a howto for getting u-boot and lightning-boot on a new Didj without loosing the original functionality of the Didj
After this steps everybody should easily can start homebrew on the Didj , only 3 things are needed : The SD-Card cartdridge, USB Cable and a computer with a recent Linux installed.

Maybe , if there there is demand , I will produce a small batch of these SD-Card cartridges and will sell them for small money (~15€  / ~20$ + shipping )

Just drop me a email if you need a cartdridge.

 Update 25.09.09

 I ordered 10 Didj cartridge PCBs. The PCBs will arrive on October the 8th. As soon I populated,soldered and tested the cartridges I will ship them.

One cartridge will cost 15€ , please be aware that I don't earn a single cent from this. Alone the manufactured PCB without components costs ~9€

The shipping costs are : US ~6€ , Europe ~ 3€

Only 2 cartridges left. 

The cartridges will have an FTDI FT232RL for console access and an SD Card socket. Further ther is an unpopulated Footprint for a NAND Flash.

Here are the schematics and a rendering of the cartridge 


I will release the Altium Designer project , Gerber files and BOM as soon the first batch of PCBs is populated and I'm sure that there are no errors in the layout.

Also I have set up a project on Berlios, named


There you will find a git repository filled with the Leapfrog tarball and an (empty) Wiki...

Feel free to join :-) Any kind of help is welcome !

In the future I will shift this page to the Berlios Opendidj Wiki.

Update 1.10.09

New Cartridge Pinout.  Still waiting for my PCBs to arrive ....

Update 11.10.09

The Cartridge PCBs arrived yesterday. I build one prototype and it works!


 The bare PCB 

And the backside of the PCB


Don't worry the Cartridges I will ship look far better. They will be soldered in a reflow oven.

Next week I will have next to no spare time, so I will populate and solder the cartridges next weekend. 

Update 26.12.09

Finally finished the cartridges , sorry to everyone who orderd for the delay!

I had an really busy time the last months

Waiting for the glue to dry :-)  I will write an email to everyone who orderd a cartridge 

All cartridges are sold ! 

By request the Gerber files for the Cartridge : DidjCartV1.zip

Update 12.02.10

I get many request if I ever build a second batch of the Cartridges.
At the moment I'm not planing doing so. I will try to find a manufacturer who
build the Cartridges for me.

But the Cartridges definitely get more expensive If i build them by myself.
I will let you know when I get an offer from the manufacturer.