**Part 6: Simplifying capture on the Beeb Model B**
It's been pointed out that one of the barriers to more widespread use of this logic analyzers for debugging is the practicality of connecting to the various signals on the 6502. I'm using a professional Pomona 40-pin DIP test clip, but these are quite pricey (£20-£40):

On the Model B, almost all the necessary 6502 signals appear on the Tube connector, so wouldn't it be nice if you could just connect your £15 USB Logic Analyzer directly to that?

Specifically, the Tube Connector has the following signals (plus a few more we don't use):

- 2MHzE

- D0..7

- RnW

- RST

Unfortunately, there is one crucial missing signal, sync, which is used by the 6502 to mark the beginning of the each instruction (i.e. the cycle where the opcode is being fetched). The first version of the 6502 bus protocol decoder made very extensive use of sync to determine the boundaries between instructions.

It turns out that with a little ingenuity its possible to get some very decent results without using sync. But the decoder needs to be much more aware how the 6502 works, including:

- the minimum number of bus cycles for each instruction

- taken branches take an extra cycle (i.e. 3 cycles rather than 2 cycles)

- certain addressing modes take an extra cycle when a page is crossed

By knowing exactly how many cycles an instruction takes, it should be possible to lock on, and stay locked on, to an instruction stream. There's a good analogy here to a disassembler. Even if you start disassembling at a random address, pretty soon you will hit the correct instruction alignment and then you stay aligned.

Where it gets complicated is that to be able to predict whether branches are taken means the decoder has to model each of the 6502 flags. Similarly, to predict whether "LDA absolute, X" takes 4 or 5 cycles, it has to know the value of the X register. So it starts to become more like a full 6502 emulator, but one that has to deal with uncertainty, because initially none of the register or flag values are known.

So, with this goal in mind, over the last couple of weeks I've been rewriting the decoder. It now has it's own github repository (

here), and it's been re-written now as a standalone C program. Which means it runs about 200x faster than the original python program.

Here's a photo of the cheap USB logic analyzer hooked up to the Tube connector:

The connections are:

Code: Select all

```
Tube Connector -> Logic Analyzer
------------- --------------
Pin 1 (0V) -> GND
Pin 2 (RnW) -> PD0
Pin 4 (2MHzE) -> PD3
Pin 10 (NRST) -> PD6
Pin 11 (0V) -> GND
Pin 12 (D0) -> PB0
Pin 14 (D1) -> PB1
Pin 16 (D2) -> PB2
Pin 18 (D3) -> PB3
Pin 20 (D4) -> PB4
Pin 22 (D5) -> PB5
Pin 24 (D6) -> PB6
Pin 26 (D7) -> PB7
```

I'm still using sigrok-cli to capture the data (to a binary file):

Code: Select all

```
$ sigrok-cli -d fx2lafw --config samplerate=12MHz:captureratio=1 -o data1.bin -O binary --triggers D14=r --samples=12M
```

The trigger for here is the rising edge of reset, and we have captured 1 second of data (12 million samples).

You then then process the binary capture file with the new 6502 protocol decoder:

Code: Select all

```
$ decode6502 -h -s --sync= <data.bin >data.txt
```

The --sync= param tells it the sync signal is not connected, and causes it to switch to the syncless decoding algorithm.

And here's the result:

Code: Select all

```
???? : : 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
....
D9EE : 91 00 : STA (00),Y A=00 X=7F Y=FF SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9F0 : C5 01 : CMP 01 A=00 X=7F Y=FF SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9F2 : F0 09 : BEQ D9FD A=00 X=7F Y=FF SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9F4 : C8 : INY A=00 X=7F Y=00 SP=FE N=0 V=? D=0 I=1 Z=1 C=0
D9F5 : D0 F7 : BNE D9EE A=00 X=7F Y=00 SP=FE N=0 V=? D=0 I=1 Z=1 C=0
D9F7 : C8 : INY A=00 X=7F Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
D9F8 : E8 : INX A=00 X=80 Y=01 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9F9 : E6 01 : INC 01 A=00 X=80 Y=01 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9FB : 10 F1 : BPL D9EE A=00 X=80 Y=01 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
D9FD : 8E 8E 02 : STX 028E A=00 X=80 Y=01 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
DA00 : 8E 84 02 : STX 0284 A=00 X=80 Y=01 SP=FE N=1 V=? D=0 I=1 Z=0 C=0
DA03 : A2 0F : LDX #0F A=00 X=0F Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
DA05 : 8E 42 FE : STX FE42 A=00 X=0F Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
DA08 : CA : DEX A=00 X=0E Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
DA09 : 8E 40 FE : STX FE40 A=00 X=0E Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=0
DA0C : E0 09 : CPX #09 A=00 X=0E Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0E : B0 F8 : BCS DA08 A=00 X=0E Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA08 : CA : DEX A=00 X=0D Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA09 : 8E 40 FE : STX FE40 A=00 X=0D Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0C : E0 09 : CPX #09 A=00 X=0D Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0E : B0 F8 : BCS DA08 A=00 X=0D Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA08 : CA : DEX A=00 X=0C Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA09 : 8E 40 FE : STX FE40 A=00 X=0C Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0C : E0 09 : CPX #09 A=00 X=0C Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0E : B0 F8 : BCS DA08 A=00 X=0C Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA08 : CA : DEX A=00 X=0B Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA09 : 8E 40 FE : STX FE40 A=00 X=0B Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0C : E0 09 : CPX #09 A=00 X=0B Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0E : B0 F8 : BCS DA08 A=00 X=0B Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA08 : CA : DEX A=00 X=0A Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA09 : 8E 40 FE : STX FE40 A=00 X=0A Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0C : E0 09 : CPX #09 A=00 X=0A Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0E : B0 F8 : BCS DA08 A=00 X=0A Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA08 : CA : DEX A=00 X=09 Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA09 : 8E 40 FE : STX FE40 A=00 X=09 Y=01 SP=FE N=0 V=? D=0 I=1 Z=0 C=1
DA0C : E0 09 : CPX #09 A=00 X=09 Y=01 SP=FE N=0 V=? D=0 I=1 Z=1 C=1
DA0E : B0 F8 : BCS DA08 A=00 X=09 Y=01 SP=FE N=0 V=? D=0 I=1 Z=1 C=1
```

You can see initially the register state is unknown, but as successive instructions are executed it becomes known.

The above example started with a RESET, so here's a harder case, starting in the middle of a running BBC Basic program:

Code: Select all

```
???? : 01 8A : ORA (8A,X) A=?? X=?? Y=?? SP=?? N=? V=? D=? I=? Z=? C=?
???? : 98 : TYA A=?? X=?? Y=?? SP=?? N=? V=? D=? I=? Z=? C=?
???? : 48 : PHA A=00 X=?? Y=?? SP=?? N=? V=? D=? I=? Z=? C=?
???? : BA : TSX A=00 X=?? Y=?? SP=?? N=? V=? D=? I=? Z=? C=?
???? : BD 03 01 : LDA 0103,X A=01 X=?? Y=?? SP=?? N=0 V=? D=? I=? Z=0 C=?
???? : 48 : PHA A=01 X=?? Y=?? SP=?? N=0 V=? D=? I=? Z=0 C=?
???? : 2C 60 02 : BIT 0260 A=01 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=?
???? : 10 08 : BPL pc-8 A=01 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=?
???? : 18 : CLC A=01 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
???? : A9 02 : LDA #02 A=02 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=0 C=0
???? : 2C 7C 02 : BIT 027C A=02 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
???? : D0 05 : BNE pc-5 A=02 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
???? : 68 : PLA A=01 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=0 C=0
???? : 48 : PHA A=01 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=0 C=0
???? : 20 C0 C4 : JSR C4C0 A=01 X=?? Y=?? SP=?? N=0 V=0 D=? I=? Z=0 C=0
C4C0 : AE 6A 02 : LDX 026A A=01 X=FD Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C4C3 : D0 4D : BNE C512 A=01 X=FD Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C512 : 9D 24 02 : STA 0224,X A=01 X=FD Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C515 : E8 : INX A=01 X=FE Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C516 : 8E 6A 02 : STX 026A A=01 X=FE Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C519 : D0 17 : BNE C532 A=01 X=FE Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C532 : 18 : CLC A=01 X=FE Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
C533 : 60 : RTS A=01 X=FE Y=?? SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0C8 : A9 08 : LDA #08 A=08 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=0 C=0
E0CA : 2C 7C 02 : BIT 027C A=08 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0CD : D0 02 : BNE E0D1 A=08 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0CF : 90 05 : BCC E0D6 A=08 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0D6 : AD 7C 02 : LDA 027C A=00 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0D9 : 6A : ROR A A=00 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0DA : 90 1B : BCC E0F7 A=00 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0F7 : A9 10 : LDA #10 A=10 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=0 C=0
E0F9 : 2C 7C 02 : BIT 027C A=10 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0FC : D0 0F : BNE E10D A=10 X=FE Y=?? SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0FE : AC 57 02 : LDY 0257 A=10 X=FE Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E101 : F0 0A : BEQ E10D A=10 X=FE Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E10D : 68 : PLA A=01 X=FE Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E10E : 68 : PLA A=00 X=FE Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E10F : A8 : TAY A=00 X=FE Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E110 : 68 : PLA A=37 X=FE Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E111 : AA : TAX A=37 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E112 : 68 : PLA A=01 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E113 : 60 : RTS A=01 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
941F : 20 56 94 : JSR 9456 A=01 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
9456 : A5 2A : LDA 2A A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
9458 : 6C 0E 02 : JMP (020E) A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0A4 : 48 : PHA A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0A5 : 8A : TXA A=37 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E0A6 : 48 : PHA A=37 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E0A7 : 98 : TYA A=00 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0A8 : 48 : PHA A=00 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0A9 : BA : TSX A=00 X=37 Y=00 SP=?? N=? V=0 D=? I=? Z=? C=0
E0AA : BD 03 01 : LDA 0103,X A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0AD : 48 : PHA A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0AE : 2C 60 02 : BIT 0260 A=C7 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0B1 : 10 08 : BPL E0BB A=C7 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0BB : 18 : CLC A=C7 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0BC : A9 02 : LDA #02 A=02 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=0 C=0
E0BE : 2C 7C 02 : BIT 027C A=02 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0C1 : D0 05 : BNE E0C8 A=02 X=37 Y=00 SP=?? N=0 V=0 D=? I=? Z=1 C=0
E0C3 : 68 : PLA A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0C4 : 48 : PHA A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
E0C5 : 20 C0 C4 : JSR C4C0 A=C7 X=37 Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
C4C0 : AE 6A 02 : LDX 026A A=C7 X=FE Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
C4C3 : D0 4D : BNE C512 A=C7 X=FE Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
C512 : 9D 24 02 : STA 0224,X A=C7 X=FE Y=00 SP=?? N=1 V=0 D=? I=? Z=0 C=0
```

It takes a bit longer to "lock on", and SP and D remain unknown. This was the SPHERE benchmark by the way.

Here's the full help for the decode6502 command:

Code: Select all

```
$ 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.
-c, --c02 Enable 65C02 mode.
--data=BITNUM The start bit number for data
-d, --debug=LEVEL Sets debug level (0 1 or 2)
-h, --hex Show hex bytes of instruction.
--phi2[=BITNUM] The bit number for phi2, blank if unconnected
--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
--sync[=BITNUM] The bit number for sync, blank if unconnected
-s, --state Show register/flag state.
-u, --undocumented Enable undocumented 6502 opcodes (currently
incomplete)
-?, --help Give this help list
--usage Give a short usage message
-V, --version Print program version
Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.
Report bugs to <dave@hoglet.com>.
```

I'm using decode6502 on Linux (Ubuntu 16.04), but it should be possible to build it using the bash shell on Window 10.

If anyone wants to take this for a spin, please do ask for help if needed. It would be great to have someone try this on a Beeb that was failing to start for example. It should then be possible to narrow down the fault very quickly indeed.

Dave

P.S. This isn't quite as straight forward on the Master. The external tube is buffered, so the internal tube would have to be used. And also the master uses Rdy rather than cycle stretching, so one additional wire is still required, at least currently.