In my last post, I described some of the early influences that directed me onto the path of working with electronics for a career. However, I didn’t mention an important piece that caused me to dip my toe into programming as a hobby. Since my job today entails at least equal parts of hardware and software—and since I just got an old copy of a very special book—it’s time to describe my introduction to writing code as well.
When I was seven, we had some Usborne “Introduction” series books covering a variety of different science-y topics, including electronics, physics, and chemistry. I don’t remember how much of the actual content of those books I absorbed, but I clearly remember being enamored with the BASIC code listings that some of them had towards the back, starting with the resistor color code program in the back of the electronics book.
My dad had a ‘286 PC that had GW-BASIC on it, and so with book in hand I began painstakingly transcribing the code listing from the book into the arcane black-and-white editor.
I hadn’t yet developed any typing ability to speak of, so it took a very long time. Regardless, I eventually got it to work, and I was fascinated. My computer did something that I told it to! Not only that, but the program actually translated between numeric resistor values and color codes, which was doubly fascinating since I’d just learned how to do that by hand as well.
The interface is plain, yet functional. The code notes potential color misspellings and prints an error message, which is a nice touch.
After that initial accomplishment, I looked for similar code listings in everything I could find: other Usborne books, introduction to programming books, science books, anything remotely related that I could locate at the library. I didn’t have a good grasp of what the code actually did; I just knew it would probably work if I copied it correctly. Really, that’s not a bad way for a seven-year-old to start out. The slightly deeper understanding began when my dad brought home the beautiful orange QBasic Primer Plus from The Waite Group, complete with all kinds of step-by-step training and the glorious Goki Blaster and fractal generation programs towards the end.
Revisiting the Source Code
I decided to spend a few dollars and get a used copy of the Usborne Introduction to Electronics book from an Amazon seller a couple of weeks ago, and it finally arrived a few days ago. There, in the back of the book right where I remembered it, was the “Colour code computer program” listing, complete with British spelling and everything. Bingo! I transcribed it once more, reliving my first experience without the hunt-and-peck tediousness, and I’ve copied it here for your reading pleasure:
10 GOSUB 490 20 GOSUB 470 30 PRINT "COLOUR CODES HELPER" 40 PRINT:PRINT "A. COLOUR CODES LIST" 50 PRINT "B. VALUE TO COLOURS" 60 PRINT "C. COLOURS TO VALUE" 70 PRINT:PRINT "TYPE IN A,B OR C" 80 INPUT I$ 90 IF I$="A" THEN GOSUB 130 100 IF I$="B" THEN GOSUB 180 110 IF I$="C" THEN GOSUB 320 120 GOTO 20 130 GOSUB 470 140 PRINT "COLOUR CODES ARE :":PRINT 150 FOR I=1 TO 10 160 PRINT TAB(2);C$(I);TAB(14);I-1 170 NEXT I:GOSUB 450:RETURN 180 GOSUB 470 190 PRINT "WHAT VALUE":INPUT V 200 PRINT "WHAT MULTIPLIER":PRINT "M=MEGOHMS" 210 PRINT "K=KILOHMS":PRINT "O=OHMS" 220 INPUT M$ 230 IF M$="M" THEN LET V=V*1E6 240 IF M$="K" THEN LET V=V*1E3 250 LET NZ=0 260 IF V>=100 THEN LET V=V/10:LET NZ=NZ+1:GOTO 260 270 LET V=INT(V):PRINT:PRINT "COLOUR CODING IS" 280 PRINT C$(INT(V/10)+1);" "; 290 PRINT C$((V/10-INT(V/10))*10+1.1);" "; 300 PRINT C$(NZ+1):GOSUB 450 310 RETURN 320 GOSUB 470 330 FOR I=1 TO 3 340 PRINT "TYPE COLOUR ";I:INPUT I$ 350 LET F=0:FOR J=1 TO 10 360 IF I$=C$(J) THEN LET F=1:LET C(I)=J-1 370 NEXT J:IF F=0 THEN PRINT "CHECK SPELLING":GOTO 340 380 NEXT I 390 LET V=(C(2)+10*C(1))*10^C(3):LET M$="" 400 IF V>=1E6 THEN LET V=V/1E6:LET M$="MEG" 410 IF V>=1E3 AND M$<>"MEG" THEN LET V=V/1E3:LET M$="KIL" 420 PRINT:PRINT "VALUE IS ";V;" ";M$;"OHMS" 430 GOSUB 450 440 RETURN 450 PRINT:PRINT "PRESS RETURN TO CONTINUE" 460 INPUT X$:RETURN 470 CLS 480 PRINT:RETURN 490 DIM C$(10):DIM C(3) 500 FOR I=1 TO 10:READ C$(I):NEXT I 510 RETURN 520 DATA "BLACK","BROWN","RED" 530 DATA "ORANGE","YELLOW","GREEN" 540 DATA "BLUE","PURPLE","GREY" 550 DATA "WHITE"
Reading quickly through the code had me scratching my head for a minute trying to work out the flow, since it is full of GOSUB and RETURN and GOTO statements, presented as a single block of 55 numbered lines with no indentation or comments and many lines with multiple statements chained together. Compact? Yes. Functional? Yes. Clear? Not so much. I mean, not that I blame them for omitting comments and indentation from a simple code listing in the back of a science book from 1985. Nevertheless, it’s not hard to follow once you get your head back into old-school mode.
If any readers are so inclined, you can copy and paste this code into PC-BASIC on any modern computer. That’s what I used here, since I no longer have that ‘286 available.
For simplicity, here’s the same code with block comments denoting function-like blocks of code:
---------------------------------------------------------------- Call function LoadData ---------------------------------------------------------------- 10 GOSUB 490 ---------------------------------------------------------------- Def function PrintMenu ---------------------------------------------------------------- 20 GOSUB 470 30 PRINT "COLOUR CODES HELPER" 40 PRINT:PRINT "A. COLOUR CODES LIST" 50 PRINT "B. VALUE TO COLOURS" 60 PRINT "C. COLOURS TO VALUE" 70 PRINT:PRINT "TYPE IN A,B OR C" 80 INPUT I$ 90 IF I$="A" THEN GOSUB 130 100 IF I$="B" THEN GOSUB 180 110 IF I$="C" THEN GOSUB 320 120 GOTO 20 ---------------------------------------------------------------- Def function PrintList ---------------------------------------------------------------- 130 GOSUB 470 140 PRINT "COLOUR CODES ARE :":PRINT 150 FOR I=1 TO 10 160 PRINT TAB(2);C$(I);TAB(14);I-1 170 NEXT I:GOSUB 450:RETURN ---------------------------------------------------------------- Def function ValueToColours ---------------------------------------------------------------- 180 GOSUB 470 190 PRINT "WHAT VALUE":INPUT V 200 PRINT "WHAT MULTIPLIER":PRINT "M=MEGOHMS" 210 PRINT "K=KILOHMS":PRINT "O=OHMS" 220 INPUT M$ 230 IF M$="M" THEN LET V=V*1E6 240 IF M$="K" THEN LET V=V*1E3 250 LET NZ=0 260 IF V>=100 THEN LET V=V/10:LET NZ=NZ+1:GOTO 260 270 LET V=INT(V):PRINT:PRINT "COLOUR CODING IS" 280 PRINT C$(INT(V/10)+1);" "; 290 PRINT C$((V/10-INT(V/10))*10+1.1);" "; 300 PRINT C$(NZ+1):GOSUB 450 310 RETURN ---------------------------------------------------------------- Def function ColoursToValue ---------------------------------------------------------------- 320 GOSUB 470 330 FOR I=1 TO 3 340 PRINT "TYPE COLOUR ";I:INPUT I$ 350 LET F=0:FOR J=1 TO 10 360 IF I$=C$(J) THEN LET F=1:LET C(I)=J-1 370 NEXT J:IF F=0 THEN PRINT "CHECK SPELLING":GOTO 340 380 NEXT I 390 LET V=(C(2)+10*C(1))*10^C(3):LET M$="" 400 IF V>=1E6 THEN LET V=V/1E6:LET M$="MEG" 410 IF V>=1E3 AND M$<>"MEG" THEN LET V=V/1E3:LET M$="KIL" 420 PRINT:PRINT "VALUE IS ";V;" ";M$;"OHMS" 430 GOSUB 450 440 RETURN ---------------------------------------------------------------- Def function WaitReturn ---------------------------------------------------------------- 450 PRINT:PRINT "PRESS RETURN TO CONTINUE" 460 INPUT X$:RETURN ---------------------------------------------------------------- Def function ClearScreen ---------------------------------------------------------------- 470 CLS 480 PRINT:RETURN ---------------------------------------------------------------- Def function LoadData ---------------------------------------------------------------- 490 DIM C$(10):DIM C(3) 500 FOR I=1 TO 10:READ C$(I):NEXT I 510 RETURN ---------------------------------------------------------------- Predefined data block ---------------------------------------------------------------- 520 DATA "BLACK","BROWN","RED" 530 DATA "ORANGE","YELLOW","GREEN" 540 DATA "BLUE","PURPLE","GREY" 550 DATA "WHITE"
The various GOTO and GOSUB statements may look bit foreign, but in short, just remember that GOSUB is a function call that ends with a RETURN statement to bring execution back to the original calling point, while GOTO is just a straight “jump” with no expectation (or ability) to return. With this in mind, you can mentally translate the various GOSUB statements as follows:
- GOSUB 130: “Call PrintList”
- GOSUB 180: “Call ValueToColors”
- GOSUB 320: “Call ColorsToValue”
- GOSUB 450: “Call WaitReturn”
- GOSUB 470: “Call ClearScreen”
- GOSUB 490: “Call LoadData”
The GW-BASIC interpreter parses the entire listing before execution, including those last “DATA” statements at the end. The values declared as DATA elements are available via the READ statement, which is what the (pseudo) subroutine that I’ve labeled “LoadData” does: it creates a 10-element string array called “C$” and then iterates with a FOR loop to load each string value into the corresponding array index.
Once the data is loaded, the program enters the “PrintMenu” routine, where it lives until it is terminated. This routine displays the choices, waits for a single user input, reacts based on the input, and then jumps back to the beginning of the routine (“GOTO 20”) in an infinite loop.
Modernizing the Source Code
Since this code was published over three decades ago, I thought it might be fun to port it over to a more modern language. I chose Python 3 because it’s currently familiar to me and fits with the earlier choice of BASIC for a low-effort interpreted language of convenience.
I’ve chosen to retain the basic structure of the original code despite potential simplifications, just to make the translation more obvious. I even kept the British spelling of “colour” intact.
import os # make Python 2.x compatible try: input = raw_input except NameError: pass colours = [ "BLACK", "BROWN", "RED", "ORANGE", "YELLOW", "GREEN", "BLUE", "PURPLE", "GREY", "WHITE" ] def PrintMenu(): while True: ClearScreen() print("COLOUR CODES HELPER\n") print("A. COLOR CODES LIST") print("B. VALUE TO COLOURS") print("C. COLOURS TO VALUE\n") print("TYPE IN A,B OR C") I = input("? ").upper() if I == "A": PrintList() if I == "B": ValueToColours() if I == "C": ColoursToValue() def PrintList(): ClearScreen() print("COLOUR CODES ARE :\n") for i, colour in enumerate(colours): print(" %s\t %d" % (colour, i)) WaitReturn() def ValueToColours(): ClearScreen() print("WHAT VALUE") V = float(input("? ")) print("WHAT MULTIPLIER") print("M=MEGOHMS") print("K=KILOHMS") print("O=OHMS") M = input("? ").upper() if M == "M": V *= 1e6 if M == "K": V *= 1e3 NZ = 0 while V >= 100: V /= 10 NZ += 1 V = int(V) print("\nCOLOUR CODING IS") print("%s %s %s" % ( colours[int(V/10)], colours[V - (int(V/10) * 10)], colours[NZ] )) WaitReturn() def ColoursToValue(): ClearScreen() I = 1 C = [] while I <= 3: print("TYPE COLOUR %d" % I) colourStr = input("? ").upper() if colourStr in colours: C.append(colours.index(colourStr)) I += 1 else: print("CHECK SPELLING") V = (C[1] + 10 * C[0]) * pow(10, C[2]) M = "" if V >= 1e6: V /= 1e6 M = "MEG" if V >= 1e3: V /= 1e3 M = "KIL" print("\nVALUE IS %s %sOHMS" % (("%f" % V).rstrip("0."), M)) WaitReturn() def WaitReturn(): print("\nPRESS RETURN TO CONTINUE") input("? ") def ClearScreen(): os.system('cls' if os.name == 'nt' else 'clear') print("\n") # enter the menu loop (Ctrl+C to quit) PrintMenu()
I used Python’s convenient str.upper()
function to make the menu selection, color entry, and multiplier entry inputs case-insensitive, which is a minor improvement on the original code. I also threw in some extra spaces around the resistor value to imitate GW-BASIC’s idiosyncratic habit of forcing numbers to be surrounded by spaces in PRINT
statements. And since Python uses the carat (‘^
‘) character as an XOR operator, I had to swap that out for the built-in pow()
function. Finally, I threw in that input
/raw_input
bit at the top to allow this code to run in either Python 2.x or 3.x without issues. Otherwise, the structure and functionality of this fun little program have remained unchanged.
While I’m always excited to learn new things and take advantage of the phenomenal advancements in the world of programming and related hardware, I also enjoy exploring relatively ancient history (in the tech sense) every now and then—especially this particularly formative part of my own journey. Maybe I’ll dig into Goki Blaster or the fractal generator next time…
1 comment
Great piece of work translating the basic to Python. I would love to see the same done for all the other Usborne books with Basic code projects in them. Someone should start a group!