Close
0%
0%

Macintosh SAO

It's the 40th anniversary of the original Macintosh. Why not recapture the magic in an SAO?

Similar projects worth following
To celebrate the the 40th anniversary of the introduction of the original Macintosh, this SAO will... look like a Mac. And maybe act a little bit like one too.

Instructions on use and documentation will be available at aeiche.com/macsao, though that URL hasn't been setup up quite yet.

This project uses the following components: 

  • CH32V003 J4M6 (the 8 pin SOIC)
  • An SSD1306 64x48 px OLED display (white)
  • A Fremont Micro FT24C64A EEPROM 8KB
  • A Side-shining LED 
  • A Panasonic EVQP7J01P right angle SMD button
  • A resistor for the LED
  • Two capacitors for noise reduction on power signal.

In addition to the I2C interface on the SAO, GPIO1 can be used to program the CH32V003 with the WCH SWD protocol. GPIO2 acts as a 2nd entry point for the button. So if you don't feel like pressing the button, you can use that pin.

How do I draw something on the screen?

The API is still a work in progress, but the short version is this: You send bytes to the SAO and those get interpreted as drawing commands. Here is an example of a command you could send: 

0x01  // Control byte 1 - write this to the display stack directly
0x01  // draw the desktop
0xFF //  END background
0x10  // Mouse to 
0x07 // x coordinate: 7
0x28 // y coordinate: 40
0x01  // again, draw the desktop
0xFF //  END background
0x10  // Mouse to 
0x37 // x coordinate: 55
0x1E // y coordinate: 30

This will draw the mouse going from (7,40) to (55,30). Once the animation is done, the mouse will go back to (7,40) because the whole thing starts over again. It'll repeat endlessly. These bytes are written in hexadecimal, but you're just sending numbers anyway, so keep in mind that when you write your code you can probably just use decimal.  Full documentation on the commands will be available soon. Among other things, I hope to provide a nice set of Mac-like stuff in the API as well as just simple drawing commands, if you just want to draw to the screen using a basic graphics library.

  • 1 × CH32V003 J4M6 (8-pin SOIC)
  • 1 × SSD1306 64x48 0.66" OLED display (white) 4 pin i2c variety.
  • 1 × Freemont Micro FT24C64A EEPROM (8K)
  • 1 × Panasonic EVQP7J01P Right Angle SMD button
  • 1 × 1K ohm Resistor (for LED)

View all 8 components

  • Jiggery-Pokery!

    Aaron5 days ago 0 comments

    My new boards arrived! After a bit of eval, I'm feeling very confident that they do what I want them to. Also, cutting the additional square out for the Apple logo looks very nice, and I'm pleased with how it turned out. 

    Most of the components on the board are SMC, so I'll squeegee some solder paste on, place the components and either bake in an old toaster oven or use the hotplate I got for the purpose. 

    The thing I can't do via reflow is solder on the display. As previously noted, I stumbled into the idea that I could just wick the pins onto the contact pads with a bit of solder, but aligning the display was going to be an issue.

    Of the many benefits to the home enthusiast 3D printing has bought, one of them is custom jigs. A simple tool custom made to help you accomplish positioning or accuracy. 

    I wasn't entirely sure how to put mine together. I needed to position the display, and the PCB, make room for the button which is at the bottom, and of course leave the top open so I could actually solder the thing. 

    I made a lot of jigs. I eventually settled onto a fold-over setup. The bar that sets the position rests on the placement of the SMD resistors 

    Left to Right, my various attempts at a jig

    Eventually I managed come up with a working design. The operation is pretty simple. Put in a reflowed board, close, slide in a display. Solder the pins. 

    The second display I've tried to place with this fit very snugly in the orange display-positioner. So I can also pre-place the display. I'm tempted to make one more run of the green base, cutting open the back so I can check the display from the front-side, but if I've tightened the screws right it should be repeatable.

    And here is the first product: 

    The logo doesn't look as intense in person

    Gotta finish the firmware. Gotta complete the documentation.

    “Jiggery pokery!” said Harry in a fierce voice. “Hocus pocus — squiggly wiggly —” 

  • "Painting" in MacPaint

    Aaron10/05/2024 at 19:23 0 comments

    While I wait for the final (fingers crossed) boards to arrive, I had to figure out the appropriate resistors for the LED. In addition to the white LED, I did a test of red and it turned out really nice - the picture here does not do it justice. I think I'll make a few with red, and the rest with white. Additionally, I'm contemplating getting some opaque black hot glue to act as a light baffle. I really don't like the way the light bounces out the back.

    I'm in the middle of reevaluating the command processor, because I'm testing the limits of its practicality and I want it to be as easy as possible for a user to make the thing they want to make. And do lots of different things with it. 

    Anyway, I've added a buffer to MacPaint so you can draw on it and it persists between drawing screens and animating the mouse and whatever on top of it. This is really exciting to me because its critical for one of the big showpieces I wanted for the MacSAO (I don't know if I'll reveal that here before Supercon)

    Figuring out the buffer

    The next big thing to tackle is the command structure. Right now before any action (like animating the mouse) you have to redraw the background. That makes sense, but the current system means you have to send a new command doing it again. So for instance in the gif below I have to explicitly draw the background before each step. I have a plan to handle this programmatically, but haven't gotten there yet. 

    The smile is a little lopsided due to bad coordinates

  • Characters and "Typing" in "MacWrite"

    Aaron09/29/2024 at 03:06 0 comments

    I've ordered the final boards for the Mac SAO and (provided I haven't made any catastrophic mistakes) I'm waiting for them to be manufactured and shipped. In the mean time, I'm tackling more firmware, and todays exploits were "typing out" characters in "MacWrite"

    The display on the MacSAO is only 64x48 pixels. The character font that is included with the CH32V003fun library are 8x8 pixels. Putting nothing but these on the screen will get you 8 characters per line, and only 6 rows top-to-bottom (with no spacing). 

    I started poking around for a font that would be sufficient. There are a few 4x3 fonts out there, but I didn't want to worry about licensing, and I did want to be able to distribute the source eventually. I found a great font in Romeo Van Snick's Creep, which is a 4px wide font.

    I couldn't find any way to simply extract the bits from the font file, so I ended up reconstructing them in Emutyworks' Bitmap editor. While I was doing this, I ended up altering some of the characters more to my liking.

    As you can see from the bitmap, I tried a few different approaches. There is a world out there where I managed to get the combo Capital/Lowercase-in-a-single-byte to work, but in the name of getting things done, I just put each character in its own byte. If I start running into flash issues, I may try to solve this. As an aside, working on a project at this resolution and this size really emphasizes how much you can rely on the human brain to fill in the gaps of an experience. Some of these characters are only recognizable because you know what their much bigger, much better-defined representations are. The lower-case "m" and "w" are particularly suspect.

    One of the frustrating problems I had was getting the characters to display in the way I wanted them to. There is the way that you store the data, and the way that you read the data. I was frequently getting mirrored characters, or characters rotated 90 degrees. The right way to handle this would be to have a good understanding of how the bitmap interpreter moves through the data and build according to that. Instead, I just leaned heavily into Jasper Van Loenen's image2cpp and trial-and-error'd my way to success. 

    With the characters taken care of, I started working on displaying the characters. I wrote an ASCII map to transform character codes into actual characters on the screen, and a method of animating them.

    I probably need to figure out a scrolling feature, but maybe I'll leave that up to individual users. 

    Glancing at my the statistics on the build, I am creeping up on the limits of the CH32V003. I have just 4k of flash left, and 196 bytes of ram to work with. I'm sure there are opportunities for creative efficiencies.

    I'm pleased with the result. I can fit 3 lines of text in the MacWrite window. There are 10 characters of space per line with a single pixel between characters. Some characters being narrower than others, you might be able to fit 11 or 12.

    At any rate, I'm having fun and I'm very pleased with how it's looking.

  • Memory and Light

    Aaron09/18/2024 at 03:37 0 comments

    I got in the EEPROM and the LEDs for the apple logo, and hand soldered them in place. The pads are not intended for hand soldering - that said, I managed to make it work.

    Perfect!

    This is the LED at 3.3V with a 0 ohm resistor. It is shockingly bright. If someone needs a flashlight this will serve very well. Suffice to say that I need to figure out a more appropriate resistor. Through a happy accident, I found what I think is the right brightness level.

    I plugged the board into my Vectorscope - which happened to have low batteries - and the LED brightness was just about right. I just have to measure the voltage, and do the reverse calculation to get the proper resistor value.

    Even with the brightness toned down, it presents another problem. If you look up at that first picture, there's a lot of light bleed out the left side of the Mac. The LED is putting light through the PCB, and the translucent fiberglass center of the PCB acts as a light-pipe.  The fix for that was simple, if a little hacky. I took a black sharpie and ran it over the edge where the light was bleeding.  

    When I get these boards made in white, I'm not sure the same solution will work as well. With the black soldermask, it's not really noticeable. With the white soldermask, even though its on the side, it'll kind of stick out. One wild (and expensive) solution would be to edge plate the board, so that there's a metal edge around the outside. It'd be pretty, but is only available in gold (ENIG) and I prefer the look of Lead-free HASL.

    EEPROM Woes

    I have run into another issue as I've been writing firmware. The EEPROM was not reliably writing or reading data. It would work 1 or 2 times out of 5. At first, I thought it might be too much resistance on the I2C lines. I removed the pull up resistors on the lines and of course realized that they're in parallel. If anything, they were lowering the resistance on the line. I thought it could be a timing issue - but no dice on that front either. 

    While thinking about how I2C works, it occurred to me that maybe my EEPROM calls were getting muddied by calls being sent to the display. I2C doesn't do anything to prevent the master from interrupting itself. And neither was I. Calls to the display are fired every loop, and the signals coming from outside the SAO can happen at any time. Since I2C data is relatively slow compared to the rest of the work the SAO was doing, it's a reasonable assumption I was tripping over my own shoelaces, so to speak.

    I added an I2C 'reset' to the start of my EEPROM handler, and everything has smoothed out.

    Finally, I found the point where my SAO stops working:

    2.58V. It sure does try though.

  • v1.1 Assembly test drive

    Aaron09/14/2024 at 02:12 0 comments

    My second test run (version 1.1) showed up in the mail today. Version 1.1 fixes and moves the SAO connector to the center, adds an EEPROM and an LED behind the Apple logo (thanks for the idea Tom!). The EEPROM and LED are still coming in the mail. 

    Protoype in Black, just for fun

    One of the challenges I'm facing is how to attach the display to the main board. Because real-estate on the board is so tight, a typical surface mount header wouldn't work. I didn't want a through-hole header because I wanted the front of the SAO smooth. 

    The weird solution I'd come up with was to cut short lengths of copper wire and solder them to the pads on the back. It required desoldering the headers already on the board (and clearing the holes), sliding through the copper wire, bending them to the right position, and soldering in place. 

    I tried this a couple of times and in both cases, I accidentally ripped a pad off while bending the wire. This wasn't looking good. I have a few more test boards, and some extra displays to experiment with, but I didn't want to start losing parts to a hare-brained scheme. 

    Looking at the displays I'd bought - which again, had headers soldered in place already - I wondered if I could get away with just soldering the pins to the pads and just letting the surface tension wick the solder across the gap. As it turns out that solution worked really well, and is far easier to do.

    I proved the concept using the board I'd already damaged

    It's a tight spot to solder in, but the included tip of my PINEcil did it without issue The solder pad and pins do the real work. When I actually get to assembling en masse, I think I'll design a 3D-printed jig to properly position the display and the board relative to each other.

    Of course, given the pad I ripped away, I had to hack together a solution. Fortunately the contacts were easy to reach. When the EEPROM and LED show up, It'll take a little effort to get them soldered in place.

    I'm pleased to say that my software uploaded without issue on the first try. It even runs on last year's VectorScope badge. I was a bit surprised at this because I put rechargeable batteries in which are nominally 1.2v. The datasheet of the CH32V003 said that it wanted a 2.7v minimum. My multimeter tells me that the battery output of the SAO port is currently at 2.65v (that's freshly charged.) I'll have to see how long it can operate at that.

    There has been a bit of scuttle on the Hackaday discord about the startup state of this year's badge GPIOs. If you have the pin plugged into the SAO header, it may trigger programming mode. (Specifically, it was Tom Nardi's Cyberdeck SAO with the ATTiny3224, but I believe the CH32V003 basically uses the same protocol.)

    I have a board version in KiCad right now that adds a jumper for enabling programming via the header. With that, instead of bridging it with solder I would add a pogo pin to my programming setup and just have it connected which inserted. 

    I'm this close to being locked in on the hardware. Firmware is coming along. I'm working on the EEPROM storing and retrieving sequences.

  • Inside Macintosh

    Aaron09/04/2024 at 00:27 0 comments

    As near as I can tell, SAOs have largely been "flair". Something to stick on your badge to give it a little more personality. 

    Originally this project was going to be just that. A little display for me to do some fun things on. Once the focus on SAOs was announced for Supercon this year, my plans started expanding. Instead of just drawing some pictures on the screen, I decided that I wanted an API that anyone could use to draw on the screen. 

    After a week or so of hacking away at it, I have the beginnings of an API. A few "screens" and moving the mouse. The API is great because not only can other people who have it draw Macintosh stuff to the screen, but it makes all the things that I wanted to draw a lot easier as well. 

    The above animation is just a test of what I was working with - namely showing different selected menus and moving the mouse around. Previously I would have written a function that would draw these things. That's still true, but now with a layer of abstraction. I just send a series of bytes to the SAO and it stores and decodes them. The animation here exposes a bit of the stage magic though - the mouse and the menu aren't actually interacting.

    The API feels obvious to me now, but it was a while before I had a clear picture of how it would work. I settled on a structure that alternated between the background and the "animation" layer.


    The user could send a series of bytes to draw the background, and then an animation command that would draw the mouse moving around. The bytes are commands and arguments for those commands. They look a bit like this: 

    0x01 0xFF 0x10 0x0A 0x14 0x01 0xFF 0x10 0x1E 0x14
    
    // A break down of the commands: 
    
    // 0x01    0xFF 0x10    0x0A 0x14 0x01    0xFF 0x10    0x1E 0x14 
    // Desktop STOP MouseTo 10   20   Desktop STOP MouseTo 30   20

     The Desktop command draws the desktop. The STOP says "stop drawing background". MouseTo will animate the mouse from its current position to the coordinates provided, in this case (10,20). Once the mouse reaches (10,20), we move onto the next pair. We basically do the same thing but draw to (30,20). Once the whole set is completed, it loops back to the beginning. One of the neat things about this that the mouse doesn't care about where its coming from - So this would make the mouse move up and down and back again.

    As I've developed it, I've stumbled into amusing situations like the following, where I accidentally "paint" on the desktop with the mouse cursor: 

    Closer to Supercon I'll start working on documentation for how to write custom display animation. I still have a few firmware things to square (namely button interaction, and the i2c Address selection) before I can focus solely on the "Mac" parts of the project. And I still need to order new PCBs.

    Overall, I'm really excited about how it's all coming together. A couple of months ago this was a very different project, and I'm thrilled at how its turned out. 

    Inside Macintosh is the name of the developer documentation written by Caroline Rose that was provided for 3rd party developers when the Macintosh was introduced. 

  • From plus to minus, and from minus to plus!

    Aaron08/26/2024 at 06:14 0 comments

    I was a bit of a ways into working on this project when the announcement for this year's Supercon dropped, and the encouragement to bring your own SAO. As mentioned previously, I've become interested in both driving the display via i2c and receiving commands from the badge its connected to... via i2c.

    Initially, I was sure the right way to do it would be to have the hardware i2c stack drive the display and the software stack to act as the i2c target for the badge. This appears to be exactly the wrong approach. Knowing far more about i2c than I do, Charles Lohr offered this helpful chart: 

    In short, when at all possible you should use software for the master and hardware for the target (slave) device. 

    Fortunately, that meant I didn't need to do a lot of work. I could use the CH32V003Fun implementation of hardware i2c to interact as a target, and a software library to serve as the master to drive the display. 


    After a few days of hacking around with it I managed to draw data to the display, but it was offset by a couple of pages (8 vertical bits per page) 

    This was odd because the hardware i2c version of the code that I'd written didn't show this problem, and the display setup was identical. Eventually I found that the software setup I'd replicated was designed for displays that were either 64 or 32 pixels tall. Mine is 48, and I needed to adjust the screen multiplexor to wrap at the right width for the right number of lines.

    The rest of the weekend I hacked together a proof of concept for running both i2c channels and it's working! 

    The prototype and a Teensy for testing

    This version is the display running off the CH32v003 on the left (Software I2C) and a Teensy 3.2 (on the right) is sending a packet (CHV32003 Hardware I2C as Target) to draw which tool is highlighted in this MacPaint window. It's an early test, but the proof of concept works. I have already rerouted the signals on the board.

    Lastly, the displays arrived. To my chagrin, they already have headers in them. This means that I'll need to desolder the existing headers and setup new ones. Because of my preference for a surface-mount connection, I also have to add my own headers to the board.

    I bought some AWG24 copper jeweler wire at a local craft store. Then I make a little bed, and hand solder. I haven't come up with a better process yet... 

    Hand-Crafted in the Pacific Northwest

    Next steps: 

    • Make sure Button interrupt works
    • Protocol for sending commands
    • New PCB spin

  • PCBs and first assembly

    Aaron08/16/2024 at 06:00 2 comments

    My first PCBs arrived yesterday and I'm really pleased with how they turned out! I was feeling a bit concerned about the detail of the apple logo, and and the outline around the shape that was provided by masking, but I don't think I could be happier with how it looks. It's really great. 

    I soldered one together and immediately ran into a problem. I couldn't get the programmer to talk to the chip. I checked the connections, checked the pinouts, checked continuity. I tried unplugging it and got the same response. The programmer didn't think there was a chip present - but the programmer reported that it was "already connected" and also reported the wrong chip.

    I did a visual inspect of the header, and it looked like it really wasn't very well soldered onto the board. While I plan on reflow-soldering most of these, this first one I thought could just be hand-soldered. I added some more solder to the SWD pin (the 1-wire programming pin) and like magic, it worked! 

    For lack of a better-solution, I soldered some stranded wire to the display headers. I mentioned previously that I made these surface-mount because I wanted to keep the aesthetic of the front of the board - there wasn't room for single-row SMD header pins. My current plan is to use 20 gauge bare copper wire (like jewelers use) to go from the board to the display. I thought about just buying some solid-core wire, but it would require an awful lot of wire stripping on some very short wires.

    In the meantime, here is the assembled v0.5: 

    Next steps: 

    • Try the bare-wire screen connect
    • Order the OLED displays
    • Order new PCBs with the fixed header
    • Finish the software (I have a lot of display stuff done, but the interactivity would be nice)

    If I time this right, I think I could get them all built pretty quick. It'd be nice to not have this come down to the wire.

  • Whoops! And other things...

    Aaron08/07/2024 at 23:18 0 comments

    I am impatiently waiting the arrival of the components and PCBs that I ordered just a few days ago. While looking back at the last log I wrote, something caught my eye: 

    I put silkcreen + and - symbols near the header. And looking at the badge on my desk (shoutout to the Supercon 7 Vectorscope) I realized the position of the pins was wrong. I had the header backwards! Furthermore, I knew how I'd made my mistake:

    This is the view of my board from the front (after I corrected it.) Because the front of my board has no components on it I spent most of the time laying stuff out on the back. I think I even did it from the front and wasn't paying attention to the footprint orientation. Whoops! This could have been avoided if I'd used the "official" SAO footprint, but I didn't want the through-hole, so I made my own (I should know better by now.) As I said previously, I have made many PCB mistakes. This one is not huge. When the boards come, I'll still be able to program and test how everything comes together.  And see how it looks visually. It just won't work plugged into a header. I'll respin, and try again.

    Since my last project log here, Hackaday officially put Supercon 8 tickets up for sale. In that announcement we learned that this year's badge is going to focus on SAOs! There were some subtle hints about utilizing the whole 6-pin header. As I mentioned previously I included support for the Pins as a target device. However the CH32V003 only has one hardware I2C port and I'm using that for the display.

    If I want to support I2C as a target I can either write a software I2C Driver (just bit-banging the protocol) or I could switch to another chip. The step-up from the CH32V003, the CH32V203 has two sets of I2C pins, so I could just switch chips and get that. 

    A third option would be to swap out the I2C display for an SPI version,. The displays are the same, but the protocol is different. In this case, I'd need to move from the CH32V003J4M6 to a different package that has a few more pins. 

    At any rate, I have some choices to make - and my original boards probably aren't going to arrive for another week.

  • Parts and PCBs ordered

    Aaron08/02/2024 at 05:54 2 comments

    I pulled the trigger and ordered PCBs and parts - so far everything except the displays. I've made a number of PCBs in the past ~15 years since I got into the electronics. Frequently I have made some silly mistake that has necessitated my ordering a new variation of a board. Of course every time I do it I try to be extra meticulous so as to not repeat the problem. As an abundance of caution, I ordered just 10 PCBs.

    Interestingly in KiCad's 3D renderer the silver details
    aren't visible looking at the board head-on

    I decided to implement a button (again, inspired by Tom Nardi's Cyberdeck SAO) for stand-alone interaction. Initially I was going to try to do this as a capacitive touch pad, but I've had mixed success with those in the past and space was already tight. This button is connected to the GPIO2 pin on the header so it could be triggered from whatever its attached to. The SAO header  also implements a pair of  i2C pins. I like the idea of there being an API to draw on the screen, but that necessitates writing an i2C software stack to handle the second i2c.


    Now I just have to wait for all the parts to get here. I'm not in a rush, and it's still a few months until SuperCon, so its going to be a couple of weeks. After I've successfully assembled a board, I can order the remainder of PCBs and all the displays. 

View all 17 project logs

Enjoy this project?

Share

Discussions

jeremy.geppert wrote 09/23/2024 at 01:43 point

Love the trick to hide the OLED pins!!! Brilliant! Mine are in the middle of the board unfortunately. There might be some liberal application of thick black automotive touch up paint to "hide" them. I hope you have the sad face mac screen on there at some point. :(

  Are you sure? yes | no

Andy Geppert wrote 09/04/2024 at 13:01 point

THIS IS AWESOME!!! Can't wait to see these in person!

  Are you sure? yes | no

Aaron wrote 09/05/2024 at 04:37 point

Thanks! I'm really looking forward to sharing it! I'll keep an eye out for you.

  Are you sure? yes | no

Gravis wrote 08/08/2024 at 13:07 point

What is an SAO?

  Are you sure? yes | no

Aaron wrote 08/08/2024 at 16:03 point

It's a circuit board you can plug into conference badges. They're often artwork made with different layers of the PCB. Sometimes they have LEDs or other electronics that make them interesting. It's pretty broad what they are.

Here are a few of links:

https://hackaday.com/2018/06/21/this-is-the-year-conference-badges-get-their-own-badges/
https://hackaday.com/2019/03/20/introducing-the-shitty-add-on-v1-69bis-standard/
https://hackaday.com/tag/shitty-add-on/

  Are you sure? yes | no

Tom Nardi wrote 07/05/2024 at 16:54 point

Love this idea. I've actually been thinking of spinning up a new run of the Cyberdeck SAO using the CH32V003, partially because I wanted to get some practical experience with it, but also because the ATtiny I used are ~80 cents a pop.

  Are you sure? yes | no

Aaron wrote 07/05/2024 at 22:55 point

Thanks Tom! I'm pretty happy with the 003 now that I've got my feet under me. Charles Lohr's libraries make it a lot easier. I look forward to seeing the next version :)

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates