This commit is contained in:
kris
2022-07-02 10:58:38 +01:00
parent 622583696d
commit 2016e4a5f1

View File

@@ -3,6 +3,7 @@ import numpy
from typing import Iterable, List, Tuple, Dict from typing import Iterable, List, Tuple, Dict
import opcodes_6502 import opcodes_6502
import player_op
def audio_opcodes() -> Iterable[Tuple[opcodes_6502.Opcode]]: def audio_opcodes() -> Iterable[Tuple[opcodes_6502.Opcode]]:
@@ -202,7 +203,7 @@ def eof_trampoline_stage3_page_offsets(duty_cycles):
for a, b in sorted(duty_cycles): for a, b in sorted(duty_cycles):
second_cycles.setdefault(a, []).append(b) second_cycles.setdefault(a, []).append(b)
# bin-pack the (a, b) duty cycles into pages so we can set up indirect # bin-pack the (a, b) duty cycles into pages so that we can set up indirect
# jump tables to dispatch the third stage trampoline. A greedy algorithm # jump tables to dispatch the third stage trampoline. A greedy algorithm
# works fine here # works fine here
pages = [] pages = []
@@ -234,7 +235,6 @@ def eof_trampoline_stage3_page_offsets(duty_cycles):
EOF_TRAMPOLINE_STAGE3_PAGE_OFFSETS = eof_trampoline_stage3_page_offsets( EOF_TRAMPOLINE_STAGE3_PAGE_OFFSETS = eof_trampoline_stage3_page_offsets(
EOF_DUTY_CYCLES) EOF_DUTY_CYCLES)
print(EOF_TRAMPOLINE_STAGE3_PAGE_OFFSETS)
EOF_STAGE_3_BASE = [ EOF_STAGE_3_BASE = [
opcodes_6502.Literal( opcodes_6502.Literal(
@@ -265,13 +265,13 @@ EOF_STAGE_3_BASE = [
opcodes_6502.Opcode(4, 3, "STA WADRH"), opcodes_6502.Opcode(4, 3, "STA WADRH"),
opcodes_6502.Opcode(2, 2, "LDA #<S0RXRD"), opcodes_6502.Opcode(2, 2, "LDA #<S0RXRD"),
opcodes_6502.Opcode(4, 3, "STA WADRL"), opcodes_6502.Opcode(4, 3, "STA WADRL"),
opcodes_6502.Opcode(4, 3, opcodes_6502.Opcode(
"LDA RXRD ; TODO: in principle we could update RXRD outside of " 4, 3, "LDA RXRD ; TODO: in principle we could update RXRD outside of "
"the EOF path"), "the EOF path"),
opcodes_6502.Opcode(2, 1, "CLC"), opcodes_6502.Opcode(2, 1, "CLC"),
opcodes_6502.Opcode(2, 2, "ADC #$08"), opcodes_6502.Opcode(2, 2, "ADC #$08"),
opcodes_6502.Opcode(4, 3, opcodes_6502.Opcode(
"STA WDATA ; Store new high byte of received read pointer"), 4, 3, "STA WDATA ; Store new high byte of received read pointer"),
opcodes_6502.Opcode(4, 3, "STA RXRD ; Save for next time"), opcodes_6502.Opcode(4, 3, "STA RXRD ; Save for next time"),
opcodes_6502.Literal("; Send the Receive command"), opcodes_6502.Literal("; Send the Receive command"),
opcodes_6502.Opcode(2, 2, "LDA #<S0CR"), opcodes_6502.Opcode(2, 2, "LDA #<S0CR"),
@@ -292,7 +292,8 @@ EOF_STAGE_3_BASE = [
opcodes_6502.Literal("@0:", indent=0), opcodes_6502.Literal("@0:", indent=0),
opcodes_6502.Opcode(4, 3, "STX WADRL"), opcodes_6502.Opcode(4, 3, "STX WADRL"),
opcodes_6502.Opcode(4, 3, "CMP WDATA ; High byte of received size"), opcodes_6502.Opcode(4, 3, "CMP WDATA ; High byte of received size"),
opcodes_6502.Opcode(2, 2, opcodes_6502.Opcode(
2, 2,
"BCS @0 ; 2 cycles in common case when there is already sufficient " "BCS @0 ; 2 cycles in common case when there is already sufficient "
"data waiting."), "data waiting."),
opcodes_6502.Literal( opcodes_6502.Literal(
@@ -315,39 +316,17 @@ EOF_STAGE_3_BASE = [
] ]
def _make_end_of_frame_voltages2(cycles) -> numpy.ndarray:
"""Voltage sequence for end-of-frame TCP processing."""
max_len = 140
voltage_high = False
c = [1.0, 1.0, 1.0, -1.0] # STA $C030
for i, skip_cycles in enumerate(itertools.cycle(cycles)):
c.extend([1.0 if voltage_high else -1.0] * (skip_cycles - 1))
voltage_high = not voltage_high
c.append(1.0 if voltage_high else -1.0)
if len(c) >= max_len:
break
c.extend([1.0 if voltage_high else -1.0] * 6) # JMP (WDATA)
return numpy.array(c, dtype=numpy.float32)
import player_op
def generate_player( def generate_player(
opcode_filename: str, opcode_filename: str,
player_stage1_filename: str, player_stage1_filename: str,
player_stage2_filename: str player_stage2_filename: str
): ):
toggles = {} # Generate assembly code for page 3 operations
# Write out page 3 operations
with open(player_stage1_filename, "w+") as f: with open(player_stage1_filename, "w+") as f:
# Audio operations # Audio operations
audio_player_ops: Dict[str, player_op.PlayerOp] = {}
page_3_offset = 0 page_3_offset = 0
seen_op_suffix_toggles = set() seen_op_suffix_toggles = set()
audio_player_ops: Dict[str, player_op.PlayerOp] = {}
for i, ops in enumerate(audio_opcodes()): for i, ops in enumerate(audio_opcodes()):
player_ops = [] player_ops = []
# Generate unique entrypoints # Generate unique entrypoints
@@ -374,7 +353,6 @@ def generate_player(
# stage 1 EOF trampoline operations # stage 1 EOF trampoline operations
duty_cycle_first = sorted(list(set(dc[0] for dc in EOF_DUTY_CYCLES))) duty_cycle_first = sorted(list(set(dc[0] for dc in EOF_DUTY_CYCLES)))
stage_1_ops: Dict[str, player_op.PlayerOp] = {} stage_1_ops: Dict[str, player_op.PlayerOp] = {}
# stage_1_offsets = {}
for eof_stage1_cycles in duty_cycle_first: for eof_stage1_cycles in duty_cycle_first:
eof_stage1_ops = EOF_TRAMPOLINE_STAGE1[eof_stage1_cycles] eof_stage1_ops = EOF_TRAMPOLINE_STAGE1[eof_stage1_cycles]
if not eof_stage1_ops: if not eof_stage1_ops:
@@ -384,7 +362,6 @@ def generate_player(
f.write("%s\n" % str(op)) f.write("%s\n" % str(op))
f.write("\n") f.write("\n")
# stage_1_offsets[eof_stage1_cycles] = page_3_offset
op_name = "END_OF_FRAME_%d_STAGE1" % eof_stage1_cycles op_name = "END_OF_FRAME_%d_STAGE1" % eof_stage1_cycles
stage_1_ops[op_name] = player_op.PlayerOp( stage_1_ops[op_name] = player_op.PlayerOp(
byte=page_3_offset, byte=page_3_offset,
@@ -395,9 +372,10 @@ def generate_player(
assert page_3_offset < 256 assert page_3_offset < 256
f.write("; %d bytes\n" % page_3_offset) f.write("; %d bytes\n" % page_3_offset)
# Write out stage 2 EOF trampoline operations # Generate assembly code for stage 2 and 3 EOF operations
with open(player_stage2_filename, "w+") as f: with open(player_stage2_filename, "w+") as f:
# Stage 2 EOF operations
stage_2_3_ops: Dict[str, player_op.PlayerOp] = {} stage_2_3_ops: Dict[str, player_op.PlayerOp] = {}
for eof_stage1_cycles in duty_cycle_first: for eof_stage1_cycles in duty_cycle_first:
eof_stage2_ops = EOF_TRAMPOLINE_STAGE2[eof_stage1_cycles] eof_stage2_ops = EOF_TRAMPOLINE_STAGE2[eof_stage1_cycles]
@@ -408,6 +386,7 @@ def generate_player(
f.write("%s\n" % str(op)) f.write("%s\n" % str(op))
f.write("\n") f.write("\n")
# Stage 3 EOF operations
for a, b in EOF_DUTY_CYCLES: for a, b in EOF_DUTY_CYCLES:
# XXX compute deficit for first iteration # XXX compute deficit for first iteration
stage_3_tick_ops = itertools.cycle( stage_3_tick_ops = itertools.cycle(
@@ -442,13 +421,9 @@ def generate_player(
# eof_trampoline_7_stage3_page: # eof_trampoline_7_stage3_page:
# ; ... # ; ...
# Generated python code for player operations
with open(opcode_filename, "w") as f: with open(opcode_filename, "w") as f:
f.write("""import numpy f.write("import numpy\nimport player_op\n\n\nclass PlayerOps:\n")
import player_op
class PlayerOps:
""")
for name, op in audio_player_ops.items(): for name, op in audio_player_ops.items():
f.write(" %s = player_op.%s\n" % (name, op.define_self())) f.write(" %s = player_op.%s\n" % (name, op.define_self()))
@@ -476,6 +451,7 @@ class PlayerOps:
# TODO: count toggles # TODO: count toggles
def main(): def main():
generate_player( generate_player(
opcode_filename="opcodes_generated.py", opcode_filename="opcodes_generated.py",