Skip to content

Commit

Permalink
Make 'tap2sna.py --tape-analysis' show EAR bit readings
Browse files Browse the repository at this point in the history
Also update the description of the 'first-edge' configuration parameter.
  • Loading branch information
skoolkid committed Jul 26, 2023
1 parent c43cc9e commit c0d6745
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 60 deletions.
29 changes: 18 additions & 11 deletions skoolkit/loadtracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,28 +82,34 @@ def __getitem__(self, key):
return self.registers[REGISTERS[key]]

def get_edges(blocks, first_edge, analyse=False):
edges = [first_edge]
edges = []
if first_edge >= 0:
edges.append(first_edge)
indexes = []
data_blocks = []
tstates = first_edge

if analyse:
print('T-states Description')
print('T-states EAR Description')

for i, (timings, data) in enumerate(blocks):
# Pilot tone
if analyse and timings.pilot_len:
print(f'{tstates:>10} Tone ({timings.pilot_len} x {timings.pilot} T-states)')
ear = (len(edges) - 1) % 2 if edges else '-'
print(f'{tstates:>10} {ear:>3} Tone ({timings.pilot_len} x {timings.pilot} T-states)')
for n in range(timings.pilot_len):
tstates += timings.pilot
edges.append(tstates)
if tstates >= 0:
edges.append(tstates)

# Sync pulses
for s in timings.sync:
if analyse:
print(f'{tstates:>10} Pulse ({s} T-states)')
ear = (len(edges) - 1) % 2 if edges else '-'
print(f'{tstates:>10} {ear:>3} Pulse ({s} T-states)')
tstates += s
edges.append(tstates)
if tstates >= 0:
edges.append(tstates)

# Data
if data:
Expand All @@ -114,9 +120,8 @@ def get_edges(blocks, first_edge, analyse=False):
else:
bits = ''
data_len = len(data)
print(f'{tstates:>10} Data ({data_len} bytes{bits}; {timings.zero}/{timings.one} T-states)')
while edges[0] < 0:
edges.pop(0)
ear = (len(edges) - 1) % 2 if edges else '-'
print(f'{tstates:>10} {ear:>3} Data ({data_len} bytes{bits}; {timings.zero}/{timings.one} T-states)')
start = len(edges) - 1
for k, b in enumerate(data, 1):
if k < len(data):
Expand All @@ -130,7 +135,8 @@ def get_edges(blocks, first_edge, analyse=False):
duration = timings.zero
for k in range(2):
tstates += duration
edges.append(tstates)
if tstates >= 0:
edges.append(tstates)
b *= 2
indexes.append((start, len(edges) - 1))
data_blocks.append(data)
Expand All @@ -143,7 +149,8 @@ def get_edges(blocks, first_edge, analyse=False):
# Pause
if i + 1 < len(blocks) and timings.pause:
if analyse:
print(f'{tstates:>10} Pause ({timings.pause} T-states)')
ear = (len(edges) - 1) % 2 if edges else '-'
print(f'{tstates:>10} {ear:>3} Pause ({timings.pause} T-states)')
tstates += timings.pause

return edges, indexes, data_blocks
Expand Down
7 changes: 5 additions & 2 deletions skoolkit/tap2sna.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,8 +893,11 @@ def _print_sim_load_config_help():
Set the time (in T-states) from the start of the tape at which to place the
leading edge of the first pulse (default: -2168). The default value places
the trailing edge of the first pulse at time 0, but some loaders (e.g.
polarity-sensitive loaders) require first-edge=0.
the edge between the first and second pulses on the tape at time 0. Any
pulses that occur before time 0 are discarded. The EAR bit reading yielded by
a pulse is 0 if the 0-based index of the pulse is even (i.e. first, third,
fifth pulses etc.), or 1 otherwise. Some loaders require first-edge=0, which
effectively reverses the polarity of every pulse on the tape.
--sim-load-config load=KEYS
Expand Down
13 changes: 10 additions & 3 deletions sphinx/source/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1398,9 +1398,7 @@ parameters are:
simulation as soon as that address is reached, regardless of whether the tape
has finished (``0``, the default)
* ``first-edge`` - the time (in T-states) from the start of the tape at which
to place the leading edge of the first pulse (default: ``-2168``); the
default value places the trailing edge of the first pulse at time 0, but some
loaders (e.g. polarity-sensitive loaders) require ``first-edge=0``
to place the leading edge of the first pulse (default: ``-2168``)
* ``load`` - a space-separated list of keys to press to build an alternative
command line to load the tape (see below)
* ``machine`` - the type of machine to simulate: a 48K Spectrum (``48``, the
Expand All @@ -1414,6 +1412,15 @@ parameters are:
* ``trace`` - the file to which to log all instructions executed during the
simulated LOAD (default: none)

The default value of the ``first-edge`` parameter (-2168) places the edge
between the first and second pulses on the tape at time 0. Any pulses that
occur before time 0 are discarded. The EAR bit reading yielded by a pulse is 0
if the 0-based index of the pulse is even (i.e. first, third, fifth pulses
etc.), or 1 otherwise. Some loaders require ``first-edge=0``, which effectively
reverses the polarity of every pulse on the tape. Run *tap2sna.py* with the
``--tape-analysis`` option to see the timings and EAR bit readings of the
pulses on a tape.

The ``accelerator`` parameter must be either a comma-separated list of specific
accelerator names or one of the following special values:

Expand Down
13 changes: 10 additions & 3 deletions sphinx/source/man/tap2sna.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ parameters are:
simulation as soon as that address is reached, regardless of whether the tape
has finished (``0``, the default)
* ``first-edge`` - the time (in T-states) from the start of the tape at which
to place the leading edge of the first pulse (default: ``-2168``); the
default value places the trailing edge of the first pulse at time 0, but some
loaders (e.g. polarity-sensitive loaders) require ``first-edge=0``
to place the leading edge of the first pulse (default: ``-2168``)
* ``load`` - a space-separated list of keys to press to build an alternative
command line to load the tape (see below)
* ``machine`` - the type of machine to simulate: a 48K Spectrum (``48``, the
Expand All @@ -145,6 +143,15 @@ parameters are:
* ``trace`` - the file to which to log all instructions executed during the
simulated LOAD (default: none)

The default value of the ``first-edge`` parameter (-2168) places the edge
between the first and second pulses on the tape at time 0. Any pulses that
occur before time 0 are discarded. The EAR bit reading yielded by a pulse is 0
if the 0-based index of the pulse is even (i.e. first, third, fifth pulses
etc.), or 1 otherwise. Some loaders require ``first-edge=0``, which effectively
reverses the polarity of every pulse on the tape. Run ``tap2sna.py`` with the
``--tape-analysis`` option to see the timings and EAR bit readings of the
pulses on a tape.

The ``accelerator`` parameter must be either a comma-separated list of specific
accelerator names or one of the following special values:

Expand Down
82 changes: 41 additions & 41 deletions tests/test_tap2sna.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,16 +301,16 @@ def test_option_tape_analysis(self):
output, error = self.run_tap2sna(f'--tape-analysis {tapfile}', catch_exit=0)
self.assertEqual(error, '')
exp_output = """
T-states Description
-2168 Tone (8063 x 2168 T-states)
17478416 Pulse (667 T-states)
17479083 Pulse (735 T-states)
17479818 Data (19 bytes; 855/1710 T-states)
17763678 Pause (3500000 T-states)
21263678 Tone (3223 x 2168 T-states)
28251142 Pulse (667 T-states)
28251809 Pulse (735 T-states)
28252544 Data (5 bytes; 855/1710 T-states)
T-states EAR Description
-2168 - Tone (8063 x 2168 T-states)
17478416 0 Pulse (667 T-states)
17479083 1 Pulse (735 T-states)
17479818 0 Data (19 bytes; 855/1710 T-states)
17763678 0 Pause (3500000 T-states)
21263678 0 Tone (3223 x 2168 T-states)
28251142 1 Pulse (667 T-states)
28251809 0 Pulse (735 T-states)
28252544 1 Data (5 bytes; 855/1710 T-states)
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

Expand All @@ -323,11 +323,11 @@ def test_option_tape_analysis_with_tape_start(self):
output, error = self.run_tap2sna(f'--tape-analysis --tape-start 2 {tapfile}', catch_exit=0)
self.assertEqual(error, '')
exp_output = """
T-states Description
-2168 Tone (3223 x 2168 T-states)
6985296 Pulse (667 T-states)
6985963 Pulse (735 T-states)
6986698 Data (5 bytes; 855/1710 T-states)
T-states EAR Description
-2168 - Tone (3223 x 2168 T-states)
6985296 0 Pulse (667 T-states)
6985963 1 Pulse (735 T-states)
6986698 0 Data (5 bytes; 855/1710 T-states)
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

Expand All @@ -340,11 +340,11 @@ def test_option_tape_analysis_with_tape_stop(self):
output, error = self.run_tap2sna(f'--tape-analysis --tape-stop 2 {tapfile}', catch_exit=0)
self.assertEqual(error, '')
exp_output = """
T-states Description
-2168 Tone (8063 x 2168 T-states)
17478416 Pulse (667 T-states)
17479083 Pulse (735 T-states)
17479818 Data (19 bytes; 855/1710 T-states)
T-states EAR Description
-2168 - Tone (8063 x 2168 T-states)
17478416 0 Pulse (667 T-states)
17479083 1 Pulse (735 T-states)
17479818 0 Data (19 bytes; 855/1710 T-states)
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

Expand All @@ -357,16 +357,16 @@ def test_option_tape_analysis_with_first_edge(self):
output, error = self.run_tap2sna(f'--tape-analysis -c first-edge=0 {tapfile}', catch_exit=0)
self.assertEqual(error, '')
exp_output = """
T-states Description
0 Tone (8063 x 2168 T-states)
17480584 Pulse (667 T-states)
17481251 Pulse (735 T-states)
17481986 Data (19 bytes; 855/1710 T-states)
17765846 Pause (3500000 T-states)
21265846 Tone (3223 x 2168 T-states)
28253310 Pulse (667 T-states)
28253977 Pulse (735 T-states)
28254712 Data (5 bytes; 855/1710 T-states)
T-states EAR Description
0 0 Tone (8063 x 2168 T-states)
17480584 1 Pulse (667 T-states)
17481251 0 Pulse (735 T-states)
17481986 1 Data (19 bytes; 855/1710 T-states)
17765846 1 Pause (3500000 T-states)
21265846 1 Tone (3223 x 2168 T-states)
28253310 0 Pulse (667 T-states)
28253977 1 Pulse (735 T-states)
28254712 0 Data (5 bytes; 855/1710 T-states)
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

Expand All @@ -377,11 +377,11 @@ def test_option_tape_analysis_with_unused_bits_in_last_byte(self):
output, error = self.run_tap2sna(f'--tape-analysis {tapfile}', catch_exit=0)
self.assertEqual(error, '')
exp_output = """
T-states Description
-2168 Tone (3223 x 2168 T-states)
6985296 Pulse (667 T-states)
6985963 Pulse (735 T-states)
6986698 Data (5 bytes + 4 bits; 855/1710 T-states)
T-states EAR Description
-2168 - Tone (3223 x 2168 T-states)
6985296 0 Pulse (667 T-states)
6985963 1 Pulse (735 T-states)
6986698 0 Data (5 bytes + 4 bits; 855/1710 T-states)
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

Expand All @@ -395,12 +395,12 @@ def test_option_tape_analysis_with_pure_tone_and_pause_and_pulse_sequence_and_pu
output, error = self.run_tap2sna(f'--tape-analysis {tapfile}', catch_exit=0)
self.assertEqual(error, '')
exp_output = """
T-states Description
-2168 Tone (2000 x 1100 T-states)
2197832 Pause (3500 T-states)
2201332 Pulse (256 T-states)
2201588 Pulse (512 T-states)
2202100 Data (4 bytes; 500/1000 T-states)
T-states EAR Description
-2168 - Tone (2000 x 1100 T-states)
2197832 0 Pause (3500 T-states)
2201332 0 Pulse (256 T-states)
2201588 1 Pulse (512 T-states)
2202100 0 Data (4 bytes; 500/1000 T-states)
"""
self.assertEqual(dedent(exp_output).lstrip(), output)

Expand Down

0 comments on commit c0d6745

Please sign in to comment.