diff --git a/.gitignore b/.gitignore index 885ecb54..d84e3249 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ host_usb_mixer_control/xmos_mixer **.egg-info *tests/logs/* midi_tx_cmds.txt +midi_rx_cmds.txt diff --git a/tests/midi_test_helpers.py b/tests/midi_test_helpers.py index 5bf8b4f5..d9852d8a 100644 --- a/tests/midi_test_helpers.py +++ b/tests/midi_test_helpers.py @@ -1,7 +1,7 @@ # Copyright 2024 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. -class Midi_expect: +class midi_expect_tx: def __init(self): pass @@ -14,11 +14,33 @@ class Midi_expect: return expected +class midi_expect_rx: + def __init(self): + pass -def create_midi_tx_file(commands): - with open("midi_tx_cmds.txt", "wt") as mt: + def expect(self, commands): + expected = "" + for command in commands: + while len(command) < 3: + command.append(0) + expected += "dut_midi_rx: " + " ".join([f"{byte}" for byte in command]) + "\n" + + return expected + +midi_tx_file = "midi_tx_cmds.txt" +midi_rx_file = "midi_rx_cmds.txt" + +def create_midi_tx_file(commands=None): + with open(midi_tx_file, "wt") as mt: + if commands is None: + return for command in commands: while len(command) < 3: command.append(0) text = " ".join([str(byte) for byte in command]) + "\n" mt.write(text) + +def create_midi_rx_file(num_commands=0): + with open(midi_rx_file, "wt") as mr: + text = f"{num_commands}\n" + mr.write(text) diff --git a/tests/test_midi/src/app_midi_simple.xc b/tests/test_midi/src/app_midi_simple.xc index 71f11ce8..5f86f1cd 100644 --- a/tests/test_midi/src/app_midi_simple.xc +++ b/tests/test_midi/src/app_midi_simple.xc @@ -36,10 +36,12 @@ on tile[MIDI_TILE] : clock clk_midi = CLKBLK_MIDI; #define TEST_COMMAND_FILE_TX "midi_tx_cmds.txt" #define TEST_COMMAND_FILE_RX "midi_rx_cmds.txt" -#ifndef DEBUG -#define dprintf(...) -#else +#define DEBUG 0 + +#if DEBUG #define dprintf(...) printf(__VA_ARGS__) +#else +#define dprintf(...) #endif /* See hwsupport.xc */ @@ -134,8 +136,9 @@ void test(chanend c_midi){ } else { unsigned midi_data[3] = {0}; unsigned byte_count = 0; - {midi_data[0], midi_data[1], midi_data[2], byte_count} = midi_out_parse(rx_packet); - dprintf("dut_midi_rx: %u %u %u\n", midi_data[0], midi_data[1], midi_data[2]); + {midi_data[0], midi_data[1], midi_data[2], byte_count} = midi_out_parse(byterev(rx_packet)); + // Note this needs to always print for capff to pick it up + printf("dut_midi_rx: %u %u %u\n", midi_data[0], midi_data[1], midi_data[2]); rx_cmd_count++; } break; @@ -143,7 +146,7 @@ void test(chanend c_midi){ case tx_cmd_count < num_to_tx => tmr when timerafter(t_tx) :> int _: unsigned midi[] = {commands[tx_cmd_count][0], commands[tx_cmd_count][1], commands[tx_cmd_count][2]}; unsigned tx_packet = mini_in_parse_helper(midi); - outuint(c_midi, byterev(tx_packet)); + outuint(c_midi, byterev(tx_packet)); dprintf("Sent packet to midi: %u %u %u\n", commands[tx_cmd_count][0], commands[tx_cmd_count][1], commands[tx_cmd_count][2]); t_tx += max_tx_time; break; diff --git a/tests/test_midi_rx.py b/tests/test_midi_rx.py new file mode 100644 index 00000000..c87000c2 --- /dev/null +++ b/tests/test_midi_rx.py @@ -0,0 +1,71 @@ +# Copyright 2014-2024 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. + +import pytest +import Pyxsim +from Pyxsim import testers +from pathlib import Path +from uart_rx_checker import UARTRxChecker +from midi_test_helpers import midi_expect_rx, create_midi_rx_file, create_midi_tx_file + +MAX_CYCLES = 15000000 +MIDI_RATE = 31250 +CONFIGS = ["xs2", "xs3"] +CONFIGS = ["xs3"] + + +##### +# This test builds the spdif transmitter app with a verity of presets and tests that the output matches those presets +##### +@pytest.mark.parametrize("config", CONFIGS) +def test_rx(capfd, config): + xe = str(Path(__file__).parent / f"test_midi/bin/{config}/test_midi_{config}.xe") + + midi_commands = [[0x90, 60, 81]] + create_midi_rx_file(1) + create_midi_tx_file() + + + tester = testers.ComparisonTester(midi_expect_rx().expect(midi_commands), + regexp = "uart_tx_checker:.+", + ordered = True) + + rx_port = "tile[1]:XS1_PORT_1F" + tx_port = "tile[1]:XS1_PORT_4C" # Needed so that UARTRxChecker (a transmitter) knows when to start + baud = MIDI_RATE + bpb = 8 + parity = 0 + stop = 1 + + midi_commands_flattened = [item for row in midi_commands for item in row] + # midi_commands_flattened.append(0x00) # send a null afterwards to give RXChecker to complete + + simthreads = [ + UARTRxChecker(tx_port, rx_port, parity, baud, stop, bpb, midi_commands_flattened, debug=False) + ] + + simargs = ["--max-cycles", str(MAX_CYCLES)] + simargs.extend(["--trace-to", "trace.txt", "--vcd-tracing", "-tile tile[1] -ports -o trace.vcd"]) #This is just for local debug so we can capture the run, pass as kwarg to run_with_pyxsim + + # result = Pyxsim.run_on_simulator( + result = Pyxsim.run_on_simulator( + xe, + simthreads=simthreads, + instTracing=True, + # clean_before_build=True, + clean_before_build=False, + tester=tester, + capfd=capfd, + # capfd=None, + timeout=120, + simargs=simargs, + build_options=[ + "-j", + f"CONFIG={config}", + "EXTRA_BUILD_FLAGS=" + + f" -DMIDI_RATE_HZ={MIDI_RATE}" + , + ], + ) + + assert result \ No newline at end of file diff --git a/tests/test_midi_tx.py b/tests/test_midi_tx.py index 7f3aa12b..9b7aa842 100644 --- a/tests/test_midi_tx.py +++ b/tests/test_midi_tx.py @@ -6,7 +6,7 @@ import Pyxsim from Pyxsim import testers from pathlib import Path from uart_tx_checker import UARTTxChecker - +from midi_test_helpers import midi_expect_tx, create_midi_tx_file MAX_CYCLES = 15000000 MIDI_RATE = 31250 @@ -14,28 +14,6 @@ CONFIGS = ["xs2", "xs3"] CONFIGS = ["xs3"] -class Midi_expect: - def __init(self): - pass - - def expect(self, commands): - expected = "" - for command in commands: - while len(command) < 3: - command.append(0) - expected += "uart_tx_checker: " + " ".join([f"0x{byte:02x}" for byte in command]) + "\n" - - return expected - - -def create_midi_tx_file(commands): - with open("midi_tx_cmds.txt", "wt") as mt: - for command in commands: - while len(command) < 3: - command.append(0) - text = " ".join([str(byte) for byte in command]) + "\n" - mt.write(text) - ##### # This test builds the spdif transmitter app with a verity of presets and tests that the output matches those presets ##### @@ -46,7 +24,7 @@ def test_tx(capfd, config): midi_commands = [[0x90, 60, 81]] create_midi_tx_file(midi_commands) - tester = testers.ComparisonTester(Midi_expect().expect(midi_commands), + tester = testers.ComparisonTester(midi_expect_tx().expect(midi_commands), regexp = "uart_tx_checker:.+", ordered = True) diff --git a/tests/uart_rx_checker.py b/tests/uart_rx_checker.py index c313ae5b..79f57f27 100644 --- a/tests/uart_rx_checker.py +++ b/tests/uart_rx_checker.py @@ -30,7 +30,7 @@ class DriveHigh(px.SimThread): class UARTRxChecker(px.SimThread): - def __init__(self, rx_port, parity, baud, stop_bits, bpb, data=[0x7f, 0x00, 0x2f, 0xff], + def __init__(self, tx_port, rx_port, parity, baud, stop_bits, bpb, data=[0x7f, 0x00, 0x2f, 0xff], intermittent=False, debug=False): """ Create a UARTRxChecker instance. @@ -43,6 +43,7 @@ class UARTRxChecker(px.SimThread): :param data: A list of bytes to send (default: [0x7f, 0x00, 0x2f, 0xff]) :param intermittent: Add a random delay between sent bytes. """ + self._tx_port = tx_port self._rx_port = rx_port self._parity = parity self._baud = baud @@ -88,11 +89,11 @@ class UARTRxChecker(px.SimThread): :param xsi: XMOS Simulator Instance. :param byte: Data to send. """ - # print "0x%02x:" % byte + # print(f"Checker sent 0x{byte:02x}") for x in range(self._bits_per_byte): - # print " Sending bit %d of 0x%02x (%d)" % (x, byte, (byte >> x) & 0x01) + # print(f" Sending bit {x}") xsi.drive_port_pins(self._rx_port, (byte & (0x01 << x)) >= 1) - # print " (x): %d" % ((byte & (0x01 << x))>=1) + # print(f" (x): {((byte & (0x01 << x))>=1)}") self.wait_baud_time(xsi) def send_parity(self, xsi, byte):