New Life for the Z8671 BASIC Interperter
by Chris Howie


Many of us have written mixed BASIC and assembly code for the Zilog Z8671, and have had to abandon it after Zilog discontinued the chip. This application note describes how the BASIC/Debug interpreter from the Z8671 can be installed in EPROM for a system using any other Zilog Z8-series microcontroller, restoring the capability of mixed languages. In addition, it is now possible to use any clock speed instead of being restricted to 7.8 MHz.

The original object code for the interpreter has been altered slightly, and certain SRP (Set Register Pointer) instructions have been corrected since they interfered with the Extended Addressing found in the Z86C93.

The former method for setting the baud rate involved reading address %FFFD and setting the rate according to the data found there. The new routine, which replaces the address-reading section, requires that the baud rate be predetermined and its corresponding division factor be installed in the code at the time the EPROM is created. With this method, the clock frequency is included in the calculation, thereby removing the 7.8-MHz restriction.

The databook relates the baud rate to the values found in the Counter/Timer 0 Register (R244), Prescaler 0 Register (R245), and the crystal frequency. The formula given there is

bit rate = xtal frequency / (2 x 4 x p x t x 16)

where

p = initial value in R245
t = initial value in R244

The factor of interest is the PT product, which is produced by multiplying the prescaler division ratio by the contents of the Timer register. After massaging, these values will be placed into memory locations %97 and %95, respectively, which may be done in the source code or manually during EPROM programming. Rearranging the above formula yields

PT = (xtal frequency) / (128 x baud rate)

For example, for a 20-MHz crystal and a rate of 1200 baud, the PT product will be

PT = (xtal freq) / (128 x baud rate) = (20 x 106) / (128 x 1200) = 130

When the result is less than 255, the prescaler value will be 1. When the PT product is greater than 255, the prescaler value must be chosen so T falls between 1 and 255. Note, however, the prescaler register is organized such that the modulo is contained in the highest six bit locations, so the actual value to put in the register is the desired number multiplied by four. In addition, the first bit must be set in order for the counter to free-run, so the final value to put in R245 will be four times the required prescaler value, plus one. Therefore, in this example, R245 (prescaler) will contain %05, and R244 (timer) will contain %82.

This new routine requires very little room; in fact, less than half the space taken by the %FFFD-reader. The remaining space is padded with NOPs. Listing 1 is an excerpt from the original Zilog code, and Listing 2 shows the code replacement. To use the interpreter code attached to this note, change the %FF values found at addresses %95 and %97 to the values determined by the above formulas. Finally, Listing 3 shows the raw Intel hex format code.

Listing 1:Original code from Zilog’s listing.

008C  31 F0     236 RESET: SRP  #RPx        ! MAKE =WORK, SO SHORT
008E  B0 FB     237        CLR  IRQ+1       ! CLEAR INTERRUPT MASK
0090  8C 96     238        LD   rP01M,#150  ! RAM, FAST, INT STK
                239                         ! (10010110)
0092  FC 68     240        LD   rSPL,#ISTAK ! STACK POINTER
0094  4C AF     241        LD   rT0R,#175   ! INITIALLY 110 BAUD
0096  5C 0D     242        LD   rT0Rp1,#13  !  FOR UART (00001101)
0098  7C 41     243        LD   rP3M,#65    ! SERIAL I/O (01000001)
009A  1C 03     244        LD   rTMR,#0     ! START UART CLOCK (%03)
009C  CC 02     245        LD   rFLAGS,#2   ! SET XEQ
009E  31 13     246        SRP  #AC
00A0  B0 03     247        CLR  PORT3
00A2  4C FF     248        LD   rADH,#-1    ! POINT TO SWITCHES
00A4  5C FD     249        LD   rADL,#-3    ! = FFFD
00A6  C2 24     250        LDC  rACX,@rrADH ! GET THEM
                251 !      LD   rACX,#2     ! USE MUD DEFAULT !(commented out)
00A8  3C 80     252        LD   rAC,#128    ! POSITION SINGLE BIT
00AA  90 E3     253        RL   rAC         ! (THIS MAY TAKE A WHILE
00AC  2A FC     254        DJNZ rACX,#-2    !  BUT WHO CARES?)
00AE  A6 E3 20  255        CP   rACX,#32    ! IF NOT 110,
00B1  6B 02     256        JR   EQ $+4      !  (110 BAUD ALREADY SET)
00B3  39 F4     257        LD   T0R,rAC     !  THEN FIX UP TIMER
00B5  9F        258        EI               ! *&%$#@ UART
00B6  76 03 01  259        TM   PORT3,#1    ! IS BREAK SET?

 

Listing 2:New code (new comments in lower case).

008C  31 F0     236 RESET: SRP  #RPx        ! MAKE =WORK, SO SHORT
008E  B0 FB     237        CLR  IRQ+1       ! CLEAR INTERRUPT MASK
0090  8C 96     238        LD   rP01M,#150  ! RAM, FAST, INT STK
                239                         ! (10010110)
0092  FC 68     240        LD   rSPL,#ISTAK ! STACK POINTER
0094  4C FF     241        LD   rT0R,#255   ! magic location %95 for T0
0096  5C FF     242        LD   rT0Rp1,#255 ! " " %97 for PRE0
0098  7C 41     243        LD   rP3M,#65    ! SERIAL I/O (01000001)
009A  1C 03     244        LD   rTMR,#0     ! START UART CLOCK (%03)
009C  CC 02     245        LD   rFLAGS,#2   ! SET XEQ
009E  31 10     246        SRP  #AC         ! note cleanup of low nybble
00A0  B0 03     247        CLR  PORT3
00A2  8D 00 B5  248        JP   00B5        ! jump over NOPs
00A4  FF FF     249        NOP
00A6  FF FF     250        NOP
                251
00A8  FF FF     252        NOP
00AA  FF FF     253        NOP
00AC  FF FF     254        NOP
00AE  FF FF FF  255        NOP
00B1  FF FF     256        NOP
00B3  FF FF     257        NOP
00B5  9F        258        EI              ! *&%$#@ UART
00B6  76 03 01  259        TM   PORT3,#1   ! IS BREAK SET?

 

Listing 3:Pure hex code for the interpreter.

1000100310061009100C100F8B7EE33F
FEE32FFEAF3C20D60061762007EBF6AF
065020081B0D0AFED600813C05D6063E
D60066D60643EBF8B02000ED52355224
AFD6004728E30DB0E24E4A03E3350DC2
34A0E4AF66FB882D101276FA086BFB38
F0202056E37F66FB882D101556FAE739
F076FA106BFBAFD605FAA0E4D6008138
E24E4A03F3530DD23480E4AF31F0B0FB
8CB6FCF04CFF5CFF7C411C03CC023110
B003D2668D00B5FFFFFFFFFFFFFFFFFF
FFFFFFFFFF9F7603016B574C07D605BF
7B17EBF94908D605BF7B026BF900E449
0C490AB009E60B200DB00CCC00DC204C
0F5C20D605BF6B0C2E2A09E408045905
490859093C02D6063E480858092CFFD2
24A0E4D224C2242EEB0A023512242904
3905B0FC3100DC68E6F8B2CECA07B0EA
BC68E6F8B668EA78EB3110E406FEE407
FF98FC56E902FC80D6063C88E3C23C02
936CFF7CFFC238A0E81C1FA6E30A7B5B
A6E3307B18A6E3407B3FB0E052136B04
0219120856E3E0F0E306E3040D023306
E35F2C05C2E2A0E2C23228EED4E23110
8BC376FC026BA2D604DD6B86D6063C88
E3C29CD603926B6AAFC218A0E80C0752
0326E00406E308C0E38BB5023FE303E3
1FF331F3F08BC950E250E350E050E18B
0B50E250E370E970E8D601FAD602558B
AFD6000E50E050E170E370E2D601FA8B
4448EA58EBC228A0E8D605D322236BF5
12226B65A8E4B8E58B573100CECA05A6
FF408B08A4E4FEEB03A4E5FF31108B73
50E050E1A40AFEEB03A40BFFFB6750E2
50E3D6026EE4FE06E4FF078BA2D6000E
D6026E8B3900EFB1EFC238A0E88B33D6
05FA023512248B2626E12036E0000D80
EA42006B3088E098E1AFD605D3A6E341
7BEDA6E35ABBE8023306E3A0280C00EF
F3F200EFF3F3A6EF403B0A440C0CEBD9
A40DEFBBD4D604A0D6063CC22C229232
8338E928E8FC80D604E99C4A8C06D605
5676FC026B0AD6055638172816D604E9
D6002BB0FC8D0129D605D36B4D8B90D6
05D39B8B56E30FD60638D605D39B3B1C
0AD603148BF4D6000EB0E0B0E1EC1122
133202FB0402131202EF11EFFE11EF00
EF10E110E0EAE8AFD60636D605D31B0D
A6E3417B0526E3477B0380EAAF1C10D6
03148BE7B0E056E30F8B08E31FFEE30F
FEB0E3B0E2EC11CFFEC1EF00EFC1EFFB
0402311220C0E2C0E3EAEDAFD60061DF
D605D46BC5A6E3226B2A8BF0D605FDA8
08B80908E618E7D604CF8B03D604DDA2
46EB02A257BBF56B0DC2E8A6EE286B06
78E168E0A0E8AF380E0D38EAA40CE3EB
05A90EB90FAF280E380FD60381A8E2B8
E3AF66FB882B0C3C04D6063EB4F0E302
336BD338FC46E3FE3EEBC9AFD60049EE
3E3AF9AF480E580FB0EED603ACD6000E
58EB48EA80EA80EADF3273326278E3FB
3BEA04ECFD2CFFEE60EED603AC60EE6B
54DB2F58EB48EA08E418E5225E36E4FF
D6004FD230A0E0A404147BF4A405157B
EF090419052E6B4100E28B29EA01AFEE
EEEE5805480418E508E4025E16E400D6
020449045905C23080E0D60087A24ABB
F5A25BBBF1D22AA0EAD27A480E580FA0
EAD60049D23A3E3AF6AF00EFE60D67A8
0CBC68200DD6005428E33C03D6063EA2
326B36C23CA2326B3742226BE8A6E27F
6BE3A6E20A6BDE580D480C3C0DB2326D
0027D6007FA60DE7BB084E4AC6A40DEF
BBC13C07D600668BBC000DA40DEB3BB5
E60D682C0D8BD0D6000EE3EFFE233FFE
332F1B0AAB0442326B02E0EEE0EEE0EE
FB02A0E8E33FFEAFE6FC0280EA80EAC2
6AA0EAC27AA0EAE8E652E7EEAFC23AA0
EA3E3AF98BE9D6000EEC10B0E1B0E012
331222121140E1120040E0EAF200EFF3
F000EFF3F112336B08D605443CEEFE8B
173CEEFE2CF0532FEB0E06E3066B0943
2FEB0506E306FAEC06E3412C0530E2FF
E33FD60545E33FD6054400EFE33FD605
45D6000E0DF0E356E30F2C09A22316E3
3040E38D0061C238D60061C238A0E83E
DBF4AF01C102550248025101E1025A02
BF02B8039202390235022D000E061303
7A03770627007701D10210034C061C02
3F1018031B02D604A70182101B101E04
E6033F0015002B0556051102F8044A06
2F04DD03B400F404C80112060401B7DF
4E6B0FC23460E3D23460E3C224D23412
32CFAFCFAEAA03E33B0DC23AA0EA7B17
A6E3206BEEA6E3607B0326E320A6E330
1B05A6E33A1B024233AFD6000EE35FFE
E34FFEAFD605FAE31FFEE30FFED4E031
108B20D6061C4222DB02A0E8D6000E60
E260E3A0E28B0CD605FDD600418B0428
E638E78D026EB0E3B0E28BF7B0E356ED
F042D3C23CDEA6E3FEAF2187204154A0
627A6F24BA27E15BD30F60100D16280E
2A5110110C0016280F600E2C8F47CF9B
54CF351CE010110F601650609D49C634
E884544845CE1C1DC14A41895355C234
FFE028145480C034F07A9B4C45D4A680
BD34ED137184DE3525559AC00C81351E
80BD34DC2E0EE11D83BA3BB082A27B9D
5052494ED483BA2351EE6883BBE71D83
AC225A234182BA4285A221604E748848
4558A83516254434A7170F6324AD6117
20548C5245D4835552CEE015161D6086
53544FD0E02D855255CE3B56854E45D7
E02B845245CD1D9D49CE865055D4A010
63A010E6243FA027E15A81AC34621311
82AC4E3B818C4C4953D428E80CFF170C
7F673B5A3446E00301030216280E230A
740D0B03281C6E280F6A2024A0216324
A25B294A0E0E161D1D34258EBC84BD0B
067684BE0B05710B046E89BE84BD0B03
670B016480BD0B0267340162340297AC
85AD3414176481AB340E85AB340A185A
86AD340417580D2F342485AA34201A5A
92AF170F6734170F711B174E17340F0F
651B4794DC57170F634F170F60538A55
5352A833B480A92E2F89414E44A80C3C
33AA5287C00C4733E50D4C84DE33DF61
A2122F83A5262FC12F80A8339380A92F