DIY wood keyboard using Apple M0110A switches and keycaps

CaptainCrounche

19 Aug 2016, 15:26

Hi everyone!

In the coming months I am planning to build a keyboard from scratch using switches and keycaps from a vintage Apple keyboard: the M0110A, that came with a Macintosh Plus from 1986.

Image
Image

Before I see any pitchforks I'd like to mention that even though the keyboard was functional before disassembly, the computer that came with it was no longer in my possession. A few keyboards were all I could save from an extensive collection of old Macs that was my pride and joy and ended up at the dump. Sure it would have been neat to keep it intact and turn it into a USB keyboard (like workshop-f7/the-apple-m0110-today-t1067.html), unfortunately my keyboard uses the idiotic French layout which I hate. Instead I will do my best to turn it into something great!

Image
Hello 30 year old dust bunnies.

Image
The Alps SKCC Cream switches feel pretty amazing. After a little research it looks like it won't be possible to find any new keycaps for these. They are not compatible with Cherry MX caps despite the cross shaped stem, nor with newer Alps.

Image
The CPU itself in the Mac Plus wasn't much bigger than this chip right there...

Image
Desolder all the things.

Image
Easier than I expected.

Image
PCB is removed, the switches are still mounted to the plate.

Image
Image
The one with the spring on it is the Caps Lock key. It stays down when pressed. Not sure if I can support that with a Teensy.

Now with the new keyboard
I like my arrow keys too much for a true 60% layout so I came up with this design using http://www.keyboard-layout-editor.com. Because the keycaps have weird dimensions, I can't reuse an existing design.

Image

Image
Cutting a cardboard plate to get an idea of the final result.

Image
Not too shabby! The cardboard is pretty sturdy considering how close together the holes are. It holds the switches firmly in place.

Image

Image

Now for the bad news... The keys have different profiles and I reassigned them to different rows, so it looks super derpy.

Image

Image

It will be fine for most keys, I'll erase the labels and place them back in their original rows. The problem will be with the longer ones, like the original rshift and alt, which will be moved to command and rshift. I can probably live with that, but still a minor bummer.

Image

Update 10/16:

Got my laser cut plate from http://www.lasergist.com, I highly recommend those guys, the customer service is bomb. Here is the Illustrator file I used: https://cl.ly/0M3M032m2T28. Unfortunately the openings I drew for the switches were 1mm too large in both directions, so the switches are a little loose. I had to glue them in place.

Image

Switches are in place. Diodes soldered.

Image

Image

Wired the columns the same way everyone else does, cutting and stripping those wires to the right length takes forever when you're trying to keep it clean looking.

Image

Image

And then wiring the columns back to the controller is when it starts to look spaghetti...

Image

I kept the wires long for proper cable management when I have a case.

Image

Finally functional!

Firmware

Most guides skip the firmware part so I'll share my experience in the hopes of helping someone out in the future.

Configuration used: Step 1:
Download the source code from the Github repo using the command:

Code: Select all

git clone https://github.com/kiibohd/controller.git
Step 2:
Duplicate the controller/Scan/MD1 folder, I named my copy captain.

Step 3:
Duplicate the controller/Keyboards/template.bash script, I named my copy captain.bash.

Step 4:
Open the script with a text editor and make the following changes:

Code: Select all

Line 14: BuildPath="captain" (or any name you like)
Line 46: ScanModule="captain" (the name from step 2)
Line 52: Chip="mk20dx256" (for a Teensy 3.2)
Step 5:
Edit the file controller/Scan/captain/matrix.h to include your specific pinout.

First, add the following defines right after #include <matrix_setup.h> to make the pin names easier to understand:

Code: Select all

// Teensy 3.2 pinout
#define PIN_00	gpio(B,16)
#define PIN_01	gpio(B,17)
#define PIN_02	gpio(D,0)
#define PIN_03	gpio(A,12)
#define PIN_04	gpio(A,13)
#define PIN_05	gpio(D,7)
#define PIN_06	gpio(D,4)
#define PIN_07	gpio(D,2)
#define PIN_08	gpio(D,3)
#define PIN_09	gpio(C,3)
#define PIN_10	gpio(C,4)
#define PIN_11	gpio(C,6)
#define PIN_12	gpio(C,7)
#define PIN_13	gpio(C,5)
#define PIN_14	gpio(D,1)
#define PIN_15	gpio(C,0)
#define PIN_16	gpio(B,0)
#define PIN_17	gpio(B,1)
#define PIN_18	gpio(B,3)
#define PIN_19	gpio(B,2)
#define PIN_20	gpio(D,5)
#define PIN_21	gpio(D,6)
#define PIN_22	gpio(C,1)
#define PIN_23	gpio(C,2)
#define PIN_24	gpio(A,5)
#define PIN_25	gpio(B,19)
#define PIN_26	gpio(E,1)
#define PIN_27	gpio(C,9)
#define PIN_28	gpio(C,8)
#define PIN_29	gpio(C,10)
#define PIN_30	gpio(C,11)
#define PIN_31	gpio(E,0)
#define PIN_32	gpio(B,18)
#define PIN_33	gpio(A,4)
Now at the bottom of the file you need to specify the pins you used for your rows and columns. Here are the ones I used:

Code: Select all

GPIO_Pin Matrix_cols[] = { PIN_05, PIN_06, PIN_07, PIN_08, PIN_09, PIN_10, PIN_11, PIN_12, PIN_14, PIN_15, PIN_16, PIN_17, PIN_18, PIN_19, PIN_20 };
GPIO_Pin Matrix_rows[] = { PIN_00, PIN_23, PIN_01, PIN_03, PIN_04 };
Leave Config Matrix_type = Config_Pulldown;

Step 6:
Run the compilation:

Code: Select all

cd controller/Keyboards
./captain.bash
You should get the following output:
Spoiler:

Code: Select all

$ ./captain.bash 
-- Compiler Family:
arm
-- Compiler Selected:
gcc
-- Chip Selected:
mk20dx256
-- Chip Family:
mk20dx
-- CPU Selected:
cortex-m4
-- Compiler Source Files:
Lib/mk20dx.c;Lib/delay.c
-- Bootloader Type:
Teensy
-- Detected Scan Module Source Files:
Scan/MatrixARM/matrix_scan.c;Scan/captain/scan_loop.c
-- Detected Macro Module Source Files:
Macro/PartialMap/macro.c;Macro/PartialMap/result.c;Macro/PartialMap/trigger.c
-- Detected Output Module Source Files:
Output/pjrcUSB/output_com.c;Output/pjrcUSB/arm/usb_desc.c;Output/pjrcUSB/arm/usb_dev.c;Output/pjrcUSB/arm/usb_joystick.c;Output/pjrcUSB/arm/usb_keyboard.c;Output/pjrcUSB/arm/usb_mem.c;Output/pjrcUSB/arm/usb_mouse.c;Output/pjrcUSB/arm/usb_rawio.c;Output/pjrcUSB/arm/usb_serial.c
-- Detected Debug Module Source Files:
Debug/cli/cli.c;Debug/led/led.c;Debug/print/print.c
-- Found Git: /usr/bin/git (found version "2.8.4 (Apple Git-73)") 
-- Found Ctags: /usr/bin/ctags  
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ctags: illegal option -- -
usage: ctags [-BFadtuwvx] [-f tagsfile] file ...
-- Detected Layout Files:
/Users/captain/Documents/Projects/Keyboard/controller/Scan/MatrixARM/capabilities.kll
/Users/captain/Documents/Projects/Keyboard/controller/Macro/PartialMap/capabilities.kll
/Users/captain/Documents/Projects/Keyboard/controller/Output/pjrcUSB/capabilities.kll
/Users/captain/Documents/Projects/Keyboard/controller/Scan/captain/scancode_map.kll
/Users/captain/Documents/Projects/Keyboard/controller/kll/layouts/md1Overlay.kll
/Users/captain/Documents/Projects/Keyboard/controller/kll/layouts/stdFuncMap.kll
/Users/captain/Documents/Projects/Keyboard/controller/kll/layouts/hhkbpro2.kll
/Users/captain/Documents/Projects/Keyboard/controller/kll/layouts/colemak.kll
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/captain/Documents/Projects/Keyboard/controller/Keyboards/captain.gcc
[  4%] Generating KLL Layout
Scanning dependencies of target kiibohd.elf
[  8%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o
[ 13%] Building C object CMakeFiles/kiibohd.elf.dir/Lib/mk20dx.c.o
[ 17%] Building C object CMakeFiles/kiibohd.elf.dir/Lib/delay.c.o
[ 21%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/MatrixARM/matrix_scan.c.o
[ 26%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/captain/scan_loop.c.o
[ 30%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/PartialMap/macro.c.o
[ 34%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/PartialMap/result.c.o
[ 39%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/PartialMap/trigger.c.o
[ 43%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/output_com.c.o
[ 47%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_desc.c.o
[ 52%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_dev.c.o
[ 56%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_joystick.c.o
[ 60%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_keyboard.c.o
[ 65%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_mem.c.o
[ 69%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_mouse.c.o
[ 73%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_rawio.c.o
[ 78%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_serial.c.o
[ 82%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/cli/cli.c.o
[ 86%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.o
[ 91%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.o
[ 95%] Linking C executable kiibohd.elf
Creating iHex file to load:    kiibohd.teensy.hex
Creating Extended Listing:     kiibohd.lss
Creating Symbol Table:         kiibohd.sym
[ 95%] Built target kiibohd.elf
Scanning dependencies of target SizeAfter
[100%] Chip usage for mk20dx256
	 SRAM: 	11% 	7636/65536	bytes
	Flash: 	11% 	29592/262144	bytes
[100%] Built target SizeAfter
Firmware has been compiled into: 'captain.gcc'
/Users/captain/Documents/Projects/Keyboard/controller/Keyboards
The firmware is packaged in a .hex file at controller/Keyboards/captain.gcc/kiibohd.teensy.hex

Step 7:
Now load the firmware onto the Teensy:
  • - Connect your Teensy to your computer
    - Open the Teensy loader app
    - Press the flash button on the Teensy
    - Drag the .hex file from step 6 onto the Teensy loader window
    - Press Program
    - Press Reboot
Step 8:
You keyboard is now able to send scan codes to your computer every time you press a key. To see them, open another terminal window and run the command:

Code: Select all

screen /dev/tty.usbmodemFA134
This will let you receive raw input from the Teensy. The letters and numbers after usbmodem might differ, just press tab to find out yours. You are now in the debug cli, enter the following command:

Code: Select all

matrixDebug
It will let you see scan codes for each key stroke.

You will now need to map each scan code to a character. This is done by editing the controller/Scan/captain/scancode_map.kll file. It is pretty straightforward, each line has a scan code and the corresponding character or key.

Here is mine for reference:
Spoiler:

Code: Select all

S0x08 : U"Esc";
S0x0E : U"1";
S0x0B : U"2";
S0x0C : U"3";
S0x0D : U"4";
S0x0A : U"5";
S0x07 : U"6";
S0x09 : U"7";
S0x06 : U"8";
S0x05 : U"9";
S0x04 : U"0";
S0x00 : U"Minus";
S0x03 : U"Equal";
S0x02 : U"Backspace";
S0x01 : U"Backtick";

S0x17 : U"Tab";
S0x1D : U"Q";
S0x1A : U"W";
S0x1B : U"E";
S0x1C : U"R";
S0x19 : U"T";
S0x16 : U"Y";
S0x18 : U"U";
S0x15 : U"I";
S0x14 : U"O";
S0x13 : U"P";
S0x0F : U"LBrace";
S0x12 : U"RBrace";
S0x11 : U"Backslash";
S0x10 : U"Function1";

S0x26 : U"CapsLock";
S0x29 : U"A";
S0x2A : U"S";
S0x2B : U"D";
S0x28 : U"F";
S0x25 : U"G";
S0x27 : U"H";
S0x24 : U"J";
S0x23 : U"K";
S0x22 : U"L";
S0x1E : U"Semicolon";
S0x21 : U"Quote";
S0x20 : U"Enter";
S0x1F : U"Function2";

S0x35 : U"LShift";
S0x38 : U"Z";
S0x39 : U"X";
S0x3A : U"C";
S0x37 : U"V";
S0x34 : U"B";
S0x36 : U"N";
S0x33 : U"M";
S0x32 : U"Comma";
S0x31 : U"Period";
S0x2D : U"Slash";
S0x30 : U"RShift";
S0x2F : U"Up";
S0x2E : U"Function3";

S0x44 : U"Ctrl";
S0x4A : U"LAlt";
S0x47 : U"LGui";
S0x49 : U"Space";
S0x40 : U"RGui";
S0x3C : U"RAlt";
S0x3F : U"Left";
S0x3E : U"Down";
S0x3D : U"Right";
Step 9:
Repeat steps 6 and 7 to recompile the firmware and load it onto your Teensy.

Step 10:
Enjoy your new keyboard.
Image

Next steps
  • - Make a case out of wood
    - Erase the keycap labels
    - Print new labels
Last edited by CaptainCrounche on 08 Oct 2016, 16:13, edited 3 times in total.

User avatar
chzel

19 Aug 2016, 15:51

Nice! Buttery smooth switches!
The one with the spring on it is the Caps Lock key. It stays down when pressed. Not sure if I can support that with a Teensy.
If you open up the switch there is a little wire with a small brown bit that causes the switch to latch.
Remove them and you're all set!

Don't even think of acetone on those caps...IPA will do just fine.

You might want to rethink the name? workshop-f7/brownfox-step-by-step-t6050.html

Keep the updates coming!

User avatar
kbdfr
The Tiproman

19 Aug 2016, 15:53

CaptainCrounche wrote: […] unfortunately my keyboard uses the idiotic French layout which I hate. Instead I will do my best to turn it into something great!

[…]

Next steps:
[…]
- I will have to get rid of the markings on the keys (acetone?)
- Maybe paint them (I'll have to see if the poopy brown color looks good with the wooden case, the space bar is super yellow though)
- Draw new labels (stickers...?)
[…]
Perhaps some of our French members would be interested in swapping caps with you.

Oh, by the way, welcome to DT and thank you for sharing :D

User avatar
chzel

19 Aug 2016, 16:02

Where are my manners? :oops: :oops:
kbdfr wrote: Oh, by the way, welcome to DT and thank you for sharing :D
^^That^^

CaptainCrounche

19 Aug 2016, 16:09

Thank you guys!
chzel wrote: You might want to rethink the name? workshop-f7/brownfox-step-by-step-t6050.html
Haha yeah I am following Matt3o's guide for wiring and programming, and the brown monstrosity I built kept reminding me of the name :mrgreen:
Last edited by CaptainCrounche on 19 Aug 2016, 16:28, edited 1 time in total.

CaptainCrounche

19 Aug 2016, 16:16

chzel wrote: Nice! Buttery smooth switches!
The one with the spring on it is the Caps Lock key. It stays down when pressed. Not sure if I can support that with a Teensy.
If you open up the switch there is a little wire with a small brown bit that causes the switch to latch.
Remove them and you're all set!
I mean if I want to keep this behavior for that key, it would be a nice touch don't you think? Otherwise I can just use one of the normal switches I have left.
chzel wrote: Don't even think of acetone on those caps...IPA will do just fine.
Gotcha :|

User avatar
chzel

19 Aug 2016, 16:58

CaptainCrounche wrote: Otherwise I can just use one of the normal switches I have left.
The stem of the latching switch is shorter, so the cap is different to get the same height as the other caps. You can of course mod the CapsLock to work with the other switches.

User avatar
Chyros

19 Aug 2016, 18:17

Nice! As you mentioned there are quite a few difficulties with any sort of customisation of this keyboard xD .

CaptainCrounche

08 Oct 2016, 16:19

Hey guys! I just updated my first post after completing most of the keyboard, it is now functional and is a pleasure to type on. Only two things left: make a case and erase those damn labels.

Does anyone has any experience erasing labels on keycaps? According to the wiki it appears that they're printed using Dye sublimation.

User avatar
scottc

08 Oct 2016, 18:54

You won't have any luck removing dye sublimed legends! The ink will have permeated deeply into the plastic. Since they're PBT, your only hope would be to dye all of them a dark colour and hope that the legends completely disappear. Though perhaps instead you could swap keycaps with a French user with an ANSI variant as per kbdfr's suggestion!

CaptainCrounche

10 Oct 2016, 11:40

Thanks scottc! Man that's a real bummer... I guess I'll have to dye them black then, my chances of finding a French user with US keycaps to trade for the same keyboard are pretty slim.

User avatar
scottc

10 Oct 2016, 13:31

You can try to get some alternative keycaps, though I'm not sure how easy that would be. The IBM Pingmaster has the same switches, so might be a good candidate, but shipping is incredibly expensive. I remember mr_a500 posting about other keyboards with these switches, can't remember details though.

CaptainCrounche

10 Oct 2016, 14:20

Oh great! I'll look into that. Thanks!

Post Reply

Return to “Keyboards”