# Haha – Got It!

With my usual fantastic-collection-of-stamps approach I think I figured out why my Olduino/Z prototype isn’t working.

I hooked up my logic analyzer to capture 4 bits of address and a few control signals (/reset,/rd,/m1,/mreq) and grabbed the first few milliseconds of execution after a reset. I dumped that to ascii (many many lines of ascii) and wrote a python program to fish out all the memory read accesses with /m1 active – sort of a crappy instruction trace with only the bottom hex digit of the address.

Time[s], A0, A1, A2, A3, /OE(/rd), /MREQ, /M1, /RST 7, 1, 1, 1, 1, 1, 1, 1, 0 7.052647875, 1, 1, 1, 1, 1, 1, 1, 1 7.0526485, 0, 0, 0, 0, 1, 1, 0, 1 7.052648625, 0, 0, 0, 0, 1, 0, 0, 1 7.05264875, 0, 0, 0, 0, 0, 0, 0, 1 7.052649, 0, 0, 0, 0, 1, 1, 1, 1 7.052649125, 0, 0, 0, 0, 1, 0, 1, 1 7.052649375, 0, 0, 0, 0, 1, 1, 1, 1 7.0526495, 1, 0, 0, 0, 1, 1, 0, 1 7.052649625, 1, 0, 0, 0, 1, 0, 0, 1 7.05264975, 1, 0, 0, 0, 0, 0, 0, 1

def address(a0ton): a=0 for n in range(len(a0ton)): if a0ton[n]==' 1': a=a+2**n # print a0ton,"sez",a return a fn=raw_input("file name:") if len(fn)==0: fn="4b100" fn=fn+".csv" print fn file=open(fn) oldrd=1 linenum=0 for line in file: linenum=linenum+1 line=line.rstrip() # print line toks=line.split(',') #Time[s], A0, A1, A2, A3, /OE(/rd), /MREQ, /M1, /RST # print toks if toks[0]=="Time[s]": continue time=float(toks[0]) ax=toks[1:5] notrd=int(toks[5].strip()) notm1=int(toks[7].strip()) notrst=int(toks[8].strip()) if notrst=="0": print "spinning for reset" continue if (notrd==0) and (oldrd==1): #a memory read event if notm1==0:#opcode read print "\n",linenum,"\t",format(address(ax),'X'), else:#opex read print format(address(ax),'X'), oldrd=notrd print

>python tracer4.py file name:4bits 4bits.csv 6 0 12 1 18 2 24 3 4 35 8 9 A 55 B 0 1 69 C D E 89 F 95 0 1 2 115 3 4 5 129 6 141 7 153 8 165 9 171 A 177 B C D 191 E 203 F 214 0 226 1 236 2 241 3 246 4 251 5 256 6 261 7 266 8 271 9 276 A 287 B 292 C 303 D 308 E 319 F 0 1 330 2 3 338 4 5 347 6 7 355 8 9 0 366 A 371 B C 379 D E 387 5 6 7 398 8 9 406 A B 0 417 C D 426 E 432 F 0 1 444 8 450 9 456 A 462 B C 471 D E 482 F 0 492 A B 0 505 C D 515 E 521 F 0 1 535 2 541 3 4 5 555 6 7 565 B C 574 D E 585 F 0 596 A B 0 608 C D 618 E 624 F 0 1 638 2 644 3 4 5 657 6 7 668 B C 678 D E 689 F 0 700 A B 0 712 C D 722 E 728 F 0 1 742 2 748 3 4 5 762 6 7 773 B C 783 D E 794 F 0 803 A B 0 814 C D 822 E 827 F 0 1 838 2 843 3 4 5 854 6 7 862 B C 870 D E 879 F 0 887 A B 0 898 C D 906 E 911 F 0 1 921 2 926 3 4 5 937 6 7 945 B C 953 D E 964 F 0 973 A B 0 985 C D 994 E 1000 F 0 1 1012 2 1018 3 4 5 1030 6 7 1040 B C 1050 D E 1061 F 0 1070 A B 0 1082 C D 1092 E 1098 F 0 1 1112 2 1118 3 4 5 1132 6 7 1142 B C 1152 D E 1163 F 0 1174 A B 0 1185 C D 1195 E 1201 F 0 1 1215 2 1221 3 4 5 1235 6 7 1246 B C 1256 D E 1267 F 0 1278 A B 0 1290 C D 1300 E 1306 F 0 1 1320 2 1326 3 4 5 1340 6 7 1351 B C 1359 D E 1369 F 0 1377 A B 0 1388 C D 1396 E 1401 F 0 1 1412 2 1417 3 4 5 1427 4 5 6 0 1 1443 7 8 1451 9 1456 A 1461 B C 1469 D 1474 E 1479 F 0 1 1490 2 3 4 1501 2 3 4 <and so ad nauseam>

With that I was able to step through the soucecode and see that the monitor checks for the front panel then, failing that it looks at the first part of RAM to see if it looks valid and if not, it loops. That’s fair but I don’t think it re-enables interrupts before it loops so the thing just sits there dead. I have a query in to Josh and in the mean time I’ll get busy on replacing the eprom with an eeprom that i can program myself.

I’m pretty sure now I could squeeze out some more address bits by externally combining /rd /mreq/ and /m1 to only show instruction fetches. I also think I could probably have found the issue if i’d just read through the initialization sequence but the monitor program is 80 pages and somewhat intimidating.

Among the random things I learned is that the Z80 keeps /m1 low for both bytes of a multi-byte op code. I had not known that.