PK-232 Checkout & Alignment

I acquired an old AEA PK-232MBX controller for amateur radio digital communication. I already have a more modern Raspberry Pi running Direwolf, but the prospect of creating a 1980s/1990s vintage station with an Apple II is irrationally appealing. The opportunity to combine two hobbies, amateur radio and retro computing, is interesting.

I purchased my PK-232 untested from eBay. While it appears in good physical condition, I started with the loopback test from section 2.5 of the manual. After passing that, I moved on to the alignment procedure in Chapter 6 of the service manual. Although written for a slightly older PK-232 revision, the alignment procedure remains applicable. The alignment procedure is mostly straightforward, but I found two points confusing.

First, the procedure references the R160/C59 junction test point. The silk screen label for R160 is underneath the resistor and impossible to read. The scanned service manual does contain the board layout identifying components, but that diagram is out-of-order in the scan. The diagram is actually stuck in “Appendix D – Waveforms”. Of course, I found that after locating the test point through trial and error.

PK-232MBX circuit board, showing oscilloscope probe connected to R160/C59 junction

Second, the “AFSK null adjustment” (Step 12 in Section 6.2.1) didn’t make sense. No matter the adjustment, I observed no change in the signal. The procedure made a bit more sense after reading the Heathkit HK-232 user manual. The HK-232 is essentially a kit version of the PK-232, so design and operation is identical. To complete this adjustment, exit “CAL” mode with the “Q” command. With the oscilloscope connected to the R160/C59 junction, adjust the oscilloscope vertical scale to show the noise. Then adjust R157 to minimize the amplitude of the noise. The range of adjustment is very small and changes in the noise amplitude are barely noticeable. R157 sets the “tone generator off” output level.

Receiving packets!

In the end, the PK-232 works, and I’m able to transmit and receive packets. Unfortunately, there isn’t much packet activity nearby, and I’m unsure what’s next for the unit. I’m not done with packet yet, and I look forward to trying a better VHF/UHF antenna and HF operation.

Forgotten Software: Yet Another Star Trek

I’m pleased to share yet another “Star Trek” themed game.  I wrote this during middle school as part of a book report.  Game play is terrible and amounts to firing weapons repeatedly with no strategy, but I was proud of it at the time. I wrote most of the game in BASIC with a machine language sound routine from Nibble magazine.

There’s a bug where the title on startup appears incorrect if you haven’t enabled the 80-column firmware.  I’m preserving the original bug to avoid rewriting history.  You’ll need a 128KB machine and only use upper-case commands.

My “book report”

Forgotten Software: My Summer Reading Log

I’m pleased to share “My Summer Reading Log” by Georgiann Flowers, my 3rd grade teacher at Woodland Elementary School.  To the best of my knowledge, she never published this software outside her classroom, and nobody has archived it online.  This BASIC software for the Apple II tracks a student’s summer reading progress, including titles and page counts.  There’s also a nice splash screen animation.

Mirrored on

Programming the F18A: Tiles

In the first part of this series, we learned how to program the F18A using the AmpArcade library.  We looked at loading the library, initializing the video hardware, and changing the backdrop color.  While a good first step, that’s hardly interesting.  In this part, we program the tile layer.  The tile layer is versatile and useful for many applications, such as text and game backgrounds.

Get a disk image here with AmpArcade and several tile layers examples.


First, we must detour and understand more about how the F18A and the original VDP organize the video screen.

The VDP divides the video screen into layers or planes.  The software may modify each layer independently, and the hardware combines the layers to produce the final on-screen image.  This concept is similar to layers in Photoshop or Gimp, and the design makes common animation simple.  The background and various objects, such as a space ship or asteroid image, reside on separate layers, and the software may move objects around without needing to save/restore the background or overlapping objects.  The layers have an ordering so that a higher layer will obscure a lower layer.

VDP layers diagram from the "Video Display Processor Programmer's Guide"

VDP layers diagram from the “Video Display Processor Programmer’s Guide”

The VDP provides these layers:

  1. Background layer – A solid color that appears only when the higher layers don’t block it
  2. Tile layer (also known as the “pattern layer”) – Small images arranged in a grid useful for text (if each image is a character) or a background
  3. Sprite layers (32) – Small animated objects, such as game characters, that move independently over the tile layer

The F18A extends the original TMS9918A with more layers:

  1. Backdrop layer
  2. Tile layer 1
  3. Tile layer 2 – Another tile layer useful for parallax effects or fixed elements, such as score information
  4. Bitmap layer – A bitmapped image that optionally appears above or below the sprite layer
  5. Sprite layers (32)

The F18A also introduces additional capabilities to the layers, including more colors, scrolling, and more capable sprites.  For this discussion, we limit ourselves to the capabilities of the original VDP since AmpArcade does not support the expanded capabilities of the F18A.

The Tile Layer

The tile layer, sometimes also known as the pattern layer, divides the screen into a rectangular grid.  Each grid square, called a tile, contains a pattern of pixels.  In Graphics Mode I (GM1), the grid of tiles has 32 columns and 24 rows, and each tile may contain one of 256 different 8×8 pixel patterns.  Other modes are slightly different, and this post only describes GM1.  This “Programmer’s Guide” from Texas Instruments details each video mode.

If the patterns look like letters and numbers, the tile layer is perfect for displaying text.  Unlike the Apple II text mode where the available characters are factory-determined in ROM, the character set for the tile layer is up to the programmer.  Want a different font?  Want bold or italic? Foreign language characters?  Symbols?  Emojis?  Line-drawing characters like MouseText?  No problem.  You may design your own characters.

However, patterns do not need to be recognizable characters.  The patterns could be elements of a game background or graphic.  You may subdivide complex graphics into multiple patterns. For example, if you want a letter that is double-high, you may create two patterns, one with the top of the letter and another with the bottom.  Or, if you need a gun turret for a game, you may subdivide the turret image into as many patterns as needed.  Don’t underestimate this capability; look at many excellent games, and you’ll notice backgrounds with repeating tiles.

Internally, the VDP uses three tables to define the contents of the tile layer.  The “pattern table” describes up to 256 reusable 8×8 patterns.  The “color table” describes the colors of the patterns.  The color table only allows two different colors for every eight patterns, and the table contains 32 bytes (256 patterns divided by 8, with two colors packed into one byte).  The “name table” describes the pattern visible in each tile, and the table consists of 768 bytes (32 columns times 24 rows).  The table sizes vary with graphics mode, and these numbers only apply to GM1; however, the basic table structure applies to all modes.

Let’s try programming the tile layer.  Refer to my first part to load AmpArcade, then initialize GM1:

REM Initialize Graphics Mode I, memory layout variant A. 

aNext, define a tile pattern with the DTIL command.  DTIL requires 9 numbers.  The first number is the pattern number from 0 to 255.  The next eight numbers each range from 0 to 255 and define the pattern of pixels for one row each, beginning with the top-most row.  In this example, let’s define pattern #65 as the letter “A”:


DTIL only defines the patterns, and an additional command is necessary to set a tile to a pattern.  Typically, the programmer defines all of the patterns once and sets tiles to patterns with the STIL command throughout the program.  STIL requires 3 numbers.  The first number is the column (0-31 for Graphics Mode 1).  The second number is the row (0-23).  The final number in the pattern:


If you’re following along, you might see the letter “A” (pattern 65) in column 10, row 20.  I say “might” because we have not specified the colors.  If, by chance, the color table chooses identical foreground and background colors for this pattern, you won’t be able to see the pattern.

To set the color, use the CSET (color set) command.  This command requires two numbers.  The first number is the color group from 0 to 31.  Recall that you may only set the color for a group of 8 patterns.  To find the color group for a pattern, divide the pattern number by 8 and discard the remainder.  For our example above using pattern 65, the color group is 8 (65/8 = 8, discarding the remainder).  The second number defines the foreground and background colors for the pattern.  Multiply the foreground color by 16 and add the background color to calculate the CSET color number.  The following example sets pattern group 8 to foreground color 11 (light yellow) and background color 8 (medium red).


In addition to the STIL command that sets one tile, AmpArcade provides useful commands for setting multiple tiles:

REM Beginning in column 5 and row 10, set a horizontal row of tiles to patterns 65 and 65.
REM &HTIL,<X>,<Y>,<N1>{,<N?>}

REM Beginning in column 15 and row 15, set a horizontal row of 10 tiles all to pattern 65.
REM &HROW,<X>,<Y>,<N>,<REP>

REM Beginning in column 20 and row 22, set a vertical column of tiles to patterns 65 and 65.
REM &VTIL,<X>,<Y>,<N1>{,<N?>}

REM Beginning in column 2 and row 5, set a vertical column of 15 tiles all to pattern 65.
REM &VCOL,<X>,<Y>,<N>,<REP>

REM Fill the entire tile layer with pattern 65.

Loading Patterns

You may define all 256 patterns with 256 separate DTIL commands, but that gets really tedious really fast.  It’s possible to store multiple patterns in a single binary file on disk and transfer the data to the VDP.  Let’s say you have a file CHAR with patterns for a basic set of letters, numbers, and punctuation.  Each pattern is 8 bytes, and the patterns are in order with the first 8 bytes representing pattern 0, the second 8 bytes representing pattern 1, and so on.

This approach employs a new command, LD, to load data into the VDP’s memory.  To use LD, you must know something about the layout of the VDP’s memory (VRAM), a topic we’ve avoided so far.  The memory layout is configurable and changes with both video mode and configuration details.  The GM1A command gives the following memory layout for the tile layer:

  • Name Table: addresses 1024 ($400) to 1791 ($6FF)
  • Color Table: addresses 1920 ($780) to 1951 ($79F)
  • Pattern Table: 2048 ($800) to 4095 ($FFF)

The LD command requires 3 numbers. The first is the source address in the Apple II’s memory. The second is the destination address in the VDP’s memory. The third is the length of the data in bytes.

REM Load the tile layer patterns from disk into the Apple II's memory at address 8192.	 	 
REM A complete set of patterns requires 2 KB of memory, but you don't need to define every pattern.
REM The "CHAR" file is only 832 bytes long, which defines 104 patterns (832 bytes/8 bytes per pattern). 	 
REM We could use any available memory location on the Apple II.	 	 
REM Copy data for 104 patterns (8 bytes each) to VDP memory address 2048, which contains the pattern table.	 	 

REM Display all patterns.
REM First, set the pattern group colors to a blue foreground and a gray background. 	 
FOR I=0 TO 31 : &CSET,I,4*16+14 : NEXT I 	
REM Next, show each pattern on screen.  
REM Note that CHAR only contains 104 patterns, so some patterns will be whatever garbage was already in VRAM.
FOR Y=0 TO 23 : FOR X=0 TO 31 : &STIL,X,Y,Y*32+X : NEXT X,Y

What’s next?

Try writing a program that uses the CHAR patterns and displays a sentence on the screen. Then, use DTIL to define a new pattern that resembles the Apple logo and draw a red border of Apples around your message.  This bootable disk image contains everything you need, including the CHAR file.

In the next part, we’ll look at modern tools to help us create new patterns and tile layouts.

Programming the F18A: Getting Started

This is the first part of my tutorial on programming the F18A installed in an Apple II.  I cover installing the card and finding software.  Future parts will cover more interesting topics, such as the tile layer, sprites, and F18A-specific features.

Throughout, I’ll use VDP (Video Display Processor) to refer to the original TMS9918A, F18A to refer to the modern FPGA recreation of the VDP, and AppleTi to refer to the Apple II card holding the F18A.  Sometimes, I use AppleTi and F18A interchangeably since you cannot have one without the other in an Apple II.

For background, I recommend my AppleTi and F18A at KansasFest post.

Installing the AppleTi Hardware

I assume you’ve assembled your AppleTi card and are ready to make it do something interesting.  You may install it in any slot.  Unlike the vintage Synetix SuperSprite or Third Millennium Engineering Arcade Board, the AppleTi does not support combining Apple II video and sprite card video on one monitor.  Therefore, the AppleTi does not need any additional connections or have slot restrictions.  Obviously, you need a separate VGA monitor for the AppleTi.  If you have an Apple IIgs, be sure to set the slot to “Your Card” in the control panel.

Double-check the orientation of the card.  The component-side of the AppleTi should face the power supply, and the card has an arrow clearly indicating the correct orientation.  If you get the card, F18A, or 7400 IC backwards, you’ll likely be stuck repairing your computer instead of playing with graphics.

Getting the Software

I recommend the AmpArcade software originally distributed with the Arcade Board.  This software provides a convenient “ampersand vector” interface for programming the AppleTi with Applesoft BASIC.  Graphics and fast animation are usually challenging in BASIC, but the AppleTi does not share these challenges due to unique hardware features.

AmpArcade works with DOS 3.3, but I prefer ProDOS.  Specifically, AmpArcade’s memory usage conflicts with ProDOS BASIC.SYSTEM buffers.  At first, AmpArcade appears to work, but you’ll soon notice ProDOS commands failing and strange crashes.  Fortunately, this is straightforward to fix: BASIC.SYSTEM provides a GETBUFR programming interface for reserving memory in exactly the address range that AmpAracde requires.  Here’s a short program that loads AmpArcade under ProDOS:

 10  REM   Amparcade is not ProDOS compatible because it overwrites the BASIC.SYSTEM buffers.
 20  REM   This loader modifies Amparcade to function under ProDOS/BASIC.SYSTEM.
 100  REM  Step 1: Reserve memory from $8800-$9975 via a GETBUFR call to BASIC.SYSTEM.
 110  DATA  165, 14, 32, 245, 190, 96
 120  FOR I = 0 TO 5: READ N: POKE 768 + I,N: NEXT I: CALL 768
 200  REM  Step 2: Load Amparcade and remove inbuilt adjustment of HIMEM.  GETBUFR already did this.
 220  POKE 34832,234: POKE 34833,234
 230  POKE 34836,234: POKE 34837,234
 300  REM  Step 3: Run Amparcade.
 310  CALL 34816

Download my disk image containing AmpArcade, ProDOS, and the above loader here.  After running this loader, you should see a copyright message from Third Millennium Engineering and a few garbage characters on your AppleTi video output.  The garbage is the result of AmpArcade trying to initialize sound and video switch hardware missing on the AppleTi, and you may ignore the garbage characters.  AmpArcade scans all slots and will find the AppleTi in any slot.

Look at all the Pretty Colors

AmpArcade adds “ampersand vector” commands to BASIC.  These are commands that begin with “&” and allow you to communicate with the AppleTi card.

After loading AmpArcade, we must choose a video mode and initialize the F18A.  We have several choices:

  • 40-Column Text Mode (TXT1)
  • Multi-Color Mode (MCM) – This mode is similar to Apple II lo-res graphics.
  • Graphics Mode I (GM1) – This is the most commonly used mode.
  • Graphics Mode II (GM2) – This mode extends GM1 with more flexibility in the pattern/tile layer; however, this mode is also more difficult to program.
  • 80-Column Text Mode (TXT2) – This mode is unique to the F18A and not present on the VDP.

The modes have advantages and disadvantages, but most software uses Graphics Mode I (GM1).  GM1 offers a good compromise on features and ease of use, so we’ll start with this mode.

The F18A, like the VDP, has dedicated video memory that’s separate from the Apple II memory, and the hardware offers a lot of flexibility with memory layout and usage.  AmpArcade provides four possible memory layouts for GM1, labelled A, B, C, and D.  Memory layout matters for advanced uses, but they don’t matter for our application.  We’ll arbitrarily choose layout A:

REM Initialize Graphics Mode I, memory layout variant A.

Next, we’ll set the backdrop color, which is the color that appears behind everything else we draw.


The integer (13) selects a color from among 15 possible choices:

# Color Sample
0 Transparent (the absence of color) (transparent)
1 Black
2 Medium green
3 Light green
4 Dark blue
5 Light blue
6 Dark red
7 Cyan
8 Medium red
9 Light red
10 Dark yellow
11 Light yellow
12 Dark green
13 Magenta
14 Gray
15 White

So, we can create a simple program that cycles through the available colors:

FOR C=1 TO 15 : &BCOL,C : NEXT C

Notice how fast the colors change.  Try modifying the code to wait for a key press before advancing to the next color.

This is it for part 1.  We’ve figured out how to initialize the AppleTi and show pretty backdrop colors.  Next, we’ll investigate the pattern layer, also known as the tile layer.  This capability allows us to display text and is the heart of backgrounds in most games.

AppleTi and F18A at KansasFest

Years ago, I outlined interfacing the F18A, a TMS9918A Video Display Processor (VDP) clone with VGA output, to the Apple II.  I never followed through, but somebody on the AtariAge forum recently completed a design and released a PCB.  The “AppleTi” board is a functional clone of the E-Z Color Graphics Interface.  The AppleTi board only supports the F18A, not the original TM9918A, and is the simplest interface possible with only a single 74LS00 NAND package generating read/write control signals.

The VDP interfaces to the 6502 via two memory-mapped byte-sized registers selected with the MODE pin.  The AppleTi interface connects MODE to the Apple’s A0 address signal.  Combined with the “DEVICE SELECT” decoding on the Apple II motherboard, this design shadows the VDP registers across the 16 byte slot-specific address space ($C0n0 – $C0nF where n is the slot number plus 8).

The practical consequence is that the AppleTi is mostly-kind-of-sort-of compatible with software written for the Synetix SuperSprite and Third Millennium Engineering Arcade Board.  I say “mostly-kind-of-sort-of” because code that accesses the VDP is compatible but code that expects sound or video switch hardware won’t work.  Most of the sample code from Synetix and Third Millennium won’t work.  For the software that does work, there is minor VDP screen corruption from sound and video switch initialization attempts.  However, despite these limitations, the AMPARCADE library from Third Millennium and the StarSprite library from Synetix do function well enough to be useful with the AppleTi/F18A board.

At KansasFest 2016, I shared an introduction to the VDP, AppleTi, and programming the board with the AMPARCADE library.

Over the next month, I hope to create a series of posts with a tutorial introduction to VDP programming.

ImageWriter II: Essential hardware for every system

NOS ImageWriter II ribbon: The rubber roller has turned to sticky goo.

NOS ImageWriter II ribbon: The rubber roller has turned to sticky goo.

Back when my Apple IIc+ was my only computer, I really wanted an ImageWriter II printer.  This was “the” printer to own.  It was reasonably fast, compatible with nearly all Apple II software, and printed in glorious color.  Unfortunately, I was a kid with no job, and an ImageWriter II cost over $500.  Needless to say, I never owned the printer back then.

More than 20 years later, I finally own an ImageWriter II.  Thanks to Sean’s Garage Giveaway at KansasFest a few years ago, I walked away with a nice condition printer, a stack of NOS color ribbons, and a used black ribbon.  The color ribbons, despite being never used and sealed in plastic, were dead due to age.  An orange rubber roller internal to the ribbon cartridge had turned to some sort of nasty goo.  Every “new” ribbon I’d gathered suffered the same failure.  I was rather unhappy and shoved everything in a box for another day.  I saved the pieces of the cartridge hoping someday to rebuild it, but I have yet to open the bag and release orange goo across my desk.

A few months ago, a fellow in the Facebook Apple II Enthusiasts group reported that he had contracted with an overseas manufacturer for a small run of new color ImageWriter II ribbons.  A few dollars and a short while later, I’m finally printing in glorious color with the unmistakable “dot matrix buzz” audible at the far end of the house.  I created a card and flyer with Print Shop GS, although the recipient doesn’t properly appreciate the origins.

It’s a small and simple accomplishment, but there’s something satisfying about a working ImageWriter II.  Sure, I love fancy hardware like mass storage and accelerators, but I neither expected to own those “back then” nor knew anybody who owned those.  The lowly printer was the item that everybody seemed to own and was the missing piece in my idea of a “complete” system.


ImageWriter II: It prints in glorious color and is audible across the house. No system is complete without one.