i2s: Add functionality for a loopback sanity test This simply makes the peripheral initiate record and playback at the same time, while also shoveling bytes between both FIFOs to write to disk. In essence, this does a round-trip through the peripheral code, and should produce a 1:1 matching output on disk from the input file. Unfortunately, there's no easy way to detect when the recording audio data has run out, so it's on the user to stop it by disabling the loopback bit in the control register. In short, to run this sanity check, do the following: 1. Set the input and output files in the Renode configuration script. 2. Start the simulation 3. Telnet to the Renode console 4. Run `i2s0 WriteDoubleWord 0x0c 4` 5. Wait a while. 6. Run `i2s0 WriteDoubleWord 0x0c 0` or quit Renode. At this point, the output file should contain the same data as what was in the input file. Since we can't determine when the file is out of bytes to read, it may end up zero padded. Change-Id: I79eb3f017cea3dc415305372e5670789eb329266
diff --git a/shodan_infrastructure/MatchaI2S.cs b/shodan_infrastructure/MatchaI2S.cs index bee1cbf..3031755 100644 --- a/shodan_infrastructure/MatchaI2S.cs +++ b/shodan_infrastructure/MatchaI2S.cs
@@ -219,6 +219,13 @@ txThread.Start(); } + private void StartLoopback() + { + this.Log(LogLevel.Info, "Starting loopback."); + loopbackThread = machine.ObtainManagedThread(LoopbackFrame, SampleFrequencyHz); + loopbackThread.Start(); + } + private void StopThread(ref IManagedThread thread) { thread?.Stop(); @@ -282,6 +289,14 @@ } } + private void LoopbackFrame() + { + if ((rxBuffer.Count >= 0) && (txBuffer.Count <= 1)) { + ulong sample = rxBuffer.Read(); + txBuffer.Write(sample); + } + } + private void CreateRegisters() { Registers.IrqState.Define(this) @@ -323,7 +338,18 @@ StopThread(ref rxThread); } }) - .WithFlag(2, out loopbackEnable, name: "SLPBK") + .WithFlag(2, out loopbackEnable, name: "SLPBK", + writeCallback: (_, val) => { + if (val) { + StartRx(); + StartTx(); + StartLoopback(); + } else { + StopThread(ref rxThread); + StopThread(ref txThread); + StopThread(ref loopbackThread); + } + }) .WithReservedBits(3, 15) .WithValueField(18, 6, out rxClkDivide, name: "NCO_RX") .WithValueField(25, 6, out txClkDivide, name: "NCO_TX"); @@ -426,6 +452,7 @@ private IManagedThread rxThread; private IManagedThread txThread; + private IManagedThread loopbackThread; private PCMDecoder decoder; private PCMEncoder encoder;