Tag Archives: Python

Cosmac 1802 Assembler in Python

So back in the day, one of my Cosmac 1802 projects was getting FIG-Forth up and running on the 1802.

I laboriously converted the printed listings to a digital assembler source file. This file was then assembled with a cross-assembler that was written in BASIC.
As part of that effort I also modified the Forth system to run from EPROM.

Since I wanted to get Forth running on the 1802 Membership Card (see earlier blog post), I needed the ability to assemble that source, and do some updates etc.

In the same way it’s been a long time since I’ve had a computer with a parallel port, it’s been a long time since I’ve had a computer with a BASIC interpreter installed.

The obvious next step was to write an assembler in a more modern language. Again Python was my tool of choice.

This is a fairly simple assembler, just sufficient to assemble my ancient FIG-Forth listings. It is not a macro-assembler and I’m sure has other limitations relative to a “real” 1802 assembler.

The source is available here: Cosmac 1802 Assembler

This plays nicely with my 1802 Membership Card Loader. The loader can invoke the assembler automatically when given a source file, allowing you to give one single simple command line that assembles the source and downloads it to the Membership Card.

1802 Membership Card Loader

So I built Lee Hart’s slick little 1802 Membership Card and its Front Panel card. Next I wanted to load some programs onto it! There was that nice DB-25 connector all ready to connect to my PC’s parallel port. However… I’ve got a Mac, and haven’t seen a computer parallel port in perhaps a decade.

My solution to this problem was to create my own interface hardware based on an Arduino. I considered using a Spark Core to allow doing things wirelessly via WiFi, but decided that for this purpose the Arduino was something more people were likely to have, and it was just a somewhat simpler solution.

The final design uses an Arduino, a 16-line I2C port expander chip, and some software. The software consists of the Arduino program and a Python program that runs on my Mac. Since it’s Python, it should also run on a Windows system, a Linux box, etc.
You can also forego the Python side of things and directly control the Arduino loader from a terminal, or from your own software if you prefer.

Why go to all this trouble? Just a fun little project!

It’s been a good mental exercise and a nice trip down memory lane.

Here is the Git repository with the source code and documentation

1802 Loader Documentation

Coming up next – an 1802 Emulator

XCode Build Versions

XCode Build Versions

So, one of the things I found myself wanting to do is automatically bump the version of my application. One good reason to do this is when using the amazing TestFlight to distribute beta builds.

Now, we actually have two “versions” to play with. The first is the actual “Version”, and the second is the “Build”. For my purposes, the Build is what I want to change with each release.

This could be an incrementing number, but I’d really like it to be more useful than that. I use Mercurial as my SCM, so what I decided I wanted was to make the Build “number” be the Mercurial changeset identifier. That way (assuming I’ve done a check in of the changes, as I should) the build number will always be different, and meaningful.

What follows is the result of inspiration gained from looking at solutions found by other developers, in particular from the blogs of Bill Woody and Daniel Jalkut.

Script Summary

This script read the changeset ID from Mercurial and writes it to the app’s plist as the build version.

In addition, this script checks to see if we are doing anything other than a “Debug” configuration build with uncommitted source changes, and if so it generates a build error.
(This feature can be customized or disabled as needed)

Script Details

This script could probably be done as a shell script, and certainly could be done using Perl or Ruby. Since Python is my go-to scripting language, that’s what I used.

First, we use the Mercurial command-line program (hg) to get the changeset ID.

We then check to see if the ID ends in a plus-sign. If it does we look at what build configurations are allowed to be run with uncommitted files. Typically, the Debug configuration is the only one you’d want to do with any changes to the source not checked in. This feature can be configured as needed for your particular build style.

Next, we optionally shorten the build version string. You may want to do this if you want a shorter ID. We could take this fairly lengthy hash and truncate it to wind up with a shorter build version that for all practical purposes would still probably be unique.

The path to the build files is created, and then we use the defaults command to update the build version in the plist.
Note that we do this to the plist after it’s been copied to the build products directory. The “source” plist is not modified by design.

Python Script


#!/usr/bin/python
#
# Obtain the current Mercurial version for the local repository, and write this to the
# build version of the XCode project this script is run from.
# Also can check the build configuration and generate an error if uncommited changes exist
# and (for example) a Release build is being made.
#
# This script expects to be run as a build phase between Link Binary With Libraries and
# Copy Bundle Resources.
#

import os
import os.path
import string
import sys


# Set this to true to cause the IDs to be shortened to "XXXX" or "XXXX+"
shortenID = 0

# Configurations that allow uncommitted changes.
# If a configuration like "Release" is not in this list, the script will generate an error
# if there are changes that haven't been committed when a release build is attempted.
uncommittedAllowed = [ 'Debug' ]
#uncommittedAllowed = [ 'Debug', 'AdHoc', 'Release' ]


fh = os.popen( "/usr/local/bin/hg id -i" )  # Ask Mercurial for the global version ID
buildVer = fh.readline().strip()            # Read it from the process, and strip the newline

if buildVer[-1:] == '+':
    # Plus sign at the end means uncommitted changes

    # Check to see if this should cause a build error.
    config = os.environ['CONFIGURATION']
    if not config in uncommittedAllowed:
        # For this configuration, doing a build with uncommitted changes is an error.
        print "ERROR: Uncommitted changes in the repository while doing %s build!" % config
        sys.exit( 1 )

    # Do we want a shorter ID?
    if shortenID:
        buildVer = buildVer[:2] + buildVer[-3:] # First two chars and the last three chars (plus sign)  
else:
    # Do we want a shorter ID?
    if shortenID:
        buildVer = buildVer[:2] + buildVer[-2:] # First two chars and the last two chars

# Build the path to the Info plist in the build products directory.
infoPath = os.path.join( os.environ['BUILT_PRODUCTS_DIR'], os.environ['WRAPPER_NAME'], "Info" )

print "Setting build version of '%s' to PList %s" % ( buildVer, infoPath )

cmd = "defaults write %s CFBundleVersion %s" % ( infoPath, buildVer )
os.system( cmd )

sys.exit( 0 )   # Success

Installation

This can be embedded in the project, or called from the build phase (as shown in the image).
Regardless, it must be placed in the list of build phases between Link Binary With Libraries and Copy Bundle Resources.

Both ways have their pros and cons. If it’s embedded you can’t “lose” it. If it’s located in a common location and called by all your various XCode projects, it’s easy to fix or modify when necessary.
If it was an integral part of the build, I’d prefer having it embedded, but since it isn’t (the project will build just fine if you take it out of the build phases) I’d rather call it.

This script uses the OSX defaults command, and as of this writing (Sep 2011) the man page for that command warns that it will lose the ability to modify plists in this fashion at some point. When that day comes, I’d much rather fix my script once than edit who knows how many projects.