TRS-80 Model 1 Clone Blog #2
The Character ROM
The TRS-80 Model 1 has a pretty limited graphics and text capability. It only has 16 lines of 64 characters of text and each character is a 5x7 matrix. The character cell is actually 6 pixels wide and 12 pixels tall which means there is quite a lot of space between text lines. For graphics, the Model 1 (and 3 for that matter), use blocks - each character cell is split into two horizontally and three vertically which gives a total of 128x48 "pixels". The pixels are not square, in fact you need two together horizontally to get a square. The picture below shows the standard font including all the graphics characters. It was created by using the BASIC code shown. The memory address for the start of the Video RAM in the TRS-80 Model 1 is 0x3C00 or 15360 in decimal. My real TRS-80 has the lower case conversion with the corrected character ROM (some earlier ones had no descenders at all on the g, j, p, and q characters).
The real TRS-80 Model 1 generates the graphics blocks in specialised circuitry outside the character ROM, however to make my life a lot easier, I am just ignoring that and putting all 256 characters into my Character ROM.
Since I was going to output to VGA, I could choose a resolution - if I used 640x480, then each character horizontally would be 10 pixels, so I could use a 9 pixel wide character with 1 pixel buffer between characters and each character would be 30 pixels tall which means I could have used a 9x12 or 9x13 font for the characters, however I would not be able to reproduce the exact font above. So, I doubled the character width horizontally and tripled it vertically and came up with 768x576 pixels (64x6x2 and 16x12x3). This gives me a way to get the exact font as shown, and as a bonus, I can do a "HiRes" font to use the higher number of pixels. The challenge is that 768x576 is not a common VGA standard (I used TinyVGA's Timing information), so I chose 800x600@60Hz which should be a common resolution that multi-sync monitors can cope with. This means that there is a 16 pixel black border top and bottom and a 12 pixel border on the sides. Here are the screens produced by my Java apps I used to draw the 800x600 screen (with the borders shown in blue) for both Standard and HiRes character fonts and a sample of the character definition file. I used a large text file with 0's and 1's for the font "bits" and the Java apps to draw the screens below and generate the ROM file as well.
This is the font entry for capital A. I have a very long file with all 256 characters in it.
So the ROM needs to be more than 8 bits wide, and even though I only need 12 bits, I need to use a 16 bit wide ROM as there are none that are 12 bits wide. Since there are 36 scan lines in each character, the addressing for the ROM is like this:
ROM address lines:
A13 A12 A11 A10 A09 A08 A07 A06 A05 A04 A03 A02 A01 A00
|---------- RAM Byte ---------| SL5 SL4 SL3 SL2 SL1 SL0
Where the RAM byte is the character from the video RAM and the SLx is the scan line within the character and goes from 0-35 for a total of 36, so there are 28 entries in the Character ROM that are not used per character (scan lines 36-63) and 4 bits per scan line. Overall a bit wasteful, however the ROMs today are a lot cheaper than in the past and I am able to get a 64kx16bit ROM (AT27C1024) for around A$6.50. Since I have an address space that goes to A15, I can now also have more than one font, in fact I can have four of them chosen by A14 and A15, however I only have Standard and HiRes.
I used my TL866II Plus Programmer I bought on AliExpress to program the AT27C1024. It can program over 15,000 different chips and has adapters for the PLCC chips I will be using. The Intel HEX file I created with yet another Java application loaded fine and away we went, however I did not need to spend all the time calculating the checksum at the end of the line as the TL866II software just ignored it. I checked by changing it to an incorrect value and it still loaded fine into the programming software. I was not sure if the HEX file needed to be in big endian or little endian format and I guessed big endian which was luckily correct otherwise I would have wasted a ROM chip as the AT27C1024 is a one time programmable device. My other ROM, which will be used for the BASIC interpreter, is a FLASH chip and can be reprogrammed many times.
Various trademarks held by their respective owners.