Skip to content

Instantly share code, notes, and snippets.

@RandomInsano
Last active October 17, 2023 19:22
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RandomInsano/083283904f162137de95 to your computer and use it in GitHub Desktop.
Save RandomInsano/083283904f162137de95 to your computer and use it in GitHub Desktop.
Edwin's notes from hacking a Playskool Alphie Robot

Alphie (2009) Hacking Notes

Note: I no longer have cards and didn't scan them. You're best bet is eBay, though it's quite expensive.

I want to make my own booster packs for Alphie, a children's learning toy, so I'm learning how he works internally so I can see if it's possible. It may be helpful for someone else down the line, but for right now it's just a lot of fun. Even if I don't get there, it's great practice of both documentation (which I'm terrible at writing) and reverse engineering.

I2C Pinout

If you're trying to tap into the EEPROM, don't use J3. It's got silk screened labels for I2C to trick you, but there's nothing on that bus. Don't be wasting your time like I did! Instead, use J2 since it's what goes to the card reader, and the pads are big enough to solder some wires to.

J2 Pinout:

  1. VCC (marked with red)
  2. SCL
  3. SDA
  4. Card detect
  5. Gnd

Configuration EEPROM

The chip is an S24C02C and is id A0 on the bus. It stores up to 256 bytes and has a simple i2c protocol for reading and writing. Here's the protocol dump I've gotten from i2c on startup:

[0xA0+0x28+]
[0xA1+0x18+0xE7-]
[0xA0+0x20+]
[0xA1+0x00-]
[0xA0+0x00+]
[0xA1+0x44+0x42+0x37+0x3C+0x34+0x3E+0x3B+0x32-]
[0xA1+0x41+0x3C+0x44+0x3A+0x3E+0x3B+0x39+0x3B-]
[0xA1+0x3C+0x3B+0x45+0x41+0x86+0x81+0x83+0x82-]
[0xA1+0x81+0x82+0x82+0x82+0x87+0x85+0xDC+0xB6-]
[0xA0+0x50+]
[0xA1+0xFF+0xFF-]

Nearly everything read within the large block is written to the card reader on boot. There's an additional 0xDCB6 at the end that isn't, but I think that's likely a checksum (non-CRC16, I checked and seems to compute to zero when all values are zero). This definitely is calibration data written during production. When using calibration data from a different Alphie, the card reader is unable to decode any cards that are inserted.

I've dumped a second Alphie's startup code, and while this configuration payload is different, everything surrounding it is identical. Here's the dump:

[0xA1+0x2C+0x3F+0x3C+0x34+0x2C+0x36+0x32+0x35-]
[0xA1+0x30+0x2F+0x2D+0x43+0x38+0x36+0x37+0x30-]
[0xA1+0x3B+0x3F+0x36+0x36+0x7B+0x86+0x80+0x7F-]
[0xA1+0x80+0x7C+0x82+0x84+0x7F+0x7F+0x2E+0x96-]

The second Alphie re-writes its EEPROM on every startup. I'm not sure if that is by design in a later firmware, or if the checksum is off somehow and so it gets restored from backup (see below). The card reader certainly seems happy with it.

For language and card purposes, Alphies are region locked to the country they're sold in. I'm assuming you can only use Canadian cards in a Canadian Alphie. It would be good to get a dump from an American or Mexican Alphie to see which byte sets its region. The only other data is read out from EEPROM are two bytes at 0x28 which is 0x18E7. I assumed that had to be it, but changing the values didn't stop Alphie from being able to use one of my booster packs.

When the CPU goes into sleep mode, it keeps power to the EEPROM but silences the bus. This means that we can talk to the EEPROM without the main CPU fighting to talk to the card reader and EEPROM. With that, I was able to take memory dumps by using the sequential read as described in the datasheet (P19 of S-24C01C/02C Rev. 3 by Seiko Instruments Inc.). Here's the memory for Alphie #1:

44 42 37 3C 34 3E 3B 32 
41 3C 44 3A 3E 3B 39 3B 
FF FF FF FF FF FF 83 82 
81 82 82 82 87 85 DC FF 
00 FF FF FF FF FF FF FF 
18 E7 FF FF FF FF FF FF 
A5 BB 33 73 10 96 72 41 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
44 42 37 3C 34 3E 3B 32 
41 3C 44 3A 3E 3B 39 3B 
3C 3B 45 41 86 81 83 82 
81 82 82 82 87 85 DC B6 
FF FF FF FF FF FF FF FF 

Alphie #2:

2C 3F 3C 34 2C 36 32 35 
30 2F 2D 43 38 36 37 30 
3B 3F 36 36 7B 86 80 7F 
80 7C 82 84 7F 7F 2E 96 
00 FF FF FF FF FF FF FF 
18 E7 FF FF FF FF FF FF 
A5 BB 33 73 10 96 72 41 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
2C 3F 3C 34 2C 36 32 35 
30 2F 2D 43 38 36 37 30 
3B 3F 36 36 7B 86 80 7F 
80 7C 82 84 7F 7F 2E 96 
FF FF FF FF FF FF FF FF 

Alphie #3:

2F 3B 38 37 2D 32 3A 32 
3F 34 4D 48 47 48 4D 4B 
48 4B 4F 4C 8B 88 88 88 
8B 8A 88 8A 8C 8A 61 84 
00 FF FF FF FF FF FF FF 
18 E7 FF FF FF FF FF FF 
A5 BB 33 73 10 96 72 41 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
2F 3B 38 37 2D 32 3A 32 
3F 34 4D 48 47 48 4D 4B 
48 4B 4F 4C 8B 88 88 88 
8B 8A 88 8A 8C 8A 61 84 
FF FF FF FF FF FF FF FF 

Also, Alphie #4 (yes, I have an Alphie problem):

30 34 2C 32 29 37 3D 2C 
30 2A 46 46 44 40 49 45 
4A 50 49 46 87 87 86 84 
89 87 89 8C 89 87 F9 52 
00 FF FF FF FF FF FF FF 
18 E7 FF FF FF FF FF FF 
A5 BB 33 73 10 96 72 41 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
FF FF FF FF FF FF FF FF 
30 34 2C 32 29 37 3D 2C 
30 2A 46 46 44 40 49 45 
4A 50 49 46 87 87 86 84 
89 87 89 8C 89 87 F9 52 
FF FF FF FF FF FF FF FF 

Alphie #5 (Une Alphie Francophone!):

33 3C 32 33 29 35 39 30
2E 2A 33 2D 36 39 37 37
39 38 38 32 7E 7B 7F 81
80 80 81 80 80 7D 02 47
00 FF FF FF FF FF FF FF
17 E8 FF FF FF FF FF FF
A5 BB 33 73 10 96 72 41
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF
33 3C 32 33 29 35 39 30
2E 2A 33 2D 36 39 37 37
39 38 38 32 7E 7B 7F 81
80 80 81 80 80 7D 02 47

EEPROM Recovery Mode

If the calibration data doesn't pass its checksum, Alphie will try to re-read the data five times. If after those five reads it fails to load correct data, it uses a backup found near the end of the EEPROM and overwrites the invalid data with the backup before continuing with startup.

On my first attempt, I only overwrote the first 24 bytes instead of all 32 (typo, honest). That managed to recover correctly as described. After resetting all 32 bytes to 0x00, Alphie gets stuck in a loop as the checksum is passing but the card reader isn't responding. When the card reader doesn't respond, Alphie hard resets. To fix it, I just threw some changes wherever in the block of data and that caused the invalid checksum to trip the repair. I tried a few different places and all worked to trigger recovery.

Format of card reader protocol

Alphie's card reader shares the i2c bus with the EEPROM and it seems to have an id of 0x22 there. Pin 4 of the card reader is a mystery as it will reset the card reader when driven low, but might also pull low on a new card insertion. The CPU polls the reader ever 200ms to check the card, so I'm not sure if that output is actually used. I don't remember seeing any action when the card was removed.

Something to note here is that the i2c bus is running at a very low, non-standard clock rate of 1024 KHz, and it's fairly unhappy with anything above that. To interface with the card reader I needed to find, then slow down, a software implementation of i2c for the Arduino. I'm not quite at the point where I can read data successfully from the card reader, but I'm close.

Below is the two-way communication taken from a Bus Pirate. Some bytes are read while others are written during the same request. Each line here is a full i2c message with '[' showing the start part of the message and ']' showing the stop. Here's the dump:

Startup:

[0x23+0xE0+0x4A-]   (Write E0, Alwats reads as 4A)

Loading calibration data:

[0x22+0xA0+0x44+0x42+0x37+0x3C+0x34+0x3E+0x3B+0x32+0x41+0x3C+]
[0x22+0xA1+0x44+0x3A+0x3E+0x3B+0x39+0x3B+0x3C+0x3B+0x45+0x41+]
[0x22+0xA2+0x86+0x81+0x83+0x82+0x81+0x82+0x82+0x82+0x87+0x85+]
[0x23+0xF1+0x??+0x00-]  (Read all three(?))

Polling loop: 
Card data read happens ~18 times in a row:

[0x22+0x30+]        (Write 0x30)
[0x23+0x20+0x1C+0x00-]  (Write 0x20, Read both bytes)

Followed by this one (maybe calibration?):

[0x22+0xF0+]
[0x23+0xF1+0x??+0x00-]

When Alphie goes to sleep:

[0x22+0x90+]

Above, the "??" byte was 0xDC on one model and 0xF9 on another, and 0x61 on a third. These seem to correspond to the first byte of the checksum, but I'll have to confirm once I'm hooked up to one again. 

For reading cards, there’s a write command of 0x30, then a three byte read. The data given back from the read seems to have a fixed one byte header, then a big endian encoding of the card index. The output for a card with a printed index of "0028 A" is shown above, and the traffic shows "1C00". Another example from the reverse of the card, "0171 A" is read by the card reader as "AB00" example comms for that:

[0x22+0x30+]
[0x23+0x20+0xAB+0x00-]

Here's what things look like when no card is inserted:

[0x22+0x30+]
[0x23+0x20+0xFA+0xFF-]

And with an invalid card (bad checksum):

[0x22+0x30+]
[0x23+0x20+0xFF+0xFF-]

Also on card insertion, there are three reads in a row without the CPU issuing [0x22+0x30+] between them.

Card ID print encoding

The bottom of each activity card has a three shade 10 block barcode-like strip on the bottom with the blocks being either white, black or grey. That code identifies a numeric index a which is printed on the card (example: "0001 A"). Alphie's card reader scans the strip with a series of LEDs that work as both the light source and sensor. There's a visual example of the cards here

The bar code blocks are three different shades and the encoding is three's compliment. White being 0, grey being 1 and black being 2. They read from left to right, with the last block always being a value of 1. Along with that, the two centre blocks denote a single bit checksum that is written as either '20' or '02'. This leaves seven blocks for the card index, so there is a maximum of 2187 (3 ^ 7) possible card ids.

From Jay's figuring, this guess is that the checksum shows whether the count of zeros in the id is even or odd where '20' is even and '02' is odd. This seems to hold true for our sample set.

Here's a quick table of the sample cards I have on hand:

0001    0000|02|0011
0002    0000|02|0021
0003    0000|02|0101
0004    0000|20|0111
0005    0000|20|0121
0006    0000|02|0201
0007    0000|20|0211
0008    0000|20|0221
0009    0000|02|1001
0010    0000|20|1011
0011    0000|20|1021
0012    0000|20|1101
0013    0000|02|1111
0014    0000|02|1121
0015    0000|20|1201
0050    0001|20|2121
0171    0020|20|1001
0444    0121|02|1101
0717    0222|02|1201
0748    1000|02|2011
1021    1101|20|2111
1294    1202|20|2211
1541    2010|02|0021
1814    2111|20|0121
2087    2212|20|0221

Using the calculator here or the Python script below, you can generate the numeric encoding of a new card. As an example, a card with id "0136 A" would looks like this:

0136    0012|??|0011 (12001 is the three's compilement)

Here's a quick Python script for calculating the barcode printing:

#!/usr/bin/env python3

def compute(id):
    checksum = True
    output = ""

    for a in range(0, 7):
        mod = id % 3
        id = int(id / 3)    

        output = str(mod) + output

        if mod == 0:
            checksum ^= True    

    checksum_text = ('02' if checksum else '20')

    return output[:4] + checksum_text + output[4:] + "1"

def friendly(id, text):
    ''' Make it look like my table '''
    output  = '{0:04d}'.format(id) + '\t'
    output += text[:4] + "|" + text[4:6] + "|" + text[6:]
    return output

id = 444
print(friendly(id, compute(id)))

Just for fun, I made an SVG image which includes JavaScript to compute the barcodes for you. Just change the number after the hash in the URL to get a new card. This should not be used to pirate existing cards, but instead allow you to make your own custom cards once the card reader can be used everywhere.

Booster Pack IDs

Alphie comes with a base set of activity cards, but can be extended with booster packs of cards which come with an activity cartidge. The cards and cartidge are a matched pair, and amazingly they're region locked. It seems as though they may work with bilingual Alphies though as every Canadian booster back comes with both French and English on the box.

Here's the list of card IDs and color codes for each pack:

Pack Cards Colour
Base: 1 - 51, 171, 240, 444, 717, 748, 1294, 1541, 1814, 1946, 2087 Red
Letters: 52 - 101 Blue
Numbers: 102 - 151 Orange
Music and Sounds: 152 - 170, 172 - 202 Purple
Animals: 203 - 239, 241 - 252 Green
Food: Unknown Blueish

Button / LED Array:

This is about as simple as it can get. The LED and button board has a 12 pin connector with two sets of multiplexed pins. The buttons are multiplexed over the first six pins (two columns, four rows), and the LEDs over the remaining six. The columns aren't shared between them, and for the LEDs, the columns need to be driven high and the rows driven low. I see no electrical reason why you couldn't tie the columns of the LEDs together with the buttons, so I'm guessing they may have done it to save clock cycles. Dividing them would allow testing the buttons at a slower rate than the PWM on the LEDs.

Here's the pinout for the buttons (red wire being pin 1):

  1. Right column
  2. Left column
  3. Row 1
  4. Row 2
  5. Row 3
  6. Row 4

And the LEDs:

  1. Row 2 (Gnd)
  2. Row 3 (Gnd)
  3. Row 4 (Gnd)
  4. Row 1 (Gnd)
  5. Right column (Vcc)
  6. Left column (Vcc)

The LEDs are happy to run from six volts since the board has its own resistors. I wasn't able to measure the current they require unfortunately. :(

Card Reader Physical Fanciness

So, it turns out LEDs can be used to detect light in the same wavelength that they emit, which I didn't know until found an article today for Make Magaine written by Forrest Mims III (fantastic hobbiest author). Alphie uses that property to scan for cards and read them.

The arrangment of these surface mount LEDs is ten groups of two. The groups shine together, probably for redundancy or accuracy. The two LED groups for the checksum blocks in the barcode strip are mounted higher than the rest, probably so they can see the card being inserted before it's all the way in.

When there's no card in Alphie, the card reader only scans the two center blocks. I'm guessing to lower the latency of detecting a new card as when there is a card the LEDs turn on and off to sweep from left to right. As far as it's location, I'm guessing it just guarantees the card is flush with the bottom of the reader.

Alphie Boost Pack Cartridge (Electrical) -------------------------------------

The booster packs come in an excessively fancy box (completely custom, it's kind of nuts) filled with cards and a cartidge that I'm assuming for now has sound samples and the 'puzzles' on it. It's sonically welded shut but some prying with a screwdriver works well to pursuade it. The design of the cartidge looks like it was originally intended to snap together, but someone went the extra mile so children wouldn't break it open.

Anyways, the PCB has a chip-on-board design with the standard glob top. I can't figure out the protocol yet, but let's number the pads so I can explain some things. If you have one of these cartidges, flip it on its back so you can see the contacts. I'm numbering them from one to seven from left to right. Here's the breakdown:

  1. VCC (3.0 volts)
  2. Data
  3. Data
  4. Data
  5. Data
  6. Sense
  7. Ground

Those four data lines have some clockless format I've never seen before. I borrowed Alex's Logic Shrimp to check if I could see anything and it looks like there's a pulse of data every so often from pins 2, 3 and 4 with pin 5 flipping state occasionally. None of those signals are a real clock. I'll be checking things out on a borrowed scope, but I think I'll need to buy a hobbiest logic analyzer like the Logic 8 from Seleae so I can get long running dumps out of it.

The sense line is connected directly to the ground plane so that pin is driven low when the cartridge is inserted. Manually bringing that line to ground when a cartridge isn't inserted causes Alphie to pause every second or so it's probably an interrupt routine timing out.

Alphies of Different Regions:

So, Alphie is supposedly region locked to different locations. I assume this is so that kids don't get confused, but maybe it's a money grab.

The cards for the base pack have identical ids across English and French cards. Because some words aren't the same across languages the graphics and content of the cards are slightly adjusted. For the most part they're the same.

The EEPROM has two digits which are adjusted between English and French at offset 0x28. Here are the values:

English:  18 E7
Français: 17 E8

After some experimenting, the English cartidges definitely don't work. I did try changing the EEPROM on the off chance that it might work but unfortunately it didn't have any effect. It seems this DRM is locked into the firmware that I assume is just programmed onto a ROM.

Various helpful Bus Pirate commands:

Init system, list devices, start listening:

m 4 1
(1)
(2)

Read all EEPROM memory:

[0xA0+0x0][0xA1+rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr]

Read EEPROM byte(s) at location "??":

[0xA0+0x??][0xA1+rrrr]

Write EEPROM bytes 0xDEADBEEF at location "??":

[0xA0+0x??+0xDE+0xAD+0xBE+0xEF]
@alancfreeman
Copy link

Hi. Pleased to find this piece. I did make a few cards using MS Word that worked.
I google'd alphie card pictures, colored in my code and then listened to the robot, to figure out where
everything was. Have you done any further research on this project, or did you give up?
Do you have any REAL alphie cards? I'd love to have one that had a code that would allow me to perfect my
code lineup if you could scan and share with me? Blessings, Alan F.

@alancfreeman
Copy link

Hi. Using your decoding I was able to create about 30 cards that work in Alphie.
I made a MS Word template. Then used a black marker and a #2 pencil to encode the cards.
Then we placed them into Alphie, 1-by-1, and pushed buttons to figure out what each button meant for that card.
My son is almost 5 and can write, so I tasked him with that. He has had a blast with it.
I know we could buy the cards, but this has been a fun exercise.

@RandomInsano
Copy link
Author

RandomInsano commented Aug 18, 2016

Ah! Sorry I missed your comment. I have nearly all the cards for the Numbers, Music and Sound, and base set packs. My nephews have one booster somewhere as well. I can likely scan sets of four or five at a time, but there are a lot them. Any numbers you need in particular? The base pack is mostly represented in that list above.

I pick up the project every so often, and now I plan to replace the innards of one of the Alphies with a small computer before October. I may try reverse engineer the cartridge again now that I do have access to the right tools.

Also, if anyone else finds these useful, just e-mail me at edwinguy@gmail.com if you need anything else. I'd be interested in that MSWord template :)

@pieratt
Copy link

pieratt commented Mar 5, 2018

Good sir, curious if you've seen or uncovered anything like a list of phrases that Alphie uses?
The copywriting and interaction has always impressed me as unbelievably clever. I'd love to see a master list of the phrases he uses to interact with kids.

@RandomInsano
Copy link
Author

No, they're hidden away pretty well in there. I'm considering just using a Raspberry Pi Zero for my project as his phrases are a challenge to find/modify. In fact, it may be nearly impossible to do either.

@theseanzo
Copy link

Really appreciate this! Just got an Alphie 2 and am planning on putting a Pi inside. This will help a lot in my work to do so!

@RandomInsano
Copy link
Author

RandomInsano commented Jan 11, 2020

My plan was to do the same. How’d it work out for you?

@ethanm22
Copy link

hi
I know this topic has been dead for some years now, but just wanted to tell you all about something interesting about the 2009 / 2011 alphie: note, I am a visually impaired individual, so I will not be able to cover everything about the thing here, but I will point out some interesting stuff about the audio side of it
hold down the head button, the top left button, and the bottem right button and turn it on and release the buttons: then, wait for like 0.5 to 1 second, and press the bottem right button again
from this point, if you did this the right way, you will be in the factory debug / test mode
from here, you can use the top left and right buttons to move through the menu that pops up, and press the bottem right button to select, and the head button to exit out of something
a couple notes
in the wav test, use the top left and right buttons to go through sounds, the second and third left and right buttons to move by 10 and 100 sounds, the bottem right button to repeat a sound, bottem left button to start automatically playing sounds, and press the head button to exit
a note about the auto sound thing in the wav test, as well as anything else that plays audio in the test mode and even in the normal mode
for some reason the software that these things use has a weird thing where it cuts off audio: to get around this in the wav test, have it play a sound, then wait a couple seconds then press either top left or right buttons to advance or go back in the test
in the midi test, press eatch of the 8 frunt buttons to turn on and off instruments, and the head button to restart the midi: in the case of the music and sounds cartridge, the head button will cycle through midis
their is no way to exit this, so you will have to reboot alphie: just turn it off and back on
a note about cartridge audio and other cartridge things
to get audio from another cartridge to play in the wav or sequence test, as well as other cartridge stuff in some of the other things in the test mode, do the folowing
if you have a cartridge inserted, remove it
go into the test mode by doing the steps described above: when you have entered the test mode successfully, put the cartridge in: now, everything in the test mode will be baste on that cartridge, including the wav and animation tests
how to exit try me mode if you activate that option in the test mode
if you get stuck in try me, all you have to do is put a card in the card reader and turn it off and back on: once you do that, it will boot normally
well, think I covered everything here: I can poste an audio recording of the test mode working if you guys want me to
also, I have recorded direct audio from a couple cartrages if anyone is interested in that as well
hope you find this information useful

@RandomInsano
Copy link
Author

RandomInsano commented Oct 15, 2023 via email

@ethanm22
Copy link

ethanm22 commented Oct 15, 2023

hi
I found out about this a wile ago from a friend of mine who told me how to access it
if your interested, here is a recording of some stuff from both the base and food cartridge wav tests: this was recorded directly from alphie using a headphone jack I put on it
https://drive.google.com/file/d/1J5FE35Zlk34h9_UQT3qVL-8n8ifL7aRb/view?usp=sharing
hope you enjoy this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment