-
Notifications
You must be signed in to change notification settings - Fork 10
Home
The documentation for this project is at an early stage, so please bear with me. If you have any specific questions, please do ask them in the thread over on Stardot.
Logic analyzers are widely available, yet they are seldom the tool of choice when it comes to debugging 6502-based computer systems. There are a number of reasons for this:
-
To follow what the 6502 is doing, it's typically necessary to monitor the data bus (8 signals), the address bus (16 signals) plus a set of miscellaneous control lines (7 signals). This means a 32-channel logic analyzer must be used. These are out of the price range of many hobbyists, and time consuming to hook up.
-
It can be quite involved to work backwards from the values of externally visible bus signals to piece together then instruction stream being executed.
-
Often the point of interest (a system malfunction), can be buried in many millions of correctly executed instructions, and conventional logic analyzers interfaces become unwieldy with this amount of data.
This project enables a cheap (<£10) 16-channel USB logic analyzer to be used as an effective diagnostic tool for 6502-based computer systems, overcoming each of the above issues:
-
Minimally just Phi2 (the system clock) and D7..D0 (the data bus) need to be connected. Adding just a couple more control lines (Sync, RnW) can improve the results in certain cases, but these are optional.
-
The values on the data bus are used to reconstruct the full 6502 machine state, including the internal processor registers, the external memory state, and the stream of instructions being executed.
-
Configurable triggers allow the user to set the conditions required for decoding to commence.
The motivation for this project came from the author's experiences trying to use a variety of "classic" HP logic analyzers to fix broken 1980's vintage Acorn microcomputers.
The HP 1650A is quite limited by modern standards, and only has a capture depth of 1024 samples. Optional software, called by HP an Inverse Assembler, does allow some understanding of the instruction stream. But the user interface is very poor.
The HP 16702B is a much more capable device (being based on a 150MHz PA-RISC Processor and running HP-UX internally). Yet the Inverse Assembler also extremely difficult to use effectively.
I then stumbled across Sigrok, an Open-Source signal analysis software suite that works with many different USB logic analyzers. It allows custom protocol decoders to be developed in python, and ships with one for the Z80.
Inspired by this, I started work on the 6502 Protocol Decoder for Sigrok. At the same time, I started blogging my experiences in a series of posts on stardot: Open Source Logic Analyzer Experiments
It quickly became apparent that Sigrok and it's python protocol decoders were painfully slow for this type of application. Decoding 1-seconds worth of 6502 bus data was taking 1-2 minutes (on my 2009 vintage Linux workstation).
Hence the current version of this tool is a standalone C program, which runs ~100x faster then the python code in Sigrok.
I've written up the adventures as a set of posts over on stardot, entitled Open Source Logic Analyzer Experiments:
- Part 1: An Introduction to Sigrok and Logic Sniffer
- Part 2: Probing the 6502 with Sigrok
- Part 3: Writing a 6502 Protocol Decoder
- Part 4: Synchronous capture, triggers and sigrok-cli
- Part 5: Using an uber-cheap FX2LP development board
- Part 6: Simplifying capture on the Beeb Model B
- Part 7: Using Sigrok-cli / FX2 Logic Analyzer / 6502 Decoder on Windows
$ decode6502 -h -s --sync= <data.bin >data.txt
results in:
???? : : RESET !! A=?? X=?? Y=?? SP=?? N=? V=? D=? I=1 Z=? C=?
D9CD : A9 40 : LDA #40 A=40 X=?? Y=?? SP=?? N=0 V=? D=? I=1 Z=0 C=?
D9CF : 8D 00 0D : STA 0D00 A=40 X=?? Y=?? SP=?? N=0 V=? D=? I=1 Z=0 C=?
D9D2 : 78 : SEI A=40 X=?? Y=?? SP=?? N=0 V=? D=? I=1 Z=0 C=?
D9D3 : D8 : CLD A=40 X=?? Y=?? SP=?? N=0 V=? D=0 I=1 Z=0 C=?
D9D4 : A2 FF : LDX #FF A=40 X=FF Y=?? SP=?? N=1 V=? D=0 I=1 Z=0 C=?
D9D6 : 9A : TXS A=40 X=FF Y=?? SP=FF N=1 V=? D=0 I=1 Z=0 C=?
D9D7 : AD 4E FE : LDA FE4E A=80 X=FF Y=?? SP=FF N=1 V=? D=0 I=1 Z=0 C=?
D9DA : 0A : ASL A A=00 X=FF Y=?? SP=FF N=0 V=? D=0 I=1 Z=1 C=1
D9DB : 48 : PHA A=00 X=FF Y=?? SP=FE N=0 V=? D=0 I=1 Z=1 C=1
D9DC : F0 09 : BEQ D9E7 A=00 X=FF Y=?? SP=FE N=0 V=? D=0 I=1 Z=1 C=1
D9E7 : A2 04 : LDX #04 A=00 X=04 Y=?? SP=FE N=0 V=? D=0 I=1 Z=0 C=1
D9E9 : 86 01 : STX 01 A=00 X=04 Y=?? SP=FE N=0 V=? D=0 I=1 Z=0 C=1
D9EB : 85 00 : STA 00 A=00 X=04 Y=?? SP=FE N=0 V=? D=0 I=1 Z=0 C=1
D9ED : A8 : TAY A=00 X=04 Y=00 SP=FE N=0 V=? D=0 I=1 Z=1 C=1
D9EE : 91 00 : STA (00),Y A=00 X=04 Y=00 SP=FE N=0 V=? D=0 I=1 Z=1 C=1
D9F0 : C5 01 : CMP 01 A=00 X=04 Y=00 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9F2 : F0 09 : BEQ D9FD A=00 X=04 Y=00 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9F4 : C8 : INY A=00 X=04 Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
D9F5 : D0 F7 : BNE D9EE A=00 X=04 Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
There are a growing number of command line options. For now, please refer to the built-in help.
dmb@quadhog:~/atom/6502Decoder$ ./decode6502 --help
Usage: decode6502 [OPTION...] [FILENAME]
Decoder for 6502/65C02 logic analyzer capture files.
FILENAME must be a binary capture file with 16 bit samples.
If FILENAME is omitted, stdin is read instead.
The default bit assignments for the input signals are:
- data: bit 0 (assumes 8 consecutive bits)
- rnw: bit 8
- sync: bit 9
- rdy: bit 10
- phi2: bit 11
- rst: bit 14
To specify that an input is unconnected, include the option with an empty
BITNUM. e.g. --sync=
If phi2 is not connected the capture file should contain one sample per
falling edge of phi2.
If rdy is not connected a value of '1' is assumed.
If sync is not connected a heuristic based decoder is used. This works well,
but can take several instructions to lock onto the instruction stream.
Use of sync, is preferred.
If RST is not connected, an alternative is to specify the reset vector:
- D9CD (D9 is the high byte, CD is the low byte)
- A9D9CD (optionally, also specify the first opcode, LDA # in this case)
-a, --address Show address of instruction.
-b, --byte Byte samples
-c, --c02 Enable 65C02 mode.
--data=BITNUM The start bit number for data
-d, --debug=LEVEL Sets debug level (0 1 or 2)
-e, --emulate Enable emulation, for error checking.
-f, --bbcfwa Show BBC floating poing work areas.
-h, --hex Show hex bytes of instruction.
-i, --instruction Show instruction.
-m, --machine=MACHINE Enable machine specific behaviour
--phi2[=BITNUM] The bit number for phi2, blank if unconnected
-p, --profile[=PARAMS] Profile code execution.
-q, --quiet Set all the show options to off.
--rdy[=BITNUM] The bit number for rdy, blank if unconnected
--rnw[=BITNUM] The bit number for rnw
--rst[=BITNUM] The bit number for rst, blank if unconnected
-r, --rockwell Enable additional rockwell instructions.
--sync[=BITNUM] The bit number for sync, blank if unconnected
-s, --state Show register/flag state.
-t, --trigger=ADDRESS Trigger on address.
-u, --undocumented Enable undocumented 6502 opcodes (currently
incomplete)
--vecrst[=HEX] The reset vector, black if not known
-y, --cycles Show number of bus cycles.
-?, --help Give this help list
--usage Give a short usage message
-V, --version Print program version