An 8085 Single Board Computer – Contents

By Johnny Quest

All posts in ascending order.

1: An introduction to the OMEN Alpha 8085 Single Board Computer
2: Waiting for the arrival of the OMEN Alpha PCB
3: PCB Arrival and Assembling of the OMEN Alpha
4: OMEN Alpha; first signs of intelligence?
5: Testing the MON85 firmware on the OMEN Alpha
6: Updates to Palo Alto TinyBASIC
7: How to use the OMEN Alpha and MON85 to test and debug programs
8: I found IMSAI 8K Floating-point BASIC … and it works on the Alpha!

I found IMSAI 8K Floating-point BASIC … and it works on the Alpha!

In a prior post, I wrote about the effort to modify Palo Alto TinyBASIC to run on the OMEN Alpha. In this post, I’m going to write about the IMSAI 8K Floating-point BASIC that was written for the IMSAI 8080 microcomputer.

In my search for various “vintage” software for the 8080/8085, I ran across across the IMSAI 8K Floating-point BASIC. Unlike the “4K” version, which is written in Z-80 assembly code, the “8K” version is written in 8080 assembly code. Unlike the Palo Alto TinyBASIC, which is a 16-bit signed-integer BASIC, the IMSAI BASIC is a floating-point BASIC.

With a little effort and using the default memory locations, I was able to assemble the IMSAI 8K BASIC without any errors using Bruce Tomlin’s ASMX assembler.

However, IMSAI 8K BASIC is meant to run under CP/M but can be used anywhere in ROM or RAM. If using in ROM, the starting address can be 0x0000 with the 1st page containing the interrupt vectors or if the starting address is not 0x0000, as in the case for the OMEN Alpha, then the RST vectors need to be re-coded to use CALLs. If using under CP/M, the starting address is 0x0100 and the 1st page is reserved for interrupt vectors (if any are used). As is typical with 8080/8085/Z80 programs of that era, use of the RST instructions to save code space applies here.  In particular, I had to add conditional assembly statements to use “CALL RSTx” instructions to replace “RSTx” instructions, where the call to RSTx is the RSTx vector’s code. All seemed to be functional but then I noticed BASIC hanging on certain errors. It turns out that I had missed the embedded RST6 opcode (0xF7) in the fatal error message string table (located at the ULERR label). Once that was corrected, I didn’t find any other issues.

I will add that I used the same method to debug the code in RAM using MON85 as was posted here.

In the 32KB ROM build, IMSAI BASIC starts at address 0x1C00, with BASIC variables and program storage starting at 0xA000 and ending at 0xF800, which leaves 22K bytes available for programs.

Be warned though, IMSAI Floating-point BASIC is about 3 times slower than Palo Alto TinyBASIC but it has the advantage of being able to perform floating-point calculations if you need them. [ 2019-0223: Thank you to Wolfgang Endler for his find; IMSAI 8K BASIC inserts 133 RUBOUT characters and a delay after every CR/LF combination, presumably for use with paper-tape machines. In the updated source code, I disabled the “insert RUBOUT” and CR/LF delay routine with a conditional assembly statement, which gains back some speed while printing to the console. BTW: Wolfgang has IMSAI 8K BASIC running on his MINIMAX8085. ]

The odd thing about IMSAI Floating-point BASIC is that there are no logical functions available (i.e. AND, OR, XOR, etc.), which makes porting programs written for MS-BASIC (BASIC-80) a bit of a problem because statements like “IF B<3 AND B>6 THEN 9999″ don’t work and need to be broken apart.

The screen capture below shows a simple sine wave plot using IMSAI 8K BASIC.

IMSAI_8K_BASIC-SinePlot
Simple sine plot using IMSAI 8K BASIC

The original project files (2018-1112), including the IMSAI 8K BASIC are here: OMEN_Alpha_Files-1V0-JQ.zip.

The updated project files (2019-0223) are here: OMEN_Alpha_Files-1V0a-JQ.zip. The update consists of the speedup to IMSAI 8K BASIC as well as improving the build scripts for Linux to automate the 3.6864MHz and 4.9152MHz master clock builds.

Enjoy and have fun!

Peace and blessings.

How to use the OMEN Alpha and MON85 to test and debug programs

In the prior post, I showed the method used to modify and debug new features added to TinyBASIC using the OMEN Alpha 8085SBC and MON85.

In this post, I’ll expand on that method and illustrate how to test and debug interrupt-driven code. In this example, a program that uses the RST7.5 hardware interrupt will be assembled and tested in RAM.

Why use the RST7.5 input?: Because the Alpha makes the RST7.5 input available on the 24-pin header, so it is easily accessed. There is also a 2-pin BERG-STIK header (JP7) that should normally have a shorting bar across it’s pins to keep the RST7.5 input “grounded”, so no false interrupts occur.

In this example, the simple program will increment a counter (using register A) between “0” and “255”  with each low-to-high pulse of the RST7.5 input. If a 5 volt square wave generator is available, it can be used to drive the RST7.5 input at a frequency of say 10 Hz. In effect, we’re using the frequency generator to clock a counter with the RST7.5 restart (interrupt) input at 10 interrupts per second.

AS8085’s assembly listing for the sample program follows:

ASxxxx Assembler V05.20  (Intel 8085)                                   Page 1
Hexadecimal [16-Bits]     

                              1 ;
                              2 ;
                     8000     3 RAM		.EQU	 0x8000
                              4 		;
                              5 		;*****************************************************
                              6 		; Interrupt vectors
                              7 		;
                     8000     8 RST0		.EQU	RAM + 0x00	; Software interrupt
                     8008     9 RST1		.EQU	RAM + 0x08	; Software interrupt
                     8010    10 RST2		.EQU	RAM + 0x10	; Software interrupt
                     8018    11 RST3		.EQU	RAM + 0x18	; Software interrupt
                     8020    12 RST4		.EQU	RAM + 0x20	; Software interrupt
                     8024    13 TRAP		.EQU	RAM + 0x24	; Hardware interrupt
                     8028    14 RST5		.EQU	RAM + 0x28	; Software interrupt
                     802C    15 RST55		.EQU	RAM + 0x2C	; Hardware interrupt
                     8030    16 RST6		.EQU	RAM + 0x30	; Software interrupt
                     8034    17 RST65		.EQU	RAM + 0x34	; Hardware interrupt
                     8038    18 RST7		.EQU	RAM + 0x38	; Software interrupt
                     803C    19 RST75		.EQU	RAM + 0x3C	; Hardware interrupt
                     8040    20 PROGRAM		.EQU	RAM + 0x40	; 1st address after vector table
                             21 		;
                             22 		;Startup code... Kick off the monitor
                             23 		;
                             24 		.area	_CODE (ABS)
   8000                      25 		.ORG	RST0		; Hardware RESET vector
   8000 C3 40 80      [10]   26 		JMP		MAIN
                             27 		;
                             28 		;*****************************************************
                             29 		;Interrupt handlers for RESTART interrupts
                             30 		;
   8008                      31 		.ORG	RST1
   8008 C3 3F 80      [18]   32 		JMP	RSTINT 		;Invoke interrupt
                             33 
   8010                      34 		.ORG	RST2
   8010 C3 3F 80      [18]   35 		JMP	RSTINT 		;Invoke interrupt
                             36 
   8018                      37 		.ORG	RST3
   8018 C3 3F 80      [18]   38 		JMP	RSTINT 		;Invoke interrupt
                             39 
   8020                      40 		.ORG	RST4
   8020 C3 3F 80      [18]   41 		JMP	RSTINT 		;Invoke interrupt
                             42 
   8024                      43 		.ORG	TRAP
   8024 C3 3F 80      [18]   44 		JMP	RSTINT 		;Invoke hardware interrupt
                             45 
   8028                      46 		.ORG	RST5
   8028 C3 3F 80      [18]   47 		JMP	RSTINT 		;Invoke interrupt
                             48 
   802C                      49 		.ORG	RST55
   802C C3 3F 80      [18]   50 		JMP	RSTINT 		;Invoke hardware interrupt
                             51 
   8030                      52 		.ORG	RST6
   8030 C3 3F 80      [18]   53 		JMP	RSTINT 		;Invoke interrupt
                             54 
   8034                      55 		.ORG	RST65
   8034 C3 3F 80      [18]   56 		JMP	RSTINT 		;Invoke hardware interrupt
                             57 
   8038                      58 		.ORG	RST7
   8038 C3 3F 80      [18]   59 		JMP	RSTINT 		;Invoke interrupt
                             60 
   803C                      61 		.ORG	RST75
   803C C3 59 80      [18]   62 		JMP	RST75ISR	;Invoke hardware interrupt
                             63 		;
   803F C9            [10]   64 RSTINT:		RET			;Return to caller
                             65 
                             66 ;
                             67 ; Start of Code
                             68 ;
                             69 
   8040                      70 		.ORG	PROGRAM		; start of program
   8040 3E 80         [ 7]   71 MAIN:		MVI	A,0x80		;initialize 8255, all outputs
   8042 D3 03         [10]   72 		OUT	0x03
                             73 
   8044 3E 0B         [ 7]   74 		MVI	A,0b0001011	;enable RST7.5, disable RST6.5 and RST5.5
   8046 30            [ 4]   75 		SIM			;set the mask bits
                             76 
   8047 3E 00         [ 7]   77 		MVI	A,0		;clear A
                             78 
   8049 01 FF FF      [10]   79 		LXI	B,0xFFFF	;initialize BC as delay counter
   804C FB            [ 4]   80 		EI			;Enable interrupts
                             81 
   804D 00            [ 4]   82 MAIN1:		NOP			;waste some time
   804E 0D            [ 4]   83 		DCR	C		;decrement low-byte
   804F C2 4D 80      [10]   84 		JNZ	MAIN1		;loop till zero
   8052 05            [ 4]   85 		DCR	B		;decrement high byte
   8053 C2 4D 80      [10]   86 		JNZ	MAIN1		;loop till zero
   8056 C3 4D 80      [10]   87 		JMP	MAIN1		;continue looping
                             88 	;
                             89 	; RST7.5 ISR
   8059 D3 00         [10]   90 RST75ISR:	OUT	0x00		;ACC -> PORTA
   805B 3C            [ 4]   91 		INR	A		;increment counter
   805C FB            [ 4]   92 		EI			;Restore interrupts
   805D C9            [10]   93 		RET

How does the sample program work?:

  • Line 3 sets the destination address of the program.
  • Lines 8 to 20 define the addresses of the vector table. Normally, they are located from 0x0000 to 0x003C but since MON85 allows us to define (and use) our own vector table, we define it here, so the RST7.5 interrupt will vector and transfer control  to our program in RAM.
  • Line 26 is the beginning of the program but jumps to the routine “MAIN:” (at line 71) when a “G 8000” command is issued to MON85.
  • Lines 31 to 62 create the vector table at the specific addresses in RAM.
  • Line 64 creates a “return” to the location left on the stack, which is the address of the last instruction executed BEFORE the “restart” (interrupt) was invoked. Other than the RST7.5 interrupt, all other vectors will jump to this address, execute the RET instruction and resume to previous program execution.
  • Line 71 is the beginning of the main program loop.
  • Lines 71 and 72 initialize the 8255 for all outputs on the ports.
  • Lines 74 and 75 set the RST7.5 interrupt mask.
  • Line 77 clears the A register (the counter) to “0”.
  • Line 79 initializes the BC register pair, a 16-bit counter use to waste CPU cycles.
  • Line 80 enables hardware interrupt RST7.5 to be responded to.
  • Line 82 to 87 comprise a simple 16-bit counter that continually decrements and thereby wastes CPU cycles while awaiting RST7.5 interrupts from the frequency generator..
  • Lines 90 to 93 comprise the the interrupt service vector for the RST7.5 interrupt.
  • Line 90 outputs the value of the A register to the 8255’s PORT A, which have single LED’s attached to each port pin as a visual indicator).
  • Line 91 increments the A register, the counter that is displayed on the LED’s
  • Line 92 re-enables interrupts before returning
  • Line 93 returns to resume program execution (somewhere in lines 82 to 87)

How do I test and debug this program?: After successfully assembling the sample program, use MON85’s “load” command to upload the resulting HEX file (be sure to upload the HEX file using your terminal emulator). If you used 0x8000 as the starting address, as this program does, then the program should be loaded into RAM at address 0x8000. Use MON85’s “memory dump” (“M 8000”) command to verify it’s existence. Note: I find it helpful to clear RAM in the area that I am going to work in, so I can find my program code easier. Use the “M 8000 9000 00” command to clear RAM from 0x8000 to 0x9000 with the value of 0x00. 

Isn’t the interrupt vector table located in ROM at address 0x0000?: Yes, but MON85 provides a vector table remapping feature that allows a copy to be stored in RAM for development use. It uses the “U” command for that purpose. Normally after a “load” command, the “program base address” is set to the address that the HEX file was loaded at. Be sure that the “U” command has the correct address before continuing. If need be, use the “U xxxx” command to set it, i.e. “U 8000” in this example. Thus, it is important that your program provides the vector table, or at least the vector of the interrupt you plan to use. Be sure it is located at the correct address location.

Using the program above, one can set a breakpoint at address 0x8059, which is the entry of the RST7.5 interrupt service routine (ISR). The restart vector itself can also be used, which is located at 0x803C.

Assuming a frequency generator is connected to the RST7.5 input and the “program base address” is confirmed as 0x8000, issue the “G 8000” command to MON85. If using LED’s on PORT A of the 8255 as a visual indicator (as I did), the LEDs should illuminate and count  “up” as a binary counter, wrapping around to 0x00 from 0xFF. If one is in use, be sure the shorting bar across JP7 has been removed, otherwise the frequency generator’s output will be shorted to ground. Note: If a frequency generator is not available, I was able to place a finger on top of the 8085 package near pin 10 and the LED’s went “crazy”. This is due to the body being used as an antenna and inducing a frequency field near the RST7.5 pin. If testing in a low-humidity environment, be sure NOT to touch JP7 as you may blow the 8085 with a high-voltage static discharge. It’s safer to use a frequency generator for this purpose. Make your connections while the Alpha is powered off.

Warning about restarting MON85 when using breakpoints: Something to be aware of when using MON85 with breakpoints; if a hardware reset is performed by pressing the reset switch (S1) on the Alpha, or if MON85 is restarted in any way, MON85 will forget it’s breakpoints. Since MON85 uses the RST1 vector to create a breakpoint, it will leave the RST1 OPcode (0xCF) within your code in memory and effectively disable your program. The way around this is to use the “edit memory” command (after a MON85 restart) and change the affected byte(s) back to their original OPcode(s) by referring to the assembly listing.

Overall conclusion regarding the OMEN Alpha 8085 SBC: After spending a LOT of time finding and correcting the MC6850 ACIA’s “RDRF bug” and finding and fixing the TinyBASIC “PRTNUM bug”, I find that the OMEN Alpha is a reasonably priced tool for exploration and learning about the now considered “vintage” 8085 microprocessor.

Any more software features for the Alpha? The only other software I am interested in working with is FORTH. I have the source code available for figFORTH V1.1 but I have not spent much time getting it to run on the Alpha. If I do, I will add another entry to the project blog.

In closing: The corrections and modifications to the MON85 and TinyBASIC source code are contained within the ZIP file below. I have also included all versions of MON85 that I have located, all versions of Palo Alto TinyBASIC that I have located and the test programs referenced in this project blog. There are two versions (3.6864MHz and 4.9152MHz crystals) of HEX and binary images of MON85-1v3 and TinyBASIC suitable for burning into EEPROM (or UV EPROM with the JP6 modification). Within the ZIP file are Linux build scripts for assembling MON85 V1.3 and TinyBASIC V2.1, as well as a build script to generate the INTEL HEX file and binary ROM image of MON85 + TinyBASIC.

File: OMEN_Alpha_Files-1V0-JQ.zip

Peace and blessings.

Updates to Palo Alto TinyBASIC

In the prior post, hardware modifications were made and MON85 was modified to use the MC6850 ACIA’s interrupts for character reception, I wanted to take a closer look at the Palo Alto TinyBASIC. I knew it should be modified to use ACIA interrupts as well because in testing, while TinyBASIC was emitting characters, pressing “control-c” or “control-o” was unresponsive. Presumably for the same ACIA RDRF issue.

I searched the Internet and found a copy of the original V1.0 published in DR DOBB’s JOURNAL. There is an ASCII copy of V1.0 here. Version 2.0 is here and likely the source that Martin had used for the OMEN Alpha. I found a CP/M version, likely V3.1 in this archive file here.

What are the differences between V1.0, V2.0 and V3.1? In my inspection of each of these versions, I found the following differences. Although, there may be some other minor variations that I did not notice.

  • V1.0: The original version written by Dr. Li-Chen Wang, published in Dr. Dobb’s Journal, April 1976. The PDF of the article can be found here (starts on page 12). This version was intended to be run from address 0x0000 and takes advantage of the 8080/8085’s restart vectors to conserve code space. It appears to communicate with the user via an INTEL 8251 UART.
  • V2.0: This version was modified by Roger Rauskolb to use INTEL mnemonics and be relocatable to any address below 0x8000. It removes the dependency upon the 8080/8085’s restart vectors in the first page of memory. It appears to communicate with the user via an MC6850 ACIA in polling mode but it lacks ACIA initialization code. The date of modification is unknown but there are references on the Internet that Roger’s modifications were published in the December 1976 issue of Interface Age magazine. The PDF of the article can be found here.
  • V3.1: This version has no version nor modification information other than the original header text by Dr. Li-Chen Wang. The download source reports it to be “Bruce Sherry’s disk version 3.1 of Lichen Wang’s Tiny Basic”  It adds support for CP/M with a LOAD and SAVE command. In addition, PEEK, POKE, WAIT and USR commands were added. It communicates with the user via CP/M calls.

For the OMEN Alpha, Martin chose TinyBASIC V2.0 as the source, which already used the MC6850 ACIA but it was slightly modified for the MC6850 ACIA.

With TinyBASIC V2.0, I converted Martin’s asm80.com source code syntax to AS8085 syntax, increasing the version identifier to V2.1. After doing so, I was able to successfully assemble it.

In the process, I modified code or added features as follows:

  • Using conditional assembly statements, support was added for using either the 8251 UART or the MC6850 ACIA.
  • Using conditional assembly statements, support was added for interrupt-driven character input from the ACIA with the RAM buffer being shared with MON85.
  • The additional commands found in TinyBASIC V3.1 were added; POKE and WAIT and the functions PEEK() and USR().
  • An additional HEX() function was added, which allows one to specify a value using hexadecimal notation. This is handy when using the new PEEK, POKE, USR and WAIT functions.
  • A bug was found in the PRTNUM routine (at “PN5”) that caused TinyBASIC to incorrectly print negative numbers. This appears to be a bug introduced with the OMEN Alpha as it is not present within any of the three versions acquired.

Complications in debugging existing TinyBASIC code or new code: The Alpha’s address space is equally divided into two memory regions; IC3 is addressed between 0x0000 to 0x7FFF and IC2 is addressed between 0x8000 to 0xFFFF. Technically, both IC2 and IC3 may contain either RAM or EPROM/EEPROM since the device pin connections are JEDEC compatible. However, IC3 is intended to be “read-only” memory (ROM), while IC2 is intended to be read-write memory (RAM). The memory configuration itself is not an issue.

Palo Alto TinyBASIC uses a lookup table with varying length ASCII text strings containing the supported BASIC language keywords. In order to allow shortened commands (i.e. ‘P. 12 * 12’ instead of ‘PRINT 12 * 12’), the 15th bit position of the command’s execution address is set high, designating the end of the command’s entry in the lookup table. Once the execution address is obtained from the lookup table, the 15th bit is cleared and execution is passed to that address. Stripping the 15th bit from the 16-bit execution address has the effect of restricting TinyBASIC to residing in the lower 32KB of the 8085’s 64KB address range. The difficulty with this method is that this restriction makes it impossible to fully relocate TinyBASIC into the Alpha’s RAM for testing and debugging it’s code. Hence another method must be used.

How do I debug the TinyBASIC code? Fortunately, in assembly language, everything is flexible. If you know how to use your tools then many seemingly difficult tasks can be accomplished. Is this not true in so many cases in life? In the following paragraphs, I’ll explain what steps were taken to isolate code sections, place them in RAM, modify TinyBASIC to use them and debug them using MON85. In particular, the USR() and HEX() functions were debugged in this manner, as was the “bug” in the PRTNUM routine.

20181015_163800
External 8251 UART wired to Alpha

First step: Separate the communications channels. The modified TinyBASIC V2.1 code I make available for the OMEN Alpha has conditional assembly support for using it with an MC6850 ACIA or an 8521 UART. It’s very helpful to have TinyBASIC use one communications interface for user interaction while MON85 uses the other as a debugging interface. In locating and determining the ACIA RDRF flag bug, I wired an external 8251 UART to the Alpha to separate the channels and it was very helpful in debugging.

2nd step: Add a jump instruction to TinyBASIC for the routine that needs to be tested and debugged.

Below is an example to test the OUTP command. Added code is highlighted in orange, while the specific JUMP to RAM instruction is highlighted in red and “external” routines (or references) that are relied upon by the OUTP routine (EXPR, TST, RUNSML, AHOW and INRAM) are highlighted in blue.

		;*******************************************************************
		;*  OUTP I,J
		;*
		;*  OUTPUTS EXPRESSION 'J' TO PORT 'I'
		;*******************************************************************
TEST_OUTP	.EQU	1				;Set to "1" to test OUTP code in RAM

	.IF	TEST_OUTP == 1
	.MSG	"!! Warning: OUTP subroutine now resides in RAM"
OUTP:	JMP	0x8000
	.ELSE
OUTP:	CALL	EXPR
	MOV	A,L
	STA	INRAM+1
	MVI	A,0xD3
	STA	INRAM
	MVI	A,0xC9
	STA	INRAM+2

	CALL	TSTC
	.STR	","
	.DB	OP2-.-1

	CALL	EXPR
	MOV	A,L

	CALL	INRAM
	JMP	RUNSML
OP2:	JMP	AHOW
	.ENDIF
		;

3rd step – create a “test” file and resolve all “external” references: Once the TinyBASIC routine has been isolated from the main program, the code to be tested can be stored in another file that will be assembled and used to load into RAM at the address of 0x8000 (or anywhere in RAM). However, there are four (4) routines that are “external” to this test code and one memory location in RAM that needs to be resolved, otherwise, assembly errors will occur. The way around this is to assemble TinyBASIC after the code modifications, find the addresses of the “external” routines (and reference) and hard-code those addresses into the test code. The “-s” parameter supplied to AS8085 during assembly creates a SYMBOL table for just this purpose.

A search for the address of those “external” routines in the symbol table will yield the addresses as follows:

TSTC     0x1267
EXPR     0x1213
RUNSML   0x1364
AHOW     0x12A6
INRAM    0xC000

Those addresses can then be entered into the test code and will be used to access the “external” routines (or memory location). The following assembly listing is for the source code to be tested. The external references are defined in orange in lines 6 through 10. It can be seen that the correct “external” addresses have been properly used by the AS8085 assembler (highlighted in blue).

                              1 	; **************************************
                              2 	; Palo Alto TinyBASIC
                              3 	;	Testing routines in RAM
                              4 	;
                              5 	; Beginning of external routines *******
                     1267     6 TSTC	.EQU	0x1267
                     1213     7 EXPR	.EQU	0x1213
                     1364     8 RUNSML	.EQU	0x1364
                     12A6     9 AHOW	.EQU	0x12A6
                     C000    10 INRAM	.EQU	0xC000
                             11 	; End of external routines *******
                             12 	;
                             13 	;
                             14 	;*************************************************
                             15 	.area	_CODE (ABS)
   8000                      16 	.ORG	0X8000				;For testing in RAM
                             17 	;
                             18 	;*******************************************************************
                             19 	;*  OUTP I,J
                             20 	;*
                             21 	;*  OUTPUTS EXPRESSION 'J' TO PORT 'I'
                             22 	;*******************************************************************
   8000 CD 13 12      [18]   23 OUTP:	CALL	EXPR
   8003 7D            [ 4]   24 	MOV	A,L
   8004 32 01 C0      [13]   25 	STA	INRAM+1
   8007 3E D3         [ 7]   26 	MVI	A,0xD3
   8009 32 00 C0      [13]   27 	STA	INRAM
   800C 3E C9         [ 7]   28 	MVI	A,0xC9
   800E 32 02 C0      [13]   29 	STA	INRAM+2
                             30 
   8011 CD 67 12      [18]   31 	CALL	TSTC
   8014 2C                   32 	.STR	","
   8015 0A                   33 	.DB	OP2-.-1
                             34 
   8016 CD 13 12      [18]   35 	CALL	EXPR
   8019 7D            [ 4]   36 	MOV	A,L
                             37 
   801A CD 00 C0      [18]   38 	CALL	INRAM
   801D C3 64 13      [10]   39 	JMP	RUNSML
   8020 C3 A6 12      [10]   40 OP2:	JMP	AHOW
                             41 	;

4th step – load, test and debug: Now that the test source code has been assembled (without errors), there should be a resulting INTEL HEX file generated (AS8085 generates INTEL HEX files by default with an extension of “.ihx”). The HEX file can be uploaded to MON85 via the “L” command, which allows loading of either an INTEL HEX file or a MOTOROLA S-Record file. After issuing the “load” command, MON85 will faithfully wait until the test file is uploaded, so you’ll need to use your terminal emulator to do that. In picocom, pressing “^A” (control-A) then “^S” (control-S) will prompt for the file name to send. Other terminal emulators should have the same ability.

As the screen print below shows, after “loading” the HEX file, the contents of memory locations 0x8000 through 0x8022 show our test code loaded properly and matches our program listing (above).

MON85-TestingInRAM
MON85 – loading and memory dump of test code

From this point, breakpoints can be set with MON85’s “breakpoint” command and program execution can be started with a “G xxxx”, where “xxxx” is the start of TinyBASIC in ROM (0x1200 in my case). Hint: Don’t use MON85’s “J” command to “jump” to TinyBASIC as it does not set the system up for tracing and debugging like the “G xxxx” command does.

If a breakpoint was set at 0x8000, execution of the “OUT” command will cause MON85 to break at 0x8000 (shown on the debugging terminal). From that point, “tracing” can be enabled with the “t on” command and single-step execution can continue with the issuance of a “G” command. A screen print of a sample debugging session with the above test code is shown below.

MON85-DebugSession
MON85 – Debug session with breakpoint and program tracing

Summary: Using the above method with MON85, program development and testing using the OMEN Alpha 8085 SBC can be conducted. Although the example cited was for use with TinyBASIC, it can be used with any program one wishes to develop on the OMEN Alpha. 

In the next post, I’ll explain how to use the OMEN Alpha and MON85 to test and debug programs.

Testing the MON85 firmware on the OMEN Alpha

In the previous post, I spoke of getting the OMEN Alpha to run the provided system monitor and “upgrading” to Dave Dunfield’s MON85 (V1.2).

Since I had a working 8085 assembler and I found that MON85 had more features than the system monitor written by Martin, I decided to stick with it. It took about an hour to reformat the MON85 source code for the AS8085 assembler but all seemed correct when comparing the resulting assembly listing to the expected values.

The OMEN Alpha features an 8255 PIO on-board, so I wrote some very simple routines to initialize the 8255’s ports to outputs, pulse all port bits HIGH for a few microseconds and to display an 8-bit value on PORT A, which I had connected 8 individual LED’s to. Technically, MON85’s “O <port> <data>” command works fine as “O 3 80”, which sets I/O address 3 (the 8255’s “Mode Definition Control Word”) to 0x80 (all ports to outputs) then using “O 0 N” to set or clear PORT A’s bits (driving the LED’s) to the value of “N“. However,  I wanted a means to CALL a subroutine to display 8-bit values on the LED’s as means for debugging code or pulse an I/O bit when a particular branch or sequence of of instructions is executed. In the “old days”, this was a “poor man’s'” means of debugging code when a more fancy means (i.e. an in-circuit emulator) was not available.

20180703_233206
Simple I/O Board

BTW: for testing purposes, it is sometimes helpful to connect an indicator to an output port or a switch to an input port. I recently built something for that purpose. It’s a simple and practical design. The PDF schematic is here.

Software bug in MON85?: Something I noticed while working with MON85, is that when executing the “Display Memory” command, I could not pause the display, so it kept scrolling endless lines of memory codes. I searched for and consulted a “user’s manual” for MON85 and found that both the “memory dump” and “disassemble” commands used the “space” key to pause the display, the “enter” key to display one line at-a-time and the “esc” key to abort the listing. These three features did not seem to work, or at least not most of the time. On occasion, MON85 would catch one of those key-strokes and act appropriately but during a full-out constant blast of characters, it was rare.

Since I was wanting to perform some program development with the Alpha, I would like these features to be functional. Looking at the thought and complexity that Dave Dunfield put into MON85, I didn’t think this “bug” would have been allowed to exist in a once marketed product. In looking over the MON85 source code, I could see where the ACIA is polled for a received character, which normally worked well, including when receiving a HEX file, but it wasn’t working when the ACIA was spewing characters back-to-back as the “dump” and “disassemble” commands do. I used various methods to try and isolate where the code was not performing correctly but found no apparent software reason for the loss of characters.

Switching to another UART: After not finding a valid software bug, I decided to look into the cause as being a hardware issue. In another version of MON85, an 8251 UART was used but Martin had to modify MON85 for use with the ACIA on the OMEN Alpha. I had always wondered why he would fit a MOTOROLA CPU peripheral with an INTEL CPU when the interface design philosophies were different between the two lines of competing products. In a comment posted, Martin had stated that he chose the MC6850 ACIA over the 8251 UART because he had MC6850’s in stock, the MC6850 had a higher baud rate and that it was easier to program than the 8251.

20180919_191944
External 8251 UART w/ baud-rate generator

I decided to re-code MON85 to use the 8251 UART, which I had a few of in stock. The Alpha provided a 24-pin header that gives enough support signals to attach an 8251 UART to it as an I/O peripheral. Months ago, I had built a break-out board that would accommodate any 600 mil wide DIP package up to 40 pins. It was time to use that for temporarily wiring the 8251 to the Alpha. However, unlike the MC6850 ACIA, the 8251 has no internal baud rate generator, thus it requires a proper baud rate clock to be applied to its RxC and TxC inputs. I had nothing to use for a baud-rate generator, so I quickly built one using a CD4060 14-stage binary counter, a 2.4576 MHz crystal and a 5-position DIP switch for selection of different baud rates from the “Q” outputs. I provided rates of 4800, 9600, 19,200, 38,400 and 76,800 (76,800 ÷ 16 = 4800) baud. The PDF schematic for the 8251 to Alpha interface, including the baud-rate generator is here.

Software or Hardware bug?: Once the 8251 (and baud-rate generator) were connected to the Alpha and MON85 was modified to use the 8251 for communications, I was able to verify that the “space”, “enter” and “esc” keys worked properly (most times) with the 8251 UART, so this appeared to be a hardware issue.

I decided to take another look at Martin’s system “MONITOR V3” to see how it “dumped” memory. It seems that Martin’s system monitor does not spew the memory values to the screen as MON85 does. Instead, it emits a 16-byte line then waits for an “enter” key to emit the next 16-bytes or a “space” key to terminate the command. I asked Martin if he knew about this “bug” but I never received a response.

I also tried MON85 in Martin’s asm80.com on-line assembler and software emulator. The “memory dump” and “disassemble” commands worked properly BUT a software emulator cannot always reliably emulate a hardware device, especially if it doesn’t emulate a previously discovered hardware bug, thus I’m not surprised it didn’t fail on the software emulator.

Search for the hardware bug in the ACIA: Convinced that this was a hardware issue with the ACIA itself, I sought to find solid evidence of it. I searched for any application notes on using the ACIA and/or any known bugs. I found ONLY the same MOTOROLA MC6850 ACIA datasheet posted on various web sources.

The ACIA does support hardware interrupts with an active-low open-drain IRQ pin. The IRQ pin responds to; RX register full (RDRF), TX register empty (TDRE) and some other error conditions.

Using a DIP-clip, a 10KΩ resistor and some EZ-Hook jumpers, I pulled the IRQ pin of the ACIA to Vcc through the resistor.  I then connected an oscilloscope to the IRQ pin where I could see the IRQ pin pulling low with each new character received. I could see that the duration of the low period varied slightly due to the time it took for the 8085 to respond to the interrupt, see that new data was available and fetch it, which cleared the RDRF flag in the status register. The IRQ pin seemed to be working properly. I even tried uploading a HEX file and I could see there was an IRQ pulse for each character received. Puzzling…

With no real way to test and debug the MON85 receive routine while it resided in EEPROM, I decided to re-locate it to reside in RAM at address 0x8000. That was easy enough. I also reprogrammed the MON85 in EEPROM to use the 8251 as a “debugging terminal” while the MON85 in RAM used the ACIA. In that manner, I could set breakpoints and single-step through the code to [ hopefully ] expose the real ( hardware ?) issue.

I connected the ACIA’s IRQ pin to the 8085’s RST7.5 pin and I was happy to see that MON85 faithfully redirected the RST7.5 vector (at 0x003C) to the restart vector table stored in it’s RAM-based counterpart.

The short version of it is that after some time and testing, I figured out that the RDRF and TDRE bits in the ACIA status register are NOT isolated from each other. If a character has been received before being fetched (RDRF bit set) and a character is transmitted, the hardware updating of the TDRE bit will clear the RDRF bit and there is no longer an indication of a new character in the receive register. In other words, if polling the status register for a received character returns none and a character is received AFTER the initial poll then when the routine moves on to write a character to the data register, the RDRF bit will be cleared when the TDRE bit is set. I was able to confirm this by using MON85’s “OUT” and “IN” commands to directly write to and read from the ACIA. Typing a key on my terminal would pull the IRQ pin low as expected and the state of the RDRF flag would not change upon repeated reads of the ACIA’s status register. However, if data was written to the ACIA’s data register before reading the new character, the TDRE bit in the status register will be set once the transmission buffer empties. Setting of the TDRE bit also clears the RDRF bit.

Below is the interactive session with MON85 (communication via the 8251 UART) verifying that the ACIA’s RDRF flag is cleared when data is written to the ACIA data register. I’ve added comments after the “*” character, colored the MON85 commands issued in blue and emphasized the register reads in red.

MON85> O C0 03    * RESET ACIA (C0 = CONTROL REGISTER ADDRESS)
MON85> O C0 16    * SET MODE
MON85> I C0       * CHECK STATUS
DATA=02           * TDRE BIT SET
MON85> O C1 55    * SEND 0X55 (C1 = DATA REGISTER ADDRESS)
MON85> I C0       * CHECK STATUS
DATA=02           * CHAR SENT, TDRE BIT SET
MON85> I C0       * CHECK STATUS AFTER ACIA RECEIVED CHARACTER
DATA=03           * TDRE AND RDRF BITS ARE SET
MON85> O C1 56    * NO READ FROM DATA REGISTER BUT SEND 0X56 
MON85> I C0       * CHECK STATUS
DATA=02           * RDRF BIT WAS CLEARED, TDRE BIT SET
MON85>

Because the “dump” and “disassemble” commands are emitting characters so fast, any received characters are lost the next time a poll looks at the RDRF bit for a received character. This is actually a hardware bug in the MC6850 ACIA. What amazes me is that the MC6850 ACIA has been around since the 1970’s. The OSBORNE 1, which was released in April of 1981, used the MC6850 ACIA. Its hard to believe that in all that time and all those designs that used it, that this hardware bug was never exposed, or corrected in subsequent die updates. In all likelihood, the designs used interrupts to service the MC6850 ACIA, so this bug may never had been exposed or if it was, using interrupts was the work-around.

Is there a solution?: I knew there was a potential hardware solution but it would require a PCB modification and a software modification to implement. Connecting the ACIA’s IRQ pin to an 8085 interrupt pin and writing a software interrupt service routine was required. However, there was a logic polarity conflict between the ACIA’s active-low IRQ pin and the 8085’s active-high interrupt (and “restart”) pins. I needed a logic inverter but there were no spare gates available in the existing Alpha design to implement one. The only reasonable solution was to use a MOSFET as the logic inverter, so I chose to use a common N-channel 2N7000 (Q1), which I had in stock. It would also require two 10KΩ pull-up resistors; one on the ACIA’s IRQ pin to Vcc (R6) and the other on the 8085’s RST5.5 pin to Vcc (R4). I chose the 8085’s RST5.5 pin because RST7.5 is brought out to the Alpha’s 24-pin connector, which I wanted to leave free and RST6.5 was the center of a ground connection between adjacent pins that I didn’t want to cut. I could have used a P-channel instead of an N-channel MOSFET but I had none in stock and the parts count is the same.

20180927_155439
Alpha hardware modifications for using ACIA interrupts (Q1, R4 and R6)

Software modification of MON85: Since the hardware interrupt signal was now connected to the 8085, it was time to modify the MON85 source code to use it. In RAM, I had to create a single character buffer that resides with MON85’s internal RAM variables. I had to write an interrupt service routine that would fetch the character from the ACIA and store it in the RAM buffer until the character input routine was ready to fetch it from RAM. The MON85 RST5.5 vector was modified to point to the ACIA interrupt service routine (ISR), the hardware interrupt mask register needed to enable the RST5.5 interrupt and interrupts would need to be enabled after ACIA initialization. The character input and output routines were modified accordingly.

I should take a moment to explain how I was able to test the ACIA interrupt service routine in RAM. The 8085 stores its interrupt and restart vectors in a vector table ranging from 0x0000 to 0x003C, which resides within the read-only memory region on the Alpha. MON85 supports vector table remapping and it does it well but the program in RAM must contain it’s own copy of the vector table. This normally wouldn’t be an issue but I was only interested in test response to a single vector. It was very easy to configure MON85 to jump right to my ACIA ISR by modifying the RST5.5 vector in MON85’s vector table. In that manner, any RST5.5 hardware interrupts would be directed to my ISR in RAM. Below is the assembly code listing with the modifications I used while testing the ACIA ISR in RAM before committing it to EEPROM.

[WORDPRESS does not provide a fixed width font for use in displaying assembly listing. Sigh…]

ASxxxx Assembler V05.20 (Intel 8085) Page 1
Hexadecimal [16-Bits] Thu Oct 18 02:02:42 2018

                     1 ; MON85 modifications to support redirection
                     2 ; to RAM-based ISR.
                     3 ;
                     4           .area _CODE (ABS)
0000                 5 ROM          .EQU 0x0000     ;Beginning of program space
002C                 6 RST55        .EQU ROM + 0x2C ;*Hardware interrupt address
                     7 ;
002C                 8               .ORG RST55
002C C3 00 80 [10]   9               JMP 0x8000     ;RX interrupt service routine
                    10 ;
                    11 ; ACIA ISR located in RAM for testing
                    12 ;
FFD0                13 ACIA_BUFF    .EQU 0xFFD0     ;MC6850 ACIA RX Buffer in RAM
                    14 ;
00C0                15 ACIA         .EQU 0xC0       ;ACIA base address
00C0                16 ACIAC        .EQU ACIA       ;ACIA control register
00C0                17 ACIAS        .EQU ACIA       ;ACIA status register
00C1                18 ACIAD        .EQU ACIA+1     ;ACIA data register
                    19 ;
0002                20 ACIA_TDRE    .EQU 0b00000010 ;TDRE flag in status
0001                21 ACIA_RDRF    .EQU 0b00000001 ;RDRF flag in status
                    22 ;
                    23             .area _CODE (ABS)
8000                24             .ORG 0x8000      ;RX interrupt service routine
                    25 
8000 F5       [12]  26 ACIA_ISR:   PUSH PSW          ;Save flags
8001 DB C0    [10]  27             IN ACIAS          ;Get the ACIA status
8003 E6 01    [ 7]  28             ANI ACIA_RDRF     ;Check RDRF flag
8005 CA 0D 80 [10]  29             JZ ACIA_ISR1      ;No RDRF, so ignore this IRQ
8008 DB C1    [10]  30             IN ACIAD          ;Get 6850 data
800A 32 D0 FF [13]  31             STA ACIA_BUFF     ;Save character in RAM
800D F1       [10]  32 ACIA_ISR1:  POP PSW           ;Restore flags
800E FB       [ 4]  33             EI                ;Re-enable interrupts
800F C9       [10]  34             RET               ;Return to caller

The listing format by column number is: 1 = Value or Program Counter Address, 2 = Generated code in byte format, 3 = Opcode cycles count, 4 = Source text line number, 5 = Source text.

Once the ACIA ISR was assembled and loaded into RAM at address 0x8000, a breakpoint was set at 0x8000 (“B0 8000”) to test that the vector redirection occurred and for single-stepping program execution. Another breakpoint was set at address 0x800F (“B1 800F”) to inspect the results of the registers before exiting the routine.

It can be seen that upon a RST5.5 hardware interrupt, the 8085 executes a JMP instruction to address 0x8000 (line #9) , where the ACIA ISR has been loaded in RAM. The ISR, located at 0x8000 (line #26) looks at the RDRF flag to see if there is a new character in the ACIA’s receive register. If RDRF = 0 (line #29) then the program jumps to address 0x800D (line #32), where it re-enables interrupts and returns to resume program execution. If RDRF = 1 then the new character is retrieved from the ACIA (line #30) and stored in memory (line #31) before continuing execution at address 0x800D.

Once the ACIA ISR was tested, it was incorporated into MON85 and tested for proper functionality.

The following code excerpt shows the RST5.5 vector and the additional RST5.5 hardware interrupt enable code added to MON85. The routine “TEST” is located after the interrupt vector table within MON85.

.ORG 0x0000             ;Start of ROM
.
[ other code ] 
.ORG RST55 JMP ACIA_ISR ;RX interrupt service routine
.[ other code ] 
.
; TEST is part of MON85 and is the beginning of the cold-start code.
TEST: CALL INIT          ;Initialize the ACIA/UART
      ; JQ - added IRQ for MC6850 on-board ACIA
      MVI A,0b0001110    ;enable RST5.5, disable RST7.5 and RST6.5
      SIM                ;set the mask bits
      EI                 ;Enable interrupts

Below is the ACIA initialization code (“INIT:”) and the final ACIA interrupt service routine (“ACIA_ISR:”). The original ACIA initialization code did not perform a MASTER RESET as the datasheet recommends, so that additional instruction sequence was added.

;Equates
ACIA      .EQU 0xC0         ;ACIA base I/O Address
ACIAC     .EQU ACIA         ;ACIA CONTROL Register Address
ACIAS     .EQU ACIA         ;ACIA STATUS Register Address
ACIAD     .EQU ACIA+1       ;ACIA Data Register Address

ACIA_TDRE .EQU 0b00000010   ;TDRE bit position in STATUS
ACIA_RDRF .EQU 0b00000001   ;RDRF bit position in STATUS

;Initialize the 6850 ACIA
INIT:      MVI A,0x03       ;Master RESET first!
           OUT ACIAC
           MVI A,0x96       ;divide by 64 for 38400 Bd, 8 bit, no parity, 1 stop bit, w/ IRQ @ 4.5192MHz
           OUT ACIAC
           RET
;
;***************************************************************
; 2018-0921 - JQ - 6850 ACIA bug fix!
; An active RDRF flag is clobbered by a write to the ACIA
; data register and subsequent TDRE flag update. Using RX
; interrupt, fetch and store the new character in RAM for the
; IN routine to fetch.
;
ACIA_ISR:  PUSH PSW        ;Save flags
           IN ACIAS        ;Get the ACIA status
           ANI ACIA_RDRF   ;Check RDRF flag
           JZ ACIA_ISR1    ;No RDRF, so ignore this IRQ
           IN ACIAD        ;Get 6850 data
           STA ACIA_BUFF   ;Save character in RAM
ACIA_ISR1: POP PSW         ;Restore flags
           EI              ;Re-enable interrupts
           RET             ;Return to caller

The character input routine was modified to fetch the character from the single character RAM buffer and return it if available. The RAM buffer will contain 0x00 if there is no new character as the character input routine insures that.

;Check for a character from the console (6850 acia)
;*** 2018-0920 - JQ - Added ACIA RX buffer for 6850 RX bug fix!
IN:  DI               ;Disable interrupts
     LDA ACIA_BUFF    ;Fetch RX buffer in RAM
     ANA A            ;Test for new character (A != NULL)
     JZ IN1           ;Exit if not a new character
     PUSH PSW         ;New character, so save it
     MVI A,0          ;Clear the RX buffer in RAM
     STA ACIA_BUFF
     POP PSW          ;Restore the character
IN1: EI               ;Re-enable interrupts
     RET              ;Return to caller

The character output routine (“OUT:”) was modified to first check for a received character. If the RDRF flag is set, then the ACIA_ISR routine is used to first store the new character in the RAM buffer (for later receipt by the character input routine). The character output routine (“OUT1:”) then proceeds to emit the output character.

;Write character in A to console (6850 ACIA)
OUT:  PUSH PSW        ;Save output char
      IN ACIAS        ;Get 6850 status
      ANI ACIA_RDRF   ;Test RX bit
      JZ OUT1         ;No RX character waiting
      CALL ACIA_ISR   ;Let the ISR handle it
      RET             ;Return to caller
OUT1: IN ACIAS        ;Get 6850 status
      ANI ACIA_TDRE   ;Test TX bit
      JZ OUT1         ;Not ready
      POP PSW         ;Restore output char
      OUT ACIAD       ;Write 6850 data
      RET             ;Return to caller

In actual testing, this method worked very well. With the hardware and software modifications in place, the missing character issue became a non-issue and MON85 functioned properly once again.

20181018_065858
Addition of JP6 for 8K/32K Memory Support

Hardware modifications performed on OMEN Alpha “Issue 2”: One of the modifications I made was connecting the LED originally connected to the 8085’s SOD pin, to Vcc, to serve as a power indicator. I found an LED with a lovely shade of green for that purpose, not too bright and not too dim, positively “Goldilocks right”!  Another modification was the support of 8KB (UV) EPROM or EEPROM memories in the location of IC3 with the addition of JP6 for switching pin 1 of the socket. With a 32KB memory, pin 1 goes to the A14 address line and with an 8KB memory, pin 1 goes to Vcc.

With the hardware and revision update modifications finished, I wanted to update the schematic to reflect them. Martin used AUTODESK’s EAGLE for schematic capture and PCB layout. I don’t use EAGLE as I use OrCAD and have been for over two decades, so I decided to re-create the OMEN Alpha “Issue 2+” in OrCAD. With the exception of the additional components, the original component references are maintained.  The 11″ x 17″ PDF schematic schematic is here.

Additional research into other projects using the MC6850 ACIA: I know that other projects are using the MC6850 ACIA, so they must be having the same problem, right? For example, Grant Searle’s Z-80 design uses it. But upon closer inspection of the schematic, it can be seen that the ACIA’s IRQ pin is pulled to Vcc via a 3.3KΩ resistor and is directly connected to the Z-80’s INT pin, which is an active low input (no logic inversion necessary). Grant does not make the source code of his system monitor available, so I can only assume that he is using interrupts to service the MC6850 ACIA.

The 8251 UART does not have a dedicated interrupt output pin. Instead, it has two active-high outputs, TxRDY and RxRDY, that can be used individually or combined with an OR gate (or two diodes) to trigger the 8085’s hardware interrupt inputs. So it looks that INTEL designed the 8251 to match the interrupt signalling polarity with that of the MCS-80 and MCS-85 family, which is opposite the industry standard of using open-collector or open-drain output pins to drive active-low interrupt inputs.

A note on the HITACHI HD6350/HD6850 ACIA: I mentioned in a prior post that I found a datasheet for the HITACHI HD6850, which was a 2nd source for the MOTOROLA MC6850. The data sheet is more or less an exact word-for-word copy of the MOTOROLA datasheet. I don’t possess any HD6850’s, so I don’t know if the RDRF bug exists in them as well but it would be interesting to know if the hardware bug was found and corrected or simply duplicated. I suspect it was duplicated.

2020-0310 Update: I was able to acquire a HITACHI HD63B50CP. After testing, I was able to determine that the same RDRF hardware bug exists in the HITACHI HD63B50. The results of the register testing using MON85 above yielded the same results with the HD63B50 as with the MC6850. So it looks like the HITACHI 2nd source was simply a die copy only.

A note on hardware interrupt signaling: Why did INTEL designers choose for the 8080/8085 devices to use active-high interrupt and restart interrupts? Its unclear because a simple active-high or active-low wire-OR function can be implemented using only switching diodes, so there appears to be no difference in choice of polarity. For many decades, active-low open-drain outputs have been industry standard for “wire-OR-ing” multiple devices together on microprocessors using a single interrupt request pin. In the “old days”, the concept of “open-drain” was actually implemented as “open-collector” because bipolar junction transistors (BJT) were the state-of-art in TTL circuits of the 1970’s and 1980’s. These days, MOSFET‘s are typically used, hence the “open-drain” nomenclature.

In the next post, I will cover the changes to Palo Alto TinyBASIC.

OMEN Alpha; first signs of intelligence?

Upon successful assembly and pre-testing of the OMEN Alpha, I found myself at the stage of wanting to run some pre-configured software on it. Martin provides a 32KB EEPROM image in his GITHUB repository. The image contains a minimal monitor and Palo Alto TinyBASIC 2.0 in both HEX and binary file formats.

Using a Minipro TL-866A programmer, I was successful in programming an AT28C256 EEPROM. BTW: I’m a Linux user, so using the open-source Linux command line interface allows me to write “intelligent” BASH scripts and interact with the TL-866A without having to run the WINDOWS-XP Virtual Machine and use the OEM’s software.

First sign of “life”?: With a programmed EEPROM in socket, I set out in search of intelligence from the OMEN Alpha. Well, perhaps just an intelligible response from it will do for now.

In order to accomplish that, I first had to wire up a USB-to-TTL converter to speak with the ACIA. I have a few various flavors available but generally, I like the CP2102-based versions. I powered up the Alpha and received no response at the expected 115.2 kbaud. I adjusted the terminal’s baud rate up and down and could see with every press of the reset button, I received “garbage” characters indicating an incorrect baud rate. Then I realized that I was using a faster clock speed than the original design and that the ACIA had a baud clock of 2.4756 MHz instead of 1.8432 MHz as the original design called for. With the current firmware, the higher baud clock yielded a baud rate of 153.6K instead of 115.2K baud. Using the 4.9152 MHz crystal, I had already calculated that I could achieve a baud rate of 38.4K by using a divisor of 64 rather than 16 but I was going to need to find and make a change to the ACIA initialization routine in the system monitor source code. I found the source code for the monitor and I found the ACIA initialization code. Fortunately, it was only a single byte, but I quickly realized that I had no means to assemble the 8085 source code.

A note on Linux based terminal emulators: There are a few Linux-based terminal emulators out there. Personally, I use picocom, which is command line based. Picocom allows uploading and downloading of files with X-MODEM, Y-MODEM, Z-MODEM and ASCII protocols. One could use screen or minicom, which are also command line based. Under Linux, all three terminal emulators can “speak” through a standard RS-232 serial port or through a USB-to-Serial converterMinicom and screen can be found in most Linux distributions or the source code can be downloaded, compiled and installed.

Stuck, now what?: I thought a moment about what I needed to modify the binary image of the existing EEPROM image. After all, it was a pre-assembled program image that was already working on Martin’s product. I already have a binary editor installed as like Neo, I’ve been down this road before and found that I needed a binary file editor for other projects. I found one, a wonderful binary file editor for Linux named wxHexEditor. There are others but I like wxHexEditor.

wxHexEditor
wxHexEditor viewing MON85 Binary ROM Image

While viewing the EEPROM image file, I could see the strings mixed among the code and data. I knew I was looking for an 0x3E, 0x15 (MVI A, 0x15) sequence. wxHexEditor has a search function that will search for hexadecimal values as well as ASCII. The search revealed only one match, which was the one I was looking for. A quick change from 0x15 to 0x16 and it was done. File saved!

I reprogrammed the EEPROM with the newly modified binary image and the Alpha came to life with a more than intelligible response! The following screen captures are;  Alpha monitor on the left and Palo Alto TinyBASIC on the right.

Onward: With a functional Alpha, I now needed a means to assemble source code. I was faced with locating an assembler for the 8085. Since I’m a Linux user, I really wanted to use something that would run as a native Linux program.  I found a few 8085 assemblers; TASM32 (for DOS/WINDOWS), ASM85 by Tom Nisbet, AS8085 (ASxxxx) by Alan R. Baldwin and Dave Dunfield’s ASM85.EXE for DOS, which I found embedded here in a repository under “Compiler”.

I decided to use the AS8085 from Alan R. Baldwin because it supports other processors that I have toyed with (including the Z-80, HD6805 and 8051), SDCC uses it, its a fairly complete assembler and it’s still maintained. I downloaded the source code (V05.20), compiled and installed it. Once installed, I had a shiny new 8085 assembler to work with. My mother Gabrielle (∞) was proud of me.

Not so fast… Hmm, there seems to be a little problem with the Alpha’s monitor source code in that it isn’t syntax compatible with AS8085! Okay, let’s install the the other 8085 assemblers and see if they will assemble this source code. To no avail, no success, not even Dave’s (retro) popular ASM85.EXE running under DOSBOX. None of the existing 8085 assemblers I could locate and run would assemble Martin’s source code without multiple syntax errors.

Successful modification and assembly: As it turns out, Martin has a web site, asm80.com, that contains a full IDE for the 8085. The web interface sports an editor, assembler, emulator and debugger. He’s been writing the software behind the “engine” in his spare time and it performs well. There are several microprocessors and “machines” that can be emulated with the proper selection and emulator definition file. I was able to take Martin’s source code for the Alpha monitor and reassemble it with the new ACIA control byte yielding an INTEL HEX file for use with the TL-866A programmer. A successful “burn” of the EEPROM and the Alpha monitor V3 worked.

I want more: Okay, I have a working system now, it passes the initial litmus test and I can assemble 8085 programs now … but I wanted more. I wanted to see Dave’s MON85 in action. In Martin’s GITHUB repository is a version of MON85 as both source code and HEX file. Knowing that the same ACIA initialization control byte needed to be changed, I found the routine, changed the value and reassembled under Martin’s asm80.com. Upon running it, I could see MON85 provides a few more features, including multiple breakpoints, HEX file loading, single-stepping and tracing of program execution and interrupt vector table mapping. All of these features are essential for in-circuit software development on the target when one lacks a pricey hardware In-Circuit Emulator (ICE).

Tedious reformatting: I knew that using Martin’s asm80.com meant I was going to be tied to an Internet connection in order to use it. I’d prefer to be able to support myself in a “stand-alone” configuration without any reliance upon external resources. The other issue I ran into with asm80.com is that it doesn’t follow any existing 8085 assembler syntax. It appears that it uses a mix of various prior established assembler syntax’s and is compatible with none of them. I really didn’t want to be tied to an Internet connection for 8085 software development and any way I go about it, I would need to reformat source code for a consistent syntax. Martin had to have taken the time to reformat the original source code for MON85 and TinyBASIC to accommodate the specific syntax of his asm80.com, as they did assemble without error under asm80.com.

Back to AS8085: The syntax is different from any existing 8080/8085 source code, thus I made a decision to reformat Martin’s provided source code to be compatible with AS8085. There are approximately 2000 lines of code for Dave’s MON85 and nearly that for TinyBASIC. Not all those lines required changes, since the syntax of the mnemonics was standardized by INTEL for the 8085 and the majority of the source code consists of 8085 mnemonics. With repeated assembler and linker runs, I was able to whittle away at the errors. Many were corrected by simple “search and replace” operations in the text editor (I use medit). The most tedious and time-consuming part of the effort was adding the “:” (colon) after every label, since AS8085 issues an error if they’re missing.

Update: I recently discovered ASMX by Bruce Tomlin. Herb Johnson has modified and bug-fixed it here. It directly compiles the original TinyBASIC V1.0 and V2.0 source code as well as Dave Dunfield’s MON85 V1.2, so my hours of effort to reformat syntax to assemble with AS8085 was unnecessary. Sigh…

I decided to write a build script for assembling and linking with AS8085. I could have written a MAKEFILE for it (I may still) but I’m not so well-versed in the MAKEFILE language, so it was quicker for me to write a BASH script for that process. The BASH script below will assemble, link and generate a HEX and binary image from the 8085 assembly language source code.

#! /bin/bash

ROM_SIZE=32768 # size of the intended ROM file

# ANSI COLORS
# source $(which colordefs.sh) # source color definitions from file
NML="$(echo -e '\033[0;39m')"
RED="$(echo -e '\033[1;31m')"
GRN="$(echo -e '\033[1;32m')"
YEL="$(echo -e '\033[1;33m')"
BLU="$(echo -e '\033[1;34m')"
MAG="$(echo -e '\033[1;35m')"
CYN="$(echo -e '\033[1;36m')"
WHT="$(echo -e '\033[1;37m')"
GRY="$(echo -e '\033[0;37m')"
INV0="$(echo -e '\033[1;27m')" # inverse video off
INV1="$(echo -e '\033[1;7m')" # inverse video on
BLNK0="$(echo -e '\033[25m')" # blinking video off
BLNK1="$(echo -e '\033[5m')" # blinking video on

ROM_SIZE=32768 # size of the intended ROM file

if [ $# == 1 ] ; then
TARGET=${1%.*}
else
TARGET=alpha-mon85-1v3
fi

if [ -e $TARGET.asm ] ; then
echo
echo "Assembling $TARGET..."
as8085 -los $TARGET.asm
if [ $? -ne 0 ] ; then echo "${RED}Error assembling $TARGET.asm${NML}" ; fi

echo
echo "Linking $TARGET..."
aslink -i $TARGET.rel
if [ $? -ne 0 ] ; then echo "${RED}Error linking $TARGET.rel${NML}" ; fi

echo
echo "Generating HEX and BIN files for $TARGET..."
LOAD_ADDR=$(srec_info $TARGET.ihx -intel | sed -n '2p' | awk '{print $2}')
echo "Load Address = ${LOAD_ADDR}"
if [ "$LOAD_ADDR" == "0000" ] ; then
FILL="-fill 0xff 0x0000 0x$(printf '%x\n' ${ROM_SIZE})"
fi

# Create HEX file with 16 byte records
srec_cat $TARGET.ihx -intel -o $TARGET.hex -intel -obs=16

# Create a binary image file the size of ROM_SIZE, filling with 0xFF if needed
srec_cat $TARGET.ihx -intel ${FILL} -o $TARGET.bin -binary

rm -f $TARGET.ihx

else
echo
echo "$TARGET.asm not found!"
echo
fi

At this point, I have a syntax modified MON85 source code file that properly assembles and links under AS8085.

I should mention that the actual current draw of the OMEN Alpha is under 200 mA. With my particular mix of IC component brands, only 160 mA is drawn. The only device that gets slightly warm is the INTEL P8085AH (circa 1980), which is made on an a more current-hungry HMOS process.

In the next post, I’ll write about more of my testing of the firmware for the OMEN Alpha 8085 SBC and hardware modifications I added.

PCB Arrival and Assembling of the OMEN Alpha

After ordering the OMEN Alpha Bare PCB from Martin and testing the MC68B50 ACIA, it seemed to take forever for the PCB to arrive. See, here in the united States, “registered mail” is [ supposed to be / used to be ] highly secure. It is actually a hand-to-hand delivery method that dates back to the “Pony Express” of the 1800’s. Since it is highly secure mail, each “registered” article is placed in a locked bag during transport and secured in a safe or secure area in between transports. Each person that handles the article MUST sign a manifest attached to the article as a means of audit and tracking. It only took a few days for the PCB to arrive in the states but then it took another two and a half weeks for it to arrive to me, simply due to it being classified as “registered mail”.

When the PCB arrived, it was inside a standard A6 envelope with no particularly special attention-grabbing markings on it.

PCB inspection: The circuit was laid out on a 3.3″ x 3.9″ board using a standard green soldermask. The layout looked clean but I noticed it was an “Issue 2” and not an “Issue 4” as I had been expecting. Upon looking at the differences between the two, I could see I would need to cut some traces and tack some parts on the board to bring it (nearly) up to “Issue 4” level. Not a big deal for me as I used to work as an electronics technician for a production manufacturing company, so I had some training and am fairly proficient at reworking electronic assemblies. I also rework surface mount technology PCB’s when the need arises.

The following three images are from Martin’s TINDIE site.

Martin was thoughtful enough to design an 8255 “Programmable Peripheral Interface” onto the board as well as some additional I/O decoding via a 74HC138 address decoder exposed on a 24-pin connector residing on the edge of the PCB. I did notice that there was some crowding with connector JP4 that connected to PORT C of the 8255. Personally, I prefer headers to be placed on the edge of a PCB, so that mating headers can be attached easily and exit “away” from the PCB.

I also found a crowding situation with JP5, which is too close to IC4, the system EEPROM. JP5 is used to enable in-circuit writing (or not) to the EEPROM and requires using a BERG-STIK type shorting bar between two of it’s three pins. Using the shorting bar creates a slight physical interference fit with the 28C256 package.

I wrote Martin with the intention of telling him about the shipping delay, the “Issue 2” versus “Issue 4” misunderstanding and offering constructive feedback on component crowding based upon my observations. He seemed to appreciate the feedback but was very apologetic about the shipping delay. Apparently so much so, he refunded the full US$15 I paid for the bare PCB and shipping. Further attempts to contact him via the TINDIE site have been unresponsive and I have no personal email address for him.

PCB Assembly: In the GITHUB repository were the PCB and schematics for the “Issue 2” and “Issue 4” PCB’s, so I could see the few changes between them and was able to ascertain a correct parts list. Also contained in the repository are two PDF manuals, one written in Czechoslovakian and the other in English. The quick and basic assembly instructions reside within. Nothing fancy like those HEATHKIT days. 🙂

The PCB assembly went without any problems. I did not encounter any issues other than those revision differences I already knew about, and the reset switch that I had, fit as expected.

Initial Testing: Once fully populated with parts and IC sockets, I connected the board to my DPS3005 programmable power supply. I set the voltage to 5 volts and the maximum current to 50 ma and tried the basic “no-shorts in the power supply” test. Viola! Success! No shorts in the power supply. I measured the power supply voltage on the Alpha and it read good, so I stuffed the IC sockets with the “live actors” and tried it again with the current limit set to 250 mA. The current draw shown on the power supply was about 160 mA, a bit less than the “typical” datasheet values.

I powered up the scope and started looking for action on the 8085’s X2 pin, the output of the crystal oscillator. The frequency counter showed about 4.9152 MHz, so that function was operational. I looked for activity on the ALE pin and that was operational as well. I had no program in the EEPROM, so when fully erased, it is a 32K byte array of “OP code” 0xFF, which is a RST7 instruction. The RST7 instruction vectors program execution to memory address 0x0038. Once there, the 8085 continues to execute an endless loop of RST7 instructions from address 0x0038, endlessly, harmlessly and happily executing CPU cycles and basking in the energy (current) it draws in doing so.

In the next post, I’ll write about running the system monitor on the OMEN Alpha 8085 SBC.

Waiting for the arrival of the OMEN Alpha PCB

While awaiting for the arrival of the OMEN Alpha package, I set out to gather the parts required. I didn’t have the same push-button switch that was designed in but I had one that I could make fit. I didn’t have a 3.6864 MHz crystal but I did have a 4.9152 MHz crystal. Since the MC68B50 ACIA’s Tx Clock and Rx Clock are driven from the 8085’s CLK pin, I calculated that the ACIA’s baud rate would be 38.4 kbaud with a divisor of 64 (I used a divisor of 16 for a baud rate of ~3.9K). I also didn’t have any MC68B50 ACIA’s. 8251 UART’s I had but not 6850’s, so I’ll have to order some of those. eBay showed them available at a reasonable price, so I ordered a few.

MC6850_ACIA
Photo of an MC6850 ACIA

Testing the MC68B50 ACIA: During the time I was still waiting for the PCB to arrive, the MC68B50’s came in. From here on, I’ll refer to the MC68B50 as the “ACIA”. I figured I might as well test the ACIA’s but I didn’t have any other devices that used them, so how to test them? Well, in situations like this, I tend to break out my trusty hardware testing friend, AttoBASIC.  Running AttoBASIC on the ATMEL (now MICROCHIP) AT90USB1286 allows me to create a hardware emulator of sorts. Not a real fast one but it has plenty of I/O and a bidirectional 8-bit port to emulate the data bus with. For what I want to do, it’s another perfect fit! I created something similar with the Z80AVR project for testing the on-board RAM and I/O.

Here’s the AttoBASIC program that tests the MC68B50 ACIA.

5 REM MC68B50_TEST # E= WRITE ON L->H, READ ON H->L
10 R:= $15 # 6850 CONTROL REGISTER LOAD
15 ODF '1111; OPF '1111; PWM 128 # F3=CS, F2=RS, F1=R/W, F0=E
20 GOSUB 65; GOSUB 70; PRINT "STAT="; PRB A # INIT 6850 AND READ BACK STATUS
25 PRINT "-------------~" # PRINT SEPARATOR
30 FOR J=0 7; A:= J * 16 # INIT WRITE/READ LOOP
35 PRINT "XMIT="; PRX J * 16; GOSUB 80 # XMIT DATA
40 GOSUB 70; IF 0 = A AND 1 THEN GOTO 40 # READ 6850 STATUS
45 GOSUB 85; PRINT "RECV="; PRX A # READ AND PRINT DATA
50 PRINT "-------------~"; NEXT # PRINT SEPARATOR AND TERMINATE LOOP
55 OPF $FF; END # ALL CONTROL SIGNALS HIGH, END

60 REM CONTROL REGISTER ACCESS
65 OPF '0000; ODC $FF; OPC 3; PBF0; OPC R; PBF0; RETURN # INIT 6850 W/ 16X CLOCK
70 OPF '0010; OPC 0; ODC 0; SBF0; A:=INC; CBF0; RETURN # READ STATUS

75 REM DATA REGISTER ACCESS
80 OPF '0100; ODC $FF; OPC A; PBF0; RETURN # WRITE DATA
85 OPF '0110; OPC 0; ODC 0; SBF0; A:=INC; CBF0; RETURN # READ DATA

Essentially, the ACIA’s data and control lines are manipulated by AttoBASIC. Specifically, PORT D is emulating the data bus, while 4 outputs from PORT F are emulating the 4 control lines; E, R/W, RS and the CS0 line, while CS1 is strapped high and CS2 is strapped low. The Tx Clock and Rx Clock lines are driven by a PWM output with a 50% duty cycle. The PWM rate is 62.5 KHz, so with a baud rate divisor of 1, that’s 62.5k baud. All I cared about was the eventual goal of seeing some characters spit out of the Tx Data pin and be properly read back in (as a “loop-back”) through the Rx Data pin. But it’s not as simple as that. Because the ACIA does not have a hardware RESET pin, you first must issue a “MASTER RESET” code to the ACIA then a mode setting code. Once the mode is set then you can transmit and receive till your heart’s content. So, writing two bytes to the ACIA first had to be programmed as well. Figuring out how the E line interacted with the ACIA was the confusing part but I used a logic analyzer to verify the control signals and eventually got it to work. Because I was not expecting to journal this project, I didn’t save the logic analyzer screen captures.

Once the AttoBASIC program was working, I was able to test and verify that all 5 pieces of the ACIA were functional.

I also wanted to get an idea about how much current the board will need. Martin seems to recommend a 5 volt @ 1 Amp power supply but based on the current consumption of the parts from the datasheets, I knew that was overkill. Oddly, the Icc for the MC68B50 is not specified in the datasheet. However, HITACHI second sourced the ACIA as an HD6850 and the Icc is specified. Below is the Icc for each of the integrated circuits on the OMEN Alpha.

Sys Clk (MHz)     IC     Run Current (ma)
 4.9152MHz      I8085AH      135
 2.4576MHz      MC68B50        5
                I8255	      40
                AT28C256      50
                M5M5256       30
                74HC573        0.08
                74HC245        0.01
                74HC138        0.01
                74HC00         0.01
                Total:       260.11

Pulling from a future fact; in actual testing, the current draw was under 200 mA.

In the next post, I’ll assemble the OMEN Alpha 8085 SBC.

An introduction to the OMEN Alpha 8085 Single Board Computer

I recently cataloged (and counted) the  Dual In-line Package (DIP) integrated circuits that I have “hoarded” since my teenage years. Many parts I hoard are now considered “vintage” due to their fabrication age. These are parts like the INTEL 8085, RCA 1802, ZILOG Z-80, NATIONAL SEMI SC/MP, MOS6502, various CPU Peripherals, FPGA’s, UV-EPROMS and EEPROMS, low-density Static and Dynamic RAMS, etc. In all, I found I had some 900 line items totaling about 5,000 integrated circuits of various types.

A few months had passed since I cataloged all those IC’s, then on August 20, 2018, HACKADAY published an article for an 8085 single board computer (SBC) named “Alpha” by OMEN.  The Alpha 8085SBC was designed by a man named Martin Maly from Czechia. Martin has a page for the Alpha on HACKADAY.IO, HACKSTER.IO and a GITHUB site where he provides the original EAGLE schematic and PCB files, the GERBER files, a manual, software source code and pre-assembled HEX files. He has a modified Dave Dunfield MON85 (V1.2) system monitor and a modified Li-Chen Wang Palo Alto TinyBASIC to suit his hardware, specifically, the MC68B50 ACIA. I took an interest in this project because he was making the Alpha available as a kit on TINDIE. I read the posts on TINDIE and saw that Martin had ordered a new version, “Issue 4”, and that those PCB’s had arrived. I already had 95% of the parts required, so I contacted him to see if he would sell me a bare PCB. He responded and said he would. US$5 for the PCB and another US$10 for shipping. Not a bad deal and it saved me the time to research, design, layout and program my own 8085 SBC. I ordered one and it was shipped “registered mail” from Czechia, with the tracking number provided.

The photo’s below are from Martin’s TINDIE site.

The next post will discuss testing the MC68B50 ACIA without an existing circuit.