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;