Perceive

Computers That Influenced Me

I’ve been programming for about as long as I can remember, since sometime around the age of 7. During that 39 years I’ve used and learned with many computers.

Recently I decided to start collecting old computers, and needed to limit myself in some way because I could easily end up with a museum. Setting a limit to only computers that were influential in my life seemed like a good way to go.

I thought I'd share the memories I have about those computers.

Timex/Sinclair 1000 (a.k.a. Sinclair ZX-81)

Timex/Sinclair 1000
Timex/Sinclair 1000

My grandfather was a TV repairman, and around 1980-something the company he worked for started selling computers. I believe most of what they sold at that time was inexpensive machines, one of those being the Timex/Sinclair 1000, known to the rest of the world as the Sinclair ZX81. This little computer used a Zilog ZX80 processor in a very small plastic case with a flat membrane keyboard that was horrible to type on. I remember each key had multiple meanings depending on the modifier key you were holding down. Complex stuff for a 7 year old! I learned to program in BASIC, and although I don’t recall what I wrote, I remember making a bunch of silly things on the order of the classic:

10 PRINT “HELLO”
20 GOTO 10

In addition to more complex variations making the text appear in different places around the display. Which brings me to the peripherals. We had a small, maybe 8” or so black and white TV, which I’m pretty sure was from Radio Shack, a cassette deck for saving data and programs to, and a small thermal printer, also made by Sinclair.

For those that might not been around for the “fun” that was the act of saving data to a cassette tape, let me tell you it was slow and painful. You put the cassette in, rewind it to the beginning, and then fast-forward the tape to the spot where your program was saved, which you had dutifully written down after looking at the counter on the cassette deck. One fun quirk that I also remember — All cassette decks were not created equal. The counter on one might not match another, so using the same one was important. After you find your place, you would type in a command on the ZX81 to initiate loading, and then hit play on the deck. After what seemed like at least 2 hours (but was more like 2 minutes) whatever you were loading would finish and you would tell it to RUN, starting our code.

IBM PCjr

IBM PCjr with sidecar and CRT
IBM PCjr with sidecar and CRT

Over the next few years, the company my Grandfather worked for started carrying newer, fancier computers. When the PCjr came out he helped my parents purchase one. I remember a lot of neat things about it: It had an infrared "chicklet" keyboard, no wires needed! You could get these expansions for it that snapped onto the right side of it, and you could stack up some number of them. I don’t recall us ever having any though. It also had two cartridge slots. I don’t think many cartridges were actually available, we had the BASIC one. It also had a matching display, and best of all it used 5-1/4” floppy disks.

I did a lot with this computer. Learned BASIC well, played tons of games and learned to program in Turbo Pascal.

Apple II Series

An Apple IIe
An Apple IIe

I never owned an Apple II until very recently. I did, however, use them in school. I of course played [The Oregon Trail](https://en.wikipedia.org/wiki/TheOregonTrail(series), and there were other educational games by MECC that I don’t remember as well. The one thing that I do remember is [Logo](https://en.wikipedia.org/wiki/Logo(programming_language). Logo was a programming language built for one thing - it made a cursor or “turtle” draw on the screen. You could create surprisingly complex designs with it. I don’t recall exactly which model of Apple II it was, but I would guess it was the Apple IIe.

Paul Rickards Shared a nice recursive Logo procedure for creating a spiral design:

TO POLYSPI :D :A :I
FD :D
RT :A
IF :D > 200 [STOP]
POLYSPI (:D + :I) :A :I
END

Running the following:

POLYSPI 2 122 2

creates this image:

Logo
Logo "Polyspi" function rendered on an Apple IIc

Some years later the Apple IIc was released. It was a compact (thus the “c”) version of the Apple II platform that was portable, and looked sharp! It also had a matching green display that hovered above the machine by way of a mental stand. A friend of mine had one, and I drooled over it.

I just recently acquired and Apple IIc, with monitor and carrying case, and I’m currently learning 6502 programming.

IBM PS/2

IBM PS/2 Model 70
An IBM PS/2 Model 70

I had a few IBM PC-based clones long the way - an 8088 based machine (4.77mHz with 10mHz turbo button!), 80286, 80386, and 80486. But the next computer that really influenced by life was the IBM PS/2. During my junior and senior years of high school I took mechanical and architectural drafting respectively for the last half of my day. My school had acquired an IBM PS/2 with monitor and mouse. This was one of the 80386-based models, and it was to be used with AutoCAD R9. I became really good with AutoCAD, even entering and winning drafting competitions. I was fast, and it was fun. AutoCAD also introduced me to the AutoLISP programming language, a derivative of standard LISP. I found I really enjoyed automating things in AutoCAD, and later had a job as an draftsman where I spent far too much time programming in AutoLISP.

An actual floorplan I drew somewhere around 1991 when I was 16, as evidinced by the naming of objects
An actual floorplan I drew somewhere around 1991 when I was 16, as evidinced by the naming of objects

NeXTStation

A
A "pizzabox" style NeXTStation

Although I didn’t graduate from college, I did attend for two very influential semesters in 1993/1994. The architecture college at University of Kentucky had a computer lab, and in this lab were magical, powerful machines — a variety of NeXTStations — the base NeXTStation which only displays black and white, NeXTStation Color models, a couple NeXTStation Cubes, as well as Turbo Color models. They all had matching displays and they were amazing.

To me, even though I had used Windows 2, 3, and 3.1, the NeXTSTEP operating system seemed revolutionary and afforded totally different and more flexible workflows.

My two semesters may not have resulted in a degree, but I did learn to program in Objective-C, which I used later when working for myself and at Apple

I currently own a NeXTStation Color (thanks to David), it does boot but needs some work to get it fully going (like a new storage drive).

Silicon Graphics Indy

Silicon Graphics Indy Workstation
Silicon Graphics Indy Workstation

After my short stint trying out college, I worked for a small production company that was getting into the 3D design space. They had some Silicon Graphics Indy workstations, and Softimage 3D software for design. Even though the Indy was a lower-end workstation compared to the Indigo² or their beefier rack-based machines, it still blew away the personal computers I had used and had yet another UI that was new to me. The Irix operating system was unix-based, and was somewhat familiar because of my recent introduction to Linux.

I learned a ton on this machine, expanding my 3D design skills and it heavily influnced my desire for good UI and usability.

I currently own one of these, and I'm in the process of rehabilitating it.

Power Mac G4

The
The "Graphite" Power Mac G4

This machine is different than the rest in that I still own the actual computer. This was also the first Apple computer that I personally owned, after many years of wishing. I purchased it in 2002, and it was a few years old at the time.

I was working for myself and a client (and good friend) of mine wanted to make sure that the websites I was creating for him worked well in Safari. So I bought this machine on eBay and fell in love. I started out on the floor next to my main computer (which was a self-built PC). I found myself quickly using the Mac much more often than the PC even though it was older, and had a much slower processor. I fell in love with that Mac, and it resides in my office to this day.

I hope you enjoyed my little trip down memory lane, I know it was fun for me. Finding each one of these to collect is going to be a blast.

How I build this website

When I rebuilt this website recently, after many years of neglect, I decided I wanted to use Swift. There have been many versions of this website first starting with all hand-built html/css, a Perl/cgi-bin version, then I moved to a PHP-based template kind-of thing, then to XML content and a .NET JIT rendering engine, then an Objective-C rendering engine with GNUStep, and now after many years it was time to give it another go. I picked Swift for a couple of reasons, it's a very enjoyable language, it's the language I'm using most often now and it's certainly the "New Hot Thing". I had a few basic requirements:

  1. It should be a baked website, in that the HTML/CSS is generated, written to disk and served. The pages shouldn't be generated at request time.
  2. Content should be markdown-based. All my existing content is in Markdown, which was converted from a bunch of XML files long ago.
  3. There should be a flexible template rendering system

I started writing my own, and kept adding features. It was coming along nicely. But then I came across the Publish Site Generator by John Sundell, and it was exactly what I needed -- lots of configurability, templates built in Swift, and content written in Markdown.

I set it all up, designed a new layout and brought in my content. Next I wanted an automated build workflow. My ideal setup is write content on my iPad, push to git and the site should automatically rebuild and publish. To do so I decided to use GitHub actions to try out this fancy new CI technology.

The configuration is pretty straight forward. Create a directory named .github in the root of your repository. Within this, create a workflows directory, and a file named build-site.yml (or whatever name you want). The configuration below is what I'm using to build the site.

name: Build Site

on:
  push:
    branches: [ main ]

  schedule:
    - cron:  '0 10,15,19,22 * * *'

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    container:
      image: swift:5.4
      options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined
  
    steps:
      - name: Update system & install sudo
        run: apt update && apt install sudo
        
      - name: Update git
        run: sudo apt-get install -y software-properties-common && sudo apt-get update && sudo add-apt-repository -y ppa:git-core/ppa && sudo apt-get update && sudo apt-get install -y git
        
      - name: Checkout
        uses: actions/checkout@v2
        
      - name: Install Dependencies
        run: sudo apt-get install libsqlite3-dev
      
      - name: Get Current Date And Time
        run: |
          echo "CURRENTTIMESTAMP=$(date "+%Y-%m-%d_%H-%M")" >> $GITHUB_ENV
      
      - name: Generate blog
        run: swift run PerceiveNet

      - name: Add & Commit changes
        uses: EndBug/add-and-commit@v7
        with:
          default_author: github_actions
          message: "Site Build: ${{ env.CURRENTTIMESTAMP }}"
          add: "--all"
          tag: "Build-${{ env.CURRENTTIMESTAMP }}"
          push: true

This configures two build triggers. The first is anytime content is pushed to the branch named main, and the second is on a schedule which builds it 4 times a day. I have external content that is pulled in at build time so the pull trigger alone isn't sufficient.

The build itself creates a new ubuntu instance from the swift5.4 image. It then updates the OS, and pulls in a bunch of necessary packages. After that, it checks out my code, installs some other dependencies, and generates the blog. After this completes it commits the outputted content back to git.

Now for the step that publishes this to my webserver. Initially I had a CI step that used SFTP to push the content to my server. This took a good 15-20 minutes every run. Since it doesn't need to run often, this shouldn't matter, but I also want to keep the CI bill down, and every minute costs money. So I decided on a pull method.

Since the updated content is committed back to the git repository in the last build step, I decided to just use git for deployment. So I setup a periodic cron job to pull changes from the repository to my server. This was reasonably straight forward. My crontab for this looks like this (which pulls every 15 minutes):

0,15,30,45 * * * * cd /www/perceive-net/ && git pull origin master

I also had to change the URL for the git origin in my .git/config file in the repository to make sure it uses a personal access token to pull, since this is a private repository.

[remote "origin"]
	url = https://<USERNAME>:<PERSONAL ACCESS TOKEN>@github.com/<REPO OWNER>/<REPO NAME>.git
	fetch = +refs/heads/*:refs/remotes/origin/*

Now I can add and edit content on my webite from any device that can use git. On iOS I use Working Copy to fetch the repository. It handles all of the git interaction, and exposes the repository as a source in the iOS Files app (and thereby to any other app that works with that). Works like a charm.

Turning your Apple IIc into a Dumb Terminal

I recently purchased an Apple IIc, and decided it would be fun to use it as a dumb terminal on my Mac. There are only a few references out there, and none of them have complete/accurate information anymore it seems, so I thought I would write up the steps that I did that work.

This works with a Mac running macOS Monterey.

First you'll need to purchase a couple of items:

  1. 5DIN to DB9 cable. I purchased this one: Apple IIc, Laser 128 null modem. If you purchase one that is not a null modem, you'll need to buy an adapter.
  1. DB9 to USB Adapter: There are a ton of these out there, but I bought this: Tera Grand - Premium USB 2.0 to RS232 Serial DB9 Adapter. I suggest buying one with the FTDI chipset, as it has built-in support in macOS and you won't need additional drivers. It is also the most common.
  1. If you have a newer (i.e 2019 or newer) you may also need a USB-A to USB-C adapter, as you probably only have USB-C ports.

Now for the fun part.

On Your Mac

Plug in the USB to DB9 converter, and connect the able to it and the Apple IIc.

Next you need to spawn an instance of getty, which is used for displaying the login prompt. To do this, you'll need to create our own launch daemon

To do so, create a new file named /Library/LaunchDaemons/serialconsole.plist, with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>serialconsole</string>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/libexec/getty</string>
		<string>std.2400</string>
		<string>tty.usbserial-FTCD99Q4</string>
	</array>
	<key>KeepAlive</key>
	<true/>
</dict>
</plist>

Note the first getty parameter, 'std.2400', should be changed to match the baud rate that you choose.

The second parameter is the port to connect to. On my machine, the converter shows up as "tty.usbserial-FTCD99Q4". You can find yours in the /dev directory, and will likely start with tty.usbserial. ls /dev/tty-usbserial* will likely return yours.

Now register the daemon:

launchctl load -F /Library/LaunchDaemons/serialconsole.plist

You'll also need to start and stop it before and after use:

launchctl start serialconsole
launchctl stop serialconsole

If you want to remove the daemon for some reason:

launchctl unload -F /Library/LaunchDaemons/serialconsole.plist

If you're using zsh on macOS (which is now the default shell) and you're using a themeing system like Oh My Zsh, you'll want to make sure that your terminal doesn't use a theme. In addition change the bracketed paste setting (which, if not done, will display [?2004l after the prompt is printed). Lastly, we need to change the terminal type so that special keys (such as backspace) are interpreted properly.

To do so, update the ZSH_THEME section of your .zshrc like so:

if [ "$TERM" = "xterm-256color" ]; then
     ZSH_THEME="powerlevel10k/powerlevel10k"
fi

At the bottom of your .zshrc add the following to disable bracketed paste, and set the terminal type:

if [ "$TERM" != "xterm-256color" ]; then
     export TERM=dumb
     unset zle_bracketed_paste
fi

On Your Apple IIc

On the Apple side of things, you'll want to download the MODEM MGR terminal emulator. There are three disk, Installation, Program, and Utility. You'll at least need the first two. The MODEM MGR Docs are useful too.

Getting the software working on your Apple IIc is an exercise left up to you, dear reader. I have a Floppy EMU which emulates a floppy, and lets you load programs from an SD card making it very easy.

Once you have your disks ready, load up the first one. Configure the video driver (40 or 80 column), choose the non-smart modem and set the port speed. I chose 2400 to make it a bit more old-school so the terminal updates slower. lastly, set the parity, bits and stop bits to N, 8 and 1 respectively. Save the changes.

Now you'll boot from the program disk in the future, ESC Shift-? will bring up the menu. Once you launch it, press ESC : V, and hit enter and you should get a login prompt!

Thanks to the following posts:

Note: Updated to include some .zshrc configurations to fix some things.

Making Cioppino (or "also, maybe this is Cacciucco but either way it's delicious fish stew")

One of my family's favorite dishes is Cioppino. It's an Itanlian seafood stew that originated in San Francisco, and is very similar to Cacciucco. My recipe is somewhere between the two, but I live near San Francisco so I'm going to call it Cioppino. Fight me.

Side note, this was originally Posted on Twitter about a week ago.

Anyway, let’s make Cioppino!

Ingredients

  • 1 onion (anything other than vidalia, they're too sweet), juliened
  • 1 carrot, juliened
  • 2 celery stalks, juliened
  • 2 sprigs fresh thyme
  • 2 bay leaves
  • 1 handful of fresh parsley tops
  • 2 cups red wine (merlot, cabernet, pino noir, anything full flavored.)
  • 4-5 cups of diced roma tomatoes (seeds are fine if you don't want to remove them, you can also leave the skin on, or blanch them if you prefer)
  • 4-8 cups of fish or seafood stock.
  • ½-1 pound of Little neck clams or mussels
  • 1 pound of cod or other fish, shrimp, crab, squid, scallops or any other seafood. More is good too.
  • Sun-dried tomatoes, tomato paste, grape must optional
  • 1 baguette
  • freshly grated paremsan
  • olive oil

Directions

To begin, please note nothing in this recipe needs to be exact. Varying the amounts is totally fine and will of course vary the taste. But I promise it will be tasty.

In a large pot (I use a 4qt stock pot) saute carrots in a couple of tablespoons of olive oil, adding onion and celery after the carrots have begun to soften.

Veggies in the pot

Once the vegetables have softened and onions are somewhat translucent, add the thyme, bay leaves and parsely and saute for a few more minutes until fragrant.

Add the red wine, and cook for 5-10 minutes until it looks delicious like this.

Wine pouring into a pot

Now it's time to add the roma tomatoes.

Tomatoes added to the pot

Cook everything until the tomatoes have softened well.

Everything is cooked and soft

Add the stock - depending on how thick you want the soup to be determines how much stock you add. In this case I added 8 cups, because 4 didn't seem like enough. Then 6 didn't seem like enough.

Seafood stock pouring into the pot

Keep everything on heat, but don't bring it to a boil, just let it simmer.

If you like it thicker, and a bit richer you can add some tomato paste or a can of diced tomatos. Sun-dried tomatoes diced are also good, and grape must (the jar in the pic) adds a ton of richness.

Sun-dried tomatoes, tomato paste and grape must

At this point the smell in your kitchen is going to make you very hungry. It should look something like this.

Let it cook on low. We don't want the flavors to evaporate, we just want everything to break down some more and get oh so tasty. Stir it sometimes.

Now you can leave this covered on low for a couple of hours if you need to - you can make it at lunch time, and then the rest of the dinner comes together pretty quick.

Take your clams (normally I would have clams and mussels but I could only find clams today) and rinse them multiple times under water, and leave them in a post of cold water.

Little neck clams in a pot with water running over them

While those are sitting there thinking about how they got themselves into this mess, get your baguette and slice it on the bias.

A baguette from Sumano's Bakery in it's bagThe baguette, sliced

Now for the fish! I like white flaky rockfish, any type of cod is great. If you can get it, try some mahi mahi or swordfish if you like a denser, meatier fish. I bought this fish at Costco. I'm not using all of it today, geez.

A large quantity of packaged fish

So this time we're going to have the rockfish, scallops and little neck clams. You can add literally any seafood and it will be great. This dish being from San Francscio classically has dungeness crab, but I've somehow never made it with that. All seafood is good seafood though!

Cut the fish and any other seafood into 2" pieces. You want it chunky. You don't want seafood bits. This is a hearty meal! Don't add them right now though, you want to sear/fry the bread first.

Keep in mind cooking times - none of the seafood needs to be in the pot for long, in fact you can add the broth to the dish and put the raw seafood right in the bowl, covering it with the broth of course, and it'll turn out great.

Fish cut into chunks, with scallops and clams in a bowl.

You'll want to pull a skillet out for the clams in a minute. This is all about to come together fast.

Drizzle olive oil on a griddle or cast iron skillet. We're going to stich the baguette slices in it shortly. Heat it up!

Cast iron skillet with olive oil drizzled on it. Maybe too much in some places but it doesn't really matter

Try not to eat all of the bread.

Eric eating bread.

Stick some butter in the other skillet. it likes butter.

Heat that up, and pour some stock in it, or preferrably white wine. I'm using fish stock because I forgot to buy white wine.

Stock pouring in the skillet with butter.

Throw all the bread on the griddle once the oil just starts to smoke.

Bread covering the griddle

Pepper the clam skillet.

Drizzle more olive oil on top of the bread.

We're basically frying the bread in olive oil. Yes it's delicious. You want to keep going until the bottom is nice and brown, then flip them over. I burnt a few, but it's ok. I like burnt ones.

Toasted bread on the griddle. 4 have burnt spots. I apologized to them

Now coat them in freshly grated parmesan cheese. I also added some artichoke bruchetta that we bought. it's tasty. Now toast the top.

Bread in an oven coved in cheese. Everything is good if its covered in cheese.

It's time to toss all the seafood into the pot.

cutting board with seafood in it being poured into a pot.

While those are cooking, let's cook the clams! Cook them on medium high. You can put a cover on it if you like.

Wait until the clams open. If some just don't want to open, they're not good. Throw them out.

Cooked clams in a skillet

So here's how it comes together. Everything in the bowl, go eat!

Two bowls full of cioppino, with the bread on a separate plate all sitting on a wooden cutting board.A closeup of one of the bowls of cioppino

I hope you enjoyed this, I thoroughly enjoy making and eating this dish.

Yosemite is Beautiful (or "How We Were Stupid and Hadn't Visited Yosemite Until Now")

My wife and I went to Yosemite for a 3 day vacation this past weekend and I can't believe we've lived in California for 11 years and hadn't visted yet. It's every adjective that you would guess it is - Majestic. Grand. Awe-Inspiring. Marvelous. Huge. Impressive. Fantastic.

Yosemite Valley as seen from Tunnel View. Canon 6D Mk II 42mm 𝑓/4 1/6000 ISO 100
Yosemite Valley as seen from Tunnel View.
Canon 6D Mk II 42mm 𝑓/4 1/6000 ISO 100

I was pleased to see pretty much everyone wearing masks and being very pandemic-friendly. That's not to say there went a bunch of people -- there absolutely were, but everyone was playing by the rules really well.

This was essentially a first-pass scouting mission. We went on only one hike, a small one, to Lower Yosemite Falls and investigated everything in Yosemite Valley to find out where we'd like to camp, hike, take photos and generally relax on what I can only imagine will be our many visits in the future.

Lower Yosemite Falls with a rainbow. Canon 6D Mk II 35mm 𝑓/8 1/320 ISO 100
Lower Yosemite Falls with a rainbow.
Canon 6D Mk II 35mm 𝑓/8 1/320 ISO 100
More blog posts ➺
More daily links ➺